layout.vue 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. <script setup lang="ts">
  2. import type { LayoutType } from '@vben/types';
  3. import { MdiQuestionMarkCircleOutline } from '@vben-core/iconify';
  4. import { VbenTooltip } from '@vben-core/shadcn-ui';
  5. import { $t } from '@vben/locales';
  6. import { type Component, computed } from 'vue';
  7. import {
  8. FullContent,
  9. HeaderNav,
  10. MixedNav,
  11. SideMixedNav,
  12. SideNav,
  13. } from '../../icons';
  14. interface PresetItem {
  15. name: string;
  16. tip: string;
  17. type: LayoutType;
  18. }
  19. defineOptions({
  20. name: 'PreferenceLayout',
  21. });
  22. const modelValue = defineModel<LayoutType>({ default: 'side-nav' });
  23. const components: Record<LayoutType, Component> = {
  24. 'full-content': FullContent,
  25. 'header-nav': HeaderNav,
  26. 'mixed-nav': MixedNav,
  27. 'side-mixed-nav': SideMixedNav,
  28. 'side-nav': SideNav,
  29. };
  30. const PRESET = computed((): PresetItem[] => [
  31. {
  32. name: $t('preference.vertical'),
  33. tip: $t('preference.vertical-tip'),
  34. type: 'side-nav',
  35. },
  36. {
  37. name: $t('preference.two-column'),
  38. tip: $t('preference.two-column-tip'),
  39. type: 'side-mixed-nav',
  40. },
  41. {
  42. name: $t('preference.horizontal'),
  43. tip: $t('preference.vertical-tip'),
  44. type: 'header-nav',
  45. },
  46. {
  47. name: $t('preference.mixed-menu'),
  48. tip: $t('preference.mixed-menu-tip'),
  49. type: 'mixed-nav',
  50. },
  51. {
  52. name: $t('preference.full-content'),
  53. tip: $t('preference.full-content-tip'),
  54. type: 'full-content',
  55. },
  56. ]);
  57. function activeClass(theme: string): string[] {
  58. return theme === modelValue.value ? ['outline-box-active'] : [];
  59. }
  60. </script>
  61. <template>
  62. <div class="flex w-full flex-wrap gap-5">
  63. <template v-for="theme in PRESET" :key="theme.name">
  64. <div
  65. class="flex w-[100px] cursor-pointer flex-col"
  66. @click="modelValue = theme.type"
  67. >
  68. <div :class="activeClass(theme.type)" class="outline-box flex-center">
  69. <component :is="components[theme.type]" />
  70. </div>
  71. <div
  72. class="text-muted-foreground flex-center hover:text-foreground mt-2 text-center text-xs"
  73. >
  74. {{ theme.name }}
  75. <VbenTooltip v-if="theme.tip" side="bottom">
  76. <template #trigger>
  77. <MdiQuestionMarkCircleOutline class="ml-1 cursor-help" />
  78. </template>
  79. {{ theme.tip }}
  80. </VbenTooltip>
  81. </div>
  82. </div>
  83. </template>
  84. </div>
  85. </template>