Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin
This commit is contained in:
commit
5720279063
@ -1,9 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted } from 'vue';
|
||||
import { computed, onMounted, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
||||
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
||||
import { useWatermark } from '@vben/hooks';
|
||||
import { BookOpenText, CircleHelp, MdiGithub, ProfileIcon } from '@vben/icons';
|
||||
import {
|
||||
BasicLayout,
|
||||
@ -28,6 +29,7 @@ const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
const accessStore = useAccessStore();
|
||||
const router = useRouter();
|
||||
const { destroyWatermark, updateWatermark } = useWatermark();
|
||||
|
||||
const tenantStore = useTenantStore();
|
||||
const menus = computed(() => {
|
||||
@ -91,6 +93,21 @@ onMounted(() => notifyStore.startListeningMessage());
|
||||
function handleViewAll() {
|
||||
message.warning('暂未开放');
|
||||
}
|
||||
watch(
|
||||
() => preferences.app.watermark,
|
||||
async (enable) => {
|
||||
if (enable) {
|
||||
await updateWatermark({
|
||||
content: `${userStore.userInfo?.username}`,
|
||||
});
|
||||
} else {
|
||||
destroyWatermark();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -34,9 +34,7 @@ function setupCommonGuard(router: Router) {
|
||||
router.afterEach((to) => {
|
||||
// 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
|
||||
|
||||
if (preferences.tabbar.enable) {
|
||||
loadedPaths.add(to.path);
|
||||
}
|
||||
loadedPaths.add(to.path);
|
||||
|
||||
// 关闭页面加载进度条
|
||||
if (preferences.transition.progress) {
|
||||
|
@ -1,10 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { NotificationItem } from '@vben/layouts';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
||||
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
||||
import { useWatermark } from '@vben/hooks';
|
||||
import { BookOpenText, CircleHelp, MdiGithub } from '@vben/icons';
|
||||
import {
|
||||
BasicLayout,
|
||||
@ -54,6 +55,7 @@ const notifications = ref<NotificationItem[]>([
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
const accessStore = useAccessStore();
|
||||
const { destroyWatermark, updateWatermark } = useWatermark();
|
||||
const showDot = computed(() =>
|
||||
notifications.value.some((item) => !item.isRead),
|
||||
);
|
||||
@ -103,6 +105,21 @@ function handleNoticeClear() {
|
||||
function handleMakeAll() {
|
||||
notifications.value.forEach((item) => (item.isRead = true));
|
||||
}
|
||||
watch(
|
||||
() => preferences.app.watermark,
|
||||
async (enable) => {
|
||||
if (enable) {
|
||||
await updateWatermark({
|
||||
content: `${userStore.userInfo?.username}`,
|
||||
});
|
||||
} else {
|
||||
destroyWatermark();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -34,9 +34,7 @@ function setupCommonGuard(router: Router) {
|
||||
router.afterEach((to) => {
|
||||
// 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
|
||||
|
||||
if (preferences.tabbar.enable) {
|
||||
loadedPaths.add(to.path);
|
||||
}
|
||||
loadedPaths.add(to.path);
|
||||
|
||||
// 关闭页面加载进度条
|
||||
if (preferences.transition.progress) {
|
||||
|
@ -1,10 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { NotificationItem } from '@vben/layouts';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
||||
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
||||
import { useWatermark } from '@vben/hooks';
|
||||
import { BookOpenText, CircleHelp, MdiGithub } from '@vben/icons';
|
||||
import {
|
||||
BasicLayout,
|
||||
@ -54,6 +55,7 @@ const notifications = ref<NotificationItem[]>([
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
const accessStore = useAccessStore();
|
||||
const { destroyWatermark, updateWatermark } = useWatermark();
|
||||
const showDot = computed(() =>
|
||||
notifications.value.some((item) => !item.isRead),
|
||||
);
|
||||
@ -103,6 +105,22 @@ function handleNoticeClear() {
|
||||
function handleMakeAll() {
|
||||
notifications.value.forEach((item) => (item.isRead = true));
|
||||
}
|
||||
|
||||
watch(
|
||||
() => preferences.app.watermark,
|
||||
async (enable) => {
|
||||
if (enable) {
|
||||
await updateWatermark({
|
||||
content: `${userStore.userInfo?.username}`,
|
||||
});
|
||||
} else {
|
||||
destroyWatermark();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -34,9 +34,7 @@ function setupCommonGuard(router: Router) {
|
||||
router.afterEach((to) => {
|
||||
// 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
|
||||
|
||||
if (preferences.tabbar.enable) {
|
||||
loadedPaths.add(to.path);
|
||||
}
|
||||
loadedPaths.add(to.path);
|
||||
|
||||
// 关闭页面加载进度条
|
||||
if (preferences.transition.progress) {
|
||||
|
@ -234,7 +234,6 @@ const defaultPreferences: Preferences = {
|
||||
showIcon: true,
|
||||
showMaximize: true,
|
||||
showMore: true,
|
||||
showRefresh: true,
|
||||
styleType: 'chrome',
|
||||
},
|
||||
theme: {
|
||||
@ -262,6 +261,7 @@ const defaultPreferences: Preferences = {
|
||||
notification: true,
|
||||
sidebarToggle: true,
|
||||
themeToggle: true,
|
||||
refresh: true,
|
||||
},
|
||||
};
|
||||
```
|
||||
@ -421,8 +421,6 @@ interface TabbarPreferences {
|
||||
showMaximize: boolean;
|
||||
/** Whether to show the more button */
|
||||
showMore: boolean;
|
||||
/** Whether to show the refresh button */
|
||||
showRefresh: boolean;
|
||||
/** Tab style */
|
||||
styleType: TabsStyleType;
|
||||
}
|
||||
@ -469,6 +467,8 @@ interface WidgetPreferences {
|
||||
lockScreen: boolean;
|
||||
/** Whether notification widget is displayed */
|
||||
notification: boolean;
|
||||
/** Whether to show the refresh button */
|
||||
refresh: boolean;
|
||||
/** Whether sidebar show/hide widget is displayed */
|
||||
sidebarToggle: boolean;
|
||||
/** Whether theme switch widget is displayed */
|
||||
|
@ -256,7 +256,6 @@ const defaultPreferences: Preferences = {
|
||||
showIcon: true,
|
||||
showMaximize: true,
|
||||
showMore: true,
|
||||
showRefresh: true,
|
||||
styleType: 'chrome',
|
||||
},
|
||||
theme: {
|
||||
@ -282,6 +281,7 @@ const defaultPreferences: Preferences = {
|
||||
languageToggle: true,
|
||||
lockScreen: true,
|
||||
notification: true,
|
||||
refresh: true,
|
||||
sidebarToggle: true,
|
||||
themeToggle: true,
|
||||
},
|
||||
@ -445,8 +445,6 @@ interface TabbarPreferences {
|
||||
showMaximize: boolean;
|
||||
/** 显示更多按钮 */
|
||||
showMore: boolean;
|
||||
/** 显示刷新按钮 */
|
||||
showRefresh: boolean;
|
||||
/** 标签页风格 */
|
||||
styleType: TabsStyleType;
|
||||
}
|
||||
@ -494,6 +492,8 @@ interface WidgetPreferences {
|
||||
lockScreen: boolean;
|
||||
/** 是否显示通知部件 */
|
||||
notification: boolean;
|
||||
/** 显示刷新按钮 */
|
||||
refresh: boolean;
|
||||
/** 是否显示侧边栏显示/隐藏部件 */
|
||||
sidebarToggle: boolean;
|
||||
/** 是否显示主题切换部件 */
|
||||
|
@ -81,7 +81,6 @@ exports[`defaultPreferences immutability test > should not modify the config obj
|
||||
"showIcon": true,
|
||||
"showMaximize": true,
|
||||
"showMore": true,
|
||||
"showRefresh": true,
|
||||
"styleType": "chrome",
|
||||
},
|
||||
"theme": {
|
||||
@ -107,6 +106,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
|
||||
"languageToggle": true,
|
||||
"lockScreen": true,
|
||||
"notification": true,
|
||||
"refresh": true,
|
||||
"sidebarToggle": true,
|
||||
"themeToggle": true,
|
||||
},
|
||||
|
@ -81,7 +81,7 @@ const defaultPreferences: Preferences = {
|
||||
showIcon: true,
|
||||
showMaximize: true,
|
||||
showMore: true,
|
||||
showRefresh: true,
|
||||
|
||||
styleType: 'chrome',
|
||||
},
|
||||
theme: {
|
||||
@ -107,6 +107,7 @@ const defaultPreferences: Preferences = {
|
||||
languageToggle: true,
|
||||
lockScreen: true,
|
||||
notification: true,
|
||||
refresh: true,
|
||||
sidebarToggle: true,
|
||||
themeToggle: true,
|
||||
},
|
||||
|
@ -169,8 +169,6 @@ interface TabbarPreferences {
|
||||
showMaximize: boolean;
|
||||
/** 显示更多按钮 */
|
||||
showMore: boolean;
|
||||
/** 显示刷新按钮 */
|
||||
showRefresh: boolean;
|
||||
/** 标签页风格 */
|
||||
styleType: TabsStyleType;
|
||||
}
|
||||
@ -218,6 +216,8 @@ interface WidgetPreferences {
|
||||
lockScreen: boolean;
|
||||
/** 是否显示通知部件 */
|
||||
notification: boolean;
|
||||
/** 显示刷新按钮 */
|
||||
refresh: boolean;
|
||||
/** 是否显示侧边栏显示/隐藏部件 */
|
||||
sidebarToggle: boolean;
|
||||
/** 是否显示主题切换部件 */
|
||||
|
@ -1,3 +1,2 @@
|
||||
export { default as TabsToolMore } from './tool-more.vue';
|
||||
export { default as TabsToolRefresh } from './tool-refresh.vue';
|
||||
export { default as TabsToolScreen } from './tool-screen.vue';
|
||||
|
@ -1,31 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { RotateCw } from '@vben-core/icons';
|
||||
|
||||
const emit = defineEmits<{ refresh: [] }>();
|
||||
|
||||
const loading = ref(false);
|
||||
function handleClick() {
|
||||
loading.value = true;
|
||||
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
emit('refresh');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex-center hover:bg-muted hover:text-foreground text-muted-foreground border-border h-full cursor-pointer border-l px-[9px] text-lg font-semibold"
|
||||
@click="handleClick"
|
||||
>
|
||||
<RotateCw
|
||||
:class="{
|
||||
'animate-spin duration-1000': loading,
|
||||
}"
|
||||
class="size-4"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
@ -1,8 +1,6 @@
|
||||
import type { Watermark, WatermarkOptions } from 'watermark-js-plus';
|
||||
|
||||
import { nextTick, onUnmounted, ref, watch } from 'vue';
|
||||
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { nextTick, onUnmounted, ref } from 'vue';
|
||||
|
||||
const watermark = ref<Watermark>();
|
||||
const cachedOptions = ref<Partial<WatermarkOptions>>({
|
||||
@ -67,15 +65,6 @@ export function useWatermark() {
|
||||
watermark.value?.destroy();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => preferences.app.watermark,
|
||||
(enable) => {
|
||||
if (!enable) {
|
||||
destroyWatermark();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
destroyWatermark();
|
||||
});
|
||||
|
@ -3,5 +3,5 @@
|
||||
### header
|
||||
|
||||
- 支持N个自定义插槽,命名方式:header-right-n,header-left-n
|
||||
- header-left-n ,排序方式:1-4 ,breadcrumb,6-x
|
||||
- header-right-n ,排序方式:1-4,global-search,6-9,theme-toggle,11-14,language-toggle,16-19,fullscreen,21-24,notification,26-29,user-dropdown,30-x
|
||||
- header-left-n ,排序方式:0-19 ,breadcrumb 21-x
|
||||
- header-right-n ,排序方式:0-49,global-search,51-59,theme-toggle,61-69,language-toggle,71-79,fullscreen,81-89,notification,91-149,user-dropdown,151-x
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
/>
|
||||
|
@ -143,7 +143,7 @@ const vbenFormOptions = computed(() => {
|
||||
props.api.reload(formValues);
|
||||
},
|
||||
handleReset: async () => {
|
||||
formApi.resetForm();
|
||||
await formApi.resetForm();
|
||||
const formValues = formApi.form.values;
|
||||
props.api.reload(formValues);
|
||||
},
|
||||
|
@ -213,7 +213,6 @@
|
||||
"enable": "Enable Tab Bar",
|
||||
"icon": "Show Tabbar Icon",
|
||||
"showMore": "Show More Button",
|
||||
"showRefresh": "Show Refresh Button",
|
||||
"showMaximize": "Show Maximize Button",
|
||||
"persist": "Persist Tabs",
|
||||
"dragable": "Enable Dragable Sort",
|
||||
@ -325,7 +324,8 @@
|
||||
"languageToggle": "Enable Language Toggle",
|
||||
"notification": "Enable Notification",
|
||||
"sidebarToggle": "Enable Sidebar Toggle",
|
||||
"lockScreen": "Enable Lock Screen"
|
||||
"lockScreen": "Enable Lock Screen",
|
||||
"refresh": "Enable Refresh"
|
||||
}
|
||||
},
|
||||
"ui": {
|
||||
|
@ -213,7 +213,6 @@
|
||||
"enable": "启用标签栏",
|
||||
"icon": "显示标签栏图标",
|
||||
"showMore": "显示更多按钮",
|
||||
"showRefresh": "显示刷新按钮",
|
||||
"showMaximize": "显示最大化按钮",
|
||||
"persist": "持久化标签页",
|
||||
"dragable": "启动拖拽排序",
|
||||
@ -325,7 +324,8 @@
|
||||
"languageToggle": "启用语言切换",
|
||||
"notification": "启用通知",
|
||||
"sidebarToggle": "启用侧边栏切换",
|
||||
"lockScreen": "启用锁屏"
|
||||
"lockScreen": "启用锁屏",
|
||||
"refresh": "启用刷新"
|
||||
}
|
||||
},
|
||||
"ui": {
|
||||
|
@ -1,10 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { NotificationItem } from '@vben/layouts';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
||||
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
||||
import { useWatermark } from '@vben/hooks';
|
||||
import { BookOpenText, CircleHelp, MdiGithub } from '@vben/icons';
|
||||
import {
|
||||
BasicLayout,
|
||||
@ -54,6 +55,7 @@ const notifications = ref<NotificationItem[]>([
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
const accessStore = useAccessStore();
|
||||
const { destroyWatermark, updateWatermark } = useWatermark();
|
||||
const showDot = computed(() =>
|
||||
notifications.value.some((item) => !item.isRead),
|
||||
);
|
||||
@ -103,6 +105,22 @@ function handleNoticeClear() {
|
||||
function handleMakeAll() {
|
||||
notifications.value.forEach((item) => (item.isRead = true));
|
||||
}
|
||||
|
||||
watch(
|
||||
() => preferences.app.watermark,
|
||||
async (enable) => {
|
||||
if (enable) {
|
||||
await updateWatermark({
|
||||
content: `${userStore.userInfo?.username}`,
|
||||
});
|
||||
} else {
|
||||
destroyWatermark();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -33,10 +33,7 @@ function setupCommonGuard(router: Router) {
|
||||
|
||||
router.afterEach((to) => {
|
||||
// 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
|
||||
|
||||
if (preferences.tabbar.enable) {
|
||||
loadedPaths.add(to.path);
|
||||
}
|
||||
loadedPaths.add(to.path);
|
||||
|
||||
// 关闭页面加载进度条
|
||||
if (preferences.transition.progress) {
|
||||
|
@ -475,8 +475,8 @@ catalogs:
|
||||
specifier: ^2.1.6
|
||||
version: 2.1.6
|
||||
vxe-pc-ui:
|
||||
specifier: ^4.2.13
|
||||
version: 4.2.13
|
||||
specifier: ^4.2.14
|
||||
version: 4.2.14
|
||||
vxe-table:
|
||||
specifier: ^4.7.84
|
||||
version: 4.7.85
|
||||
@ -1698,7 +1698,7 @@ importers:
|
||||
version: 3.5.11(typescript@5.6.2)
|
||||
vxe-pc-ui:
|
||||
specifier: 'catalog:'
|
||||
version: 4.2.13
|
||||
version: 4.2.14
|
||||
vxe-table:
|
||||
specifier: 'catalog:'
|
||||
version: 4.7.85
|
||||
@ -10766,8 +10766,8 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.5.11
|
||||
|
||||
vxe-pc-ui@4.2.13:
|
||||
resolution: {integrity: sha512-zTI0pDAO0sJ5Snvv8zDnvxMcZt2dKg5RPrtOXsHpSuAW+B2dS/grdn7bvj7RVpgb/cSx4fdNoVmmU5U6HLufAA==}
|
||||
vxe-pc-ui@4.2.14:
|
||||
resolution: {integrity: sha512-yXZo7axUmn62bksPKFwOHafGJTDH7QXsvhWVwr/xb+vM4wLA14WUijyEnAJJvY78lM5FB8cIFZqwahOhj1Pu8w==}
|
||||
|
||||
vxe-table@4.7.85:
|
||||
resolution: {integrity: sha512-sNQ4jKnU6vZkStTK2JDDKgIz5kKCCWtTtOVl7dpNsLJ16NYWMCDlNby5m/DJC+xa0dPvSdr7+AH4TXfD1vpRFg==}
|
||||
@ -21256,13 +21256,13 @@ snapshots:
|
||||
vooks: 0.2.12(vue@3.5.11(typescript@5.6.2))
|
||||
vue: 3.5.11(typescript@5.6.2)
|
||||
|
||||
vxe-pc-ui@4.2.13:
|
||||
vxe-pc-ui@4.2.14:
|
||||
dependencies:
|
||||
'@vxe-ui/core': 4.0.12
|
||||
|
||||
vxe-table@4.7.85:
|
||||
dependencies:
|
||||
vxe-pc-ui: 4.2.13
|
||||
vxe-pc-ui: 4.2.14
|
||||
|
||||
w3c-keyname@2.2.8: {}
|
||||
|
||||
|
@ -173,7 +173,7 @@ catalog:
|
||||
vue-i18n: ^10.0.3
|
||||
vue-router: ^4.4.5
|
||||
vue-tsc: ^2.1.6
|
||||
vxe-pc-ui: ^4.2.13
|
||||
vxe-pc-ui: ^4.2.14
|
||||
vxe-table: ^4.7.84
|
||||
watermark-js-plus: ^1.5.7
|
||||
zod: ^3.23.8
|
||||
|
Loading…
Reference in New Issue
Block a user