refactor: adjust layout refresh button and watermark; allow static i18n on language switch (#4579)

* refactor: adjust layout refresh button and watermark; allow static i18n on language switch

* chore: typo
This commit is contained in:
Vben
2024-10-06 17:27:32 +08:00
committed by GitHub
parent 324cdd8259
commit 60c615ce8a
25 changed files with 142 additions and 125 deletions

View File

@@ -3,5 +3,5 @@
### header
- 支持N个自定义插槽命名方式header-right-nheader-left-n
- header-left-n ,排序方式:1-4 ,breadcrumb6-x
- header-right-n ,排序方式:1-4global-search6-9theme-toggle11-14language-toggle16-19fullscreen21-24notification26-29user-dropdown30-x
- header-left-n ,排序方式:0-19 ,breadcrumb 21-x
- header-right-n ,排序方式:0-49global-search51-59theme-toggle61-69language-toggle71-79fullscreen81-89notification91-149user-dropdown151-x

View File

@@ -1,9 +1,11 @@
<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 } from '@vben-core/shadcn-ui';
import { VbenFullScreen, VbenIconButton } from '@vben-core/shadcn-ui';
import {
GlobalSearch,
@@ -29,45 +31,49 @@ withDefaults(defineProps<Props>(), {
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: 100, name: 'user-dropdown' }];
const list = [{ index: REFERENCE_VALUE + 100, name: 'user-dropdown' }];
if (preferences.widget.globalSearch) {
list.push({
index: 5,
index: REFERENCE_VALUE,
name: 'global-search',
});
}
if (preferencesButtonPosition.value.header) {
list.push({
index: 10,
index: REFERENCE_VALUE + 10,
name: 'preferences',
});
}
if (preferences.widget.themeToggle) {
list.push({
index: 15,
index: REFERENCE_VALUE + 20,
name: 'theme-toggle',
});
}
if (preferences.widget.languageToggle) {
list.push({
index: 20,
index: REFERENCE_VALUE + 30,
name: 'language-toggle',
});
}
if (preferences.widget.fullscreen) {
list.push({
index: 25,
index: REFERENCE_VALUE + 40,
name: 'fullscreen',
});
}
if (preferences.widget.notification) {
list.push({
index: 30,
index: REFERENCE_VALUE + 50,
name: 'notification',
});
}
@@ -82,7 +88,14 @@ const rightSlots = computed(() => {
});
const leftSlots = computed(() => {
const list: any[] = [];
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('-');
@@ -100,16 +113,22 @@ function clearPreferencesAndLogout() {
<template>
<template
v-for="slot in leftSlots.filter((item) => item.index < 5)"
v-for="slot in leftSlots.filter((item) => item.index < REFERENCE_VALUE)"
:key="slot.name"
>
<slot :name="slot.name"></slot>
<slot :name="slot.name">
<template v-if="slot.name === 'refresh'">
<VbenIconButton class="my-0 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 > 5)"
v-for="slot in leftSlots.filter((item) => item.index > REFERENCE_VALUE)"
:key="slot.name"
>
<slot :name="slot.name"></slot>

View File

@@ -3,14 +3,14 @@ import type { MenuRecordRaw } from '@vben/types';
import { computed, useSlots, watch } from 'vue';
import { useWatermark } from '@vben/hooks';
import { useRefresh } from '@vben/hooks';
import { $t } from '@vben/locales';
import {
preferences,
updatePreferences,
usePreferences,
} from '@vben/preferences';
import { useLockStore, useUserStore } from '@vben/stores';
import { useLockStore } from '@vben/stores';
import { deepToRaw, mapTree } from '@vben/utils';
import { VbenAdminLayout } from '@vben-core/layout-ui';
import { Toaster, VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';
@@ -44,9 +44,8 @@ const {
sidebarCollapsed,
theme,
} = usePreferences();
const userStore = useUserStore();
const { updateWatermark } = useWatermark();
const lockStore = useLockStore();
const { refresh } = useRefresh();
const sidebarTheme = computed(() => {
const dark = isDark.value || preferences.theme.semiDarkSidebar;
@@ -129,20 +128,6 @@ function clearPreferencesAndLogout() {
emit('clearPreferencesAndLogout');
}
watch(
() => preferences.app.watermark,
async (val) => {
if (val) {
await updateWatermark({
content: `${userStore.userInfo?.username}`,
});
}
},
{
immediate: true,
},
);
watch(
() => preferences.app.layout,
async (val) => {
@@ -156,6 +141,9 @@ watch(
},
);
// 语言更新后,刷新页面
watch(() => preferences.app.locale, refresh);
const slots = useSlots();
const headerSlots = computed(() => {
return Object.keys(slots).filter((key) => key.startsWith('header-'));
@@ -267,7 +255,6 @@ const headerSlots = computed(() => {
/>
</template>
<template #mixed-menu>
<!-- :collapse="!preferences.sidebar.collapsedShowTitle" -->
<LayoutMixedMenu
:active-path="extraActiveMenu"
:menus="wrapperMenus(headerMenus)"
@@ -308,6 +295,7 @@ const headerSlots = computed(() => {
<template #content>
<LayoutContent />
</template>
<template v-if="preferences.transition.loading" #content-overlay>
<LayoutContentSpinner />
</template>

View File

@@ -5,12 +5,7 @@ import { useRoute } from 'vue-router';
import { useContentMaximize, useTabs } from '@vben/hooks';
import { preferences } from '@vben/preferences';
import { useTabbarStore } from '@vben/stores';
import {
TabsToolMore,
TabsToolRefresh,
TabsToolScreen,
TabsView,
} from '@vben-core/tabs-ui';
import { TabsToolMore, TabsToolScreen, TabsView } from '@vben-core/tabs-ui';
import { useTabbar } from './use-tabbar';
@@ -23,7 +18,7 @@ defineProps<{ showIcon?: boolean; theme?: string }>();
const route = useRoute();
const tabbarStore = useTabbarStore();
const { contentIsMaximize, toggleMaximize } = useContentMaximize();
const { refreshTab, unpinTab } = useTabs();
const { unpinTab } = useTabs();
const {
createContextMenus,
@@ -66,10 +61,6 @@ if (!preferences.tabbar.persist) {
@update:active="handleClick"
/>
<div class="flex-center h-full">
<TabsToolRefresh
v-if="preferences.tabbar.showRefresh"
@refresh="refreshTab"
/>
<TabsToolMore v-if="preferences.tabbar.showMore" :menus="menus" />
<TabsToolScreen
v-if="preferences.tabbar.showMaximize"

View File

@@ -20,7 +20,6 @@ const tabbarPersist = defineModel<boolean>('tabbarPersist');
const tabbarDragable = defineModel<boolean>('tabbarDragable');
const tabbarStyleType = defineModel<string>('tabbarStyleType');
const tabbarShowMore = defineModel<boolean>('tabbarShowMore');
const tabbarShowRefresh = defineModel<boolean>('tabbarShowRefresh');
const tabbarShowMaximize = defineModel<boolean>('tabbarShowMaximize');
const styleItems = computed((): SelectOption[] => [
@@ -60,9 +59,6 @@ const styleItems = computed((): SelectOption[] => [
<SwitchItem v-model="tabbarShowMore" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.showMore') }}
</SwitchItem>
<SwitchItem v-model="tabbarShowRefresh" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.showRefresh') }}
</SwitchItem>
<SwitchItem v-model="tabbarShowMaximize" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.showMaximize') }}
</SwitchItem>

View File

@@ -22,6 +22,7 @@ const widgetLockScreen = defineModel<boolean>('widgetLockScreen');
const appPreferencesButtonPosition = defineModel<string>(
'appPreferencesButtonPosition',
);
const widgetRefresh = defineModel<boolean>('widgetRefresh');
const positionItems = computed((): SelectOption[] => [
{
@@ -61,6 +62,9 @@ const positionItems = computed((): SelectOption[] => [
<SwitchItem v-model="widgetSidebarToggle">
{{ $t('preferences.widget.sidebarToggle') }}
</SwitchItem>
<SwitchItem v-model="widgetRefresh">
{{ $t('preferences.widget.refresh') }}
</SwitchItem>
<SelectItem v-model="appPreferencesButtonPosition" :items="positionItems">
{{ $t('preferences.position.title') }}
</SelectItem>

View File

@@ -100,7 +100,6 @@ const breadcrumbHideOnlyOne = defineModel<boolean>('breadcrumbHideOnlyOne');
const tabbarEnable = defineModel<boolean>('tabbarEnable');
const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
const tabbarShowMore = defineModel<boolean>('tabbarShowMore');
const tabbarShowRefresh = defineModel<boolean>('tabbarShowRefresh');
const tabbarShowMaximize = defineModel<boolean>('tabbarShowMaximize');
const tabbarPersist = defineModel<boolean>('tabbarPersist');
const tabbarDragable = defineModel<boolean>('tabbarDragable');
@@ -145,6 +144,7 @@ const widgetNotification = defineModel<boolean>('widgetNotification');
const widgetThemeToggle = defineModel<boolean>('widgetThemeToggle');
const widgetSidebarToggle = defineModel<boolean>('widgetSidebarToggle');
const widgetLockScreen = defineModel<boolean>('widgetLockScreen');
const widgetRefresh = defineModel<boolean>('widgetRefresh');
const {
diffPreference,
@@ -345,7 +345,6 @@ async function handleReset() {
v-model:tabbar-show-icon="tabbarShowIcon"
v-model:tabbar-show-maximize="tabbarShowMaximize"
v-model:tabbar-show-more="tabbarShowMore"
v-model:tabbar-show-refresh="tabbarShowRefresh"
v-model:tabbar-style-type="tabbarStyleType"
/>
</Block>
@@ -359,6 +358,7 @@ async function handleReset() {
v-model:widget-language-toggle="widgetLanguageToggle"
v-model:widget-lock-screen="widgetLockScreen"
v-model:widget-notification="widgetNotification"
v-model:widget-refresh="widgetRefresh"
v-model:widget-sidebar-toggle="widgetSidebarToggle"
v-model:widget-theme-toggle="widgetThemeToggle"
/>