| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- <script lang="ts" setup>
- import { computed, useSlots } from 'vue';
- import { useRefresh } from '@vben/hooks';
- import { RotateCw } from '@vben/icons';
- import { preferences, usePreferences } from '@vben/preferences';
- import { useAccessStore } from '@vben/stores';
- import { VbenFullScreen, VbenIconButton } from '@vben-core/shadcn-ui';
- import {
- GlobalSearch,
- LanguageToggle,
- PreferencesButton,
- ThemeToggle,
- TimezoneButton,
- } from '../../widgets';
- interface Props {
- /**
- * Logo 主题
- */
- theme?: string;
- }
- defineOptions({
- name: 'LayoutHeader',
- });
- withDefaults(defineProps<Props>(), {
- theme: 'light',
- });
- const emit = defineEmits<{ clearPreferencesAndLogout: [] }>();
- const REFERENCE_VALUE = 50;
- const accessStore = useAccessStore();
- const { globalSearchShortcutKey, preferencesButtonPosition } = usePreferences();
- const slots = useSlots();
- const { refresh } = useRefresh();
- const rightSlots = computed(() => {
- const list = [{ index: REFERENCE_VALUE + 100, name: 'user-dropdown' }];
- if (preferences.widget.globalSearch) {
- list.push({
- index: REFERENCE_VALUE,
- name: 'global-search',
- });
- }
- if (preferencesButtonPosition.value.header) {
- list.push({
- index: REFERENCE_VALUE + 10,
- name: 'preferences',
- });
- }
- if (preferences.widget.themeToggle) {
- list.push({
- index: REFERENCE_VALUE + 20,
- name: 'theme-toggle',
- });
- }
- if (preferences.widget.languageToggle) {
- list.push({
- index: REFERENCE_VALUE + 30,
- name: 'language-toggle',
- });
- }
- if (preferences.widget.timezone) {
- list.push({
- index: REFERENCE_VALUE + 40,
- name: 'timezone',
- });
- }
- if (preferences.widget.fullscreen) {
- list.push({
- index: REFERENCE_VALUE + 50,
- name: 'fullscreen',
- });
- }
- if (preferences.widget.notification) {
- list.push({
- index: REFERENCE_VALUE + 60,
- name: 'notification',
- });
- }
- Object.keys(slots).forEach((key) => {
- const name = key.split('-');
- if (key.startsWith('header-right')) {
- list.push({ index: Number(name[2]), name: key });
- }
- });
- return list.sort((a, b) => a.index - b.index);
- });
- const leftSlots = computed(() => {
- const list: Array<{ index: number; name: string }> = [];
- if (preferences.widget.refresh) {
- list.push({
- index: 0,
- name: 'refresh',
- });
- }
- Object.keys(slots).forEach((key) => {
- const name = key.split('-');
- if (key.startsWith('header-left')) {
- list.push({ index: Number(name[2]), name: key });
- }
- });
- return list.sort((a, b) => a.index - b.index);
- });
- function clearPreferencesAndLogout() {
- emit('clearPreferencesAndLogout');
- }
- </script>
- <template>
- <template
- v-for="slot in leftSlots.filter((item) => item.index < REFERENCE_VALUE)"
- :key="slot.name"
- >
- <slot :name="slot.name">
- <template v-if="slot.name === 'refresh'">
- <VbenIconButton class="my-0 mr-1 rounded-md" @click="refresh">
- <RotateCw class="size-4" />
- </VbenIconButton>
- </template>
- </slot>
- </template>
- <div class="flex-center hidden lg:block">
- <slot name="breadcrumb"></slot>
- </div>
- <template
- v-for="slot in leftSlots.filter((item) => item.index > REFERENCE_VALUE)"
- :key="slot.name"
- >
- <slot :name="slot.name"></slot>
- </template>
- <div
- :class="`menu-align-${preferences.header.menuAlign}`"
- class="flex h-full min-w-0 flex-1 items-center"
- >
- <slot name="menu"></slot>
- </div>
- <div class="flex h-full min-w-0 flex-shrink-0 items-center">
- <template v-for="slot in rightSlots" :key="slot.name">
- <slot :name="slot.name">
- <template v-if="slot.name === 'global-search'">
- <GlobalSearch
- :enable-shortcut-key="globalSearchShortcutKey"
- :menus="accessStore.accessMenus"
- class="mr-1 sm:mr-4"
- />
- </template>
- <template v-else-if="slot.name === 'preferences'">
- <PreferencesButton
- class="mr-1"
- @clear-preferences-and-logout="clearPreferencesAndLogout"
- />
- </template>
- <template v-else-if="slot.name === 'theme-toggle'">
- <ThemeToggle class="mr-1 mt-[2px]" />
- </template>
- <template v-else-if="slot.name === 'language-toggle'">
- <LanguageToggle class="mr-1" />
- </template>
- <template v-else-if="slot.name === 'fullscreen'">
- <VbenFullScreen class="mr-1" />
- </template>
- <template v-else-if="slot.name === 'timezone'">
- <TimezoneButton class="mr-1 mt-[2px]" />
- </template>
- </slot>
- </template>
- </div>
- </template>
- <style lang="scss" scoped>
- .menu-align-start {
- --menu-align: start;
- }
- .menu-align-center {
- --menu-align: center;
- }
- .menu-align-end {
- --menu-align: end;
- }
- </style>
|