This commit is contained in:
dap
2024-08-15 09:27:39 +08:00
84 changed files with 577 additions and 262 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/access",
"version": "5.0.1",
"version": "5.1.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/chart-ui",
"version": "5.0.1",
"version": "5.1.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/common-ui",
"version": "5.0.1",
"version": "5.1.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -9,7 +9,7 @@
```bash
# 进入目标应用目录,例如 apps/xxxx-app
# cd apps/xxxx-app
pnpm add @vben/hooks --workspace
pnpm add @vben/hooks
```
### 使用

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/hooks",
"version": "5.0.1",
"version": "5.1.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/layouts",
"version": "5.0.1",
"version": "5.1.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -10,7 +10,7 @@ import { RouterView } from 'vue-router';
import { useContentHeight } from '@vben/hooks';
import { preferences, usePreferences } from '@vben/preferences';
import { storeToRefs, useTabbarStore } from '@vben/stores';
import { Spinner } from '@vben-core/shadcn-ui';
import { VbenSpinner } from '@vben-core/shadcn-ui';
import { IFrameRouterView } from '../../iframe';
import { useContentSpinner } from './use-content-spinner';
@@ -86,7 +86,7 @@ function transformComponent(
<template>
<div class="relative h-full">
<Spinner
<VbenSpinner
v-if="preferences.transition.loading"
:spinning="spinning"
:style="contentStyles"

View File

@@ -5,7 +5,12 @@ import { preferences, usePreferences } from '@vben/preferences';
import { useAccessStore } from '@vben/stores';
import { VbenFullScreen } from '@vben-core/shadcn-ui';
import { GlobalSearch, LanguageToggle, ThemeToggle } from '../../widgets';
import {
GlobalSearch,
LanguageToggle,
PreferencesButton,
ThemeToggle,
} from '../../widgets';
interface Props {
/**
@@ -26,34 +31,44 @@ const accessStore = useAccessStore();
const { globalSearchShortcutKey } = usePreferences();
const slots = useSlots();
const rightSlots = computed(() => {
const list = [{ index: 30, name: 'user-dropdown' }];
const list = [{ index: 100, name: 'user-dropdown' }];
if (preferences.widget.globalSearch) {
list.push({
index: 5,
name: 'global-search',
});
}
if (preferences.widget.themeToggle) {
if (
preferences.app.enablePreferences &&
preferences.app.preferencesButtonPosition === 'header'
) {
list.push({
index: 10,
name: 'preferences',
});
}
if (preferences.widget.themeToggle) {
list.push({
index: 15,
name: 'theme-toggle',
});
}
if (preferences.widget.languageToggle) {
list.push({
index: 15,
index: 20,
name: 'language-toggle',
});
}
if (preferences.widget.fullscreen) {
list.push({
index: 20,
index: 25,
name: 'fullscreen',
});
}
if (preferences.widget.notification) {
list.push({
index: 25,
index: 30,
name: 'notification',
});
}
@@ -66,6 +81,7 @@ const rightSlots = computed(() => {
});
return list.sort((a, b) => a.index - b.index);
});
const leftSlots = computed(() => {
const list: any[] = [];
@@ -108,8 +124,12 @@ const leftSlots = computed(() => {
class="mr-4"
/>
</template>
<template v-else-if="slot.name === 'preferences'">
<PreferencesButton class="mr-2" />
</template>
<template v-else-if="slot.name === 'theme-toggle'">
<ThemeToggle class="mr-2" />
<ThemeToggle class="mr-2 mt-[2px]" />
</template>
<template v-else-if="slot.name === 'language-toggle'">
<LanguageToggle class="mr-2" />

View File

@@ -41,17 +41,19 @@ const {
isSideMixedNav,
layout,
sidebarCollapsed,
theme,
} = usePreferences();
const userStore = useUserStore();
const { updateWatermark } = useWatermark();
const lockStore = useLockStore();
const headerMenuTheme = computed(() => {
return isDark.value ? 'dark' : 'light';
const sidebarTheme = computed(() => {
const dark = isDark.value || preferences.theme.semiDarkSidebar;
return dark ? 'dark' : 'light';
});
const theme = computed(() => {
const dark = isDark.value || preferences.theme.semiDarkMenu;
const headerTheme = computed(() => {
const dark = isDark.value || preferences.theme.semiDarkHeader;
return dark ? 'dark' : 'light';
});
@@ -160,6 +162,7 @@ const headerSlots = computed(() => {
:footer-fixed="preferences.footer.fixed"
:header-hidden="preferences.header.hidden"
:header-mode="preferences.header.mode"
:header-theme="headerTheme"
:header-toggle-sidebar-button="preferences.widget.sidebarToggle"
:header-visible="preferences.header.enable"
:is-mobile="preferences.app.isMobile"
@@ -170,8 +173,7 @@ const headerSlots = computed(() => {
:sidebar-expand-on-hover="preferences.sidebar.expandOnHover"
:sidebar-extra-collapse="preferences.sidebar.extraCollapse"
:sidebar-hidden="preferences.sidebar.hidden"
:sidebar-semi-dark="preferences.theme.semiDarkMenu"
:sidebar-theme="theme"
:sidebar-theme="sidebarTheme"
:sidebar-width="preferences.sidebar.width"
:tabbar-enable="preferences.tabbar.enable"
:tabbar-height="preferences.tabbar.height"
@@ -192,14 +194,6 @@ const headerSlots = computed(() => {
updatePreferences({ sidebar: { extraCollapse: value } })
"
>
<template v-if="preferences.app.enablePreferences" #preferences>
<Preferences @clear-preferences-and-logout="clearPreferencesAndLogout" />
</template>
<template #floating-groups>
<VbenBackTop />
</template>
<!-- logo -->
<template #logo>
<VbenLogo
@@ -208,7 +202,7 @@ const headerSlots = computed(() => {
:collapsed="logoCollapsed"
:src="preferences.logo.source"
:text="preferences.app.name"
:theme="showHeaderNav ? headerMenuTheme : theme"
:theme="showHeaderNav ? headerTheme : theme"
/>
</template>
<!-- 头部区域 -->
@@ -230,7 +224,7 @@ const headerSlots = computed(() => {
:default-active="headerActive"
:menus="wrapperMenus(headerMenus)"
:rounded="isMenuRounded"
:theme="headerMenuTheme"
:theme="headerTheme"
class="w-full"
mode="horizontal"
@select="handleMenuSelect"
@@ -256,7 +250,7 @@ const headerSlots = computed(() => {
:default-active="sidebarActive"
:menus="wrapperMenus(sidebarMenus)"
:rounded="isMenuRounded"
:theme="theme"
:theme="sidebarTheme"
mode="vertical"
@select="handleMenuSelect"
/>
@@ -267,7 +261,7 @@ const headerSlots = computed(() => {
:active-path="extraActiveMenu"
:menus="wrapperMenus(headerMenus)"
:rounded="isMenuRounded"
:theme="theme"
:theme="sidebarTheme"
@default-select="handleDefaultSelect"
@enter="handleMenuMouseEnter"
@select="handleMixedMenuSelect"
@@ -280,7 +274,7 @@ const headerSlots = computed(() => {
:collapse="preferences.sidebar.extraCollapse"
:menus="wrapperMenus(extraMenus)"
:rounded="isMenuRounded"
:theme="theme"
:theme="sidebarTheme"
/>
</template>
<template #side-extra-title>
@@ -325,6 +319,19 @@ const headerSlots = computed(() => {
<Transition v-if="preferences.widget.lockScreen" name="slide-up">
<slot v-if="lockStore.isLockScreen" name="lock-screen"></slot>
</Transition>
<template
v-if="
preferences.app.enablePreferences &&
preferences.app.preferencesButtonPosition === 'fixed'
"
>
<Preferences
class="z-100 fixed bottom-20 right-0"
@clear-preferences-and-logout="clearPreferencesAndLogout"
/>
</template>
<VbenBackTop />
</template>
</VbenAdminLayout>
</template>

View File

@@ -6,7 +6,7 @@ import { useRoute } from 'vue-router';
import { preferences } from '@vben/preferences';
import { useTabbarStore } from '@vben/stores';
import { Spinner } from '@vben-core/shadcn-ui';
import { VbenSpinner } from '@vben-core/shadcn-ui';
defineOptions({ name: 'IFrameRouterView' });
@@ -73,7 +73,7 @@ function showSpinning(index: number) {
v-show="routeShow(item)"
class="relative size-full"
>
<Spinner :spinning="showSpinning(index)" />
<VbenSpinner :spinning="showSpinning(index)" />
<iframe
:src="item.meta.iframeSrc as string"
class="size-full"

View File

@@ -54,9 +54,6 @@ const styleItems = computed((): SelectOption[] => [
<SwitchItem v-model="tabbarDragable" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.dragable') }}
</SwitchItem>
<SelectItem v-model="tabbarStyleType" :items="styleItems">
{{ $t('preferences.tabbar.styleType.title') }}
</SelectItem>
<SwitchItem v-model="tabbarShowIcon" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.icon') }}
</SwitchItem>
@@ -69,4 +66,7 @@ const styleItems = computed((): SelectOption[] => [
<SwitchItem v-model="tabbarShowMaximize" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.showMaximize') }}
</SwitchItem>
<SelectItem v-model="tabbarStyleType" :items="styleItems">
{{ $t('preferences.tabbar.styleType.title') }}
</SelectItem>
</template>

View File

@@ -1,6 +1,11 @@
<script setup lang="ts">
import type { SelectOption } from '@vben/types';
import { computed } from 'vue';
import { $t } from '@vben/locales';
import SelectItem from '../select-item.vue';
import SwitchItem from '../switch-item.vue';
defineOptions({
@@ -14,6 +19,20 @@ const widgetNotification = defineModel<boolean>('widgetNotification');
const widgetThemeToggle = defineModel<boolean>('widgetThemeToggle');
const widgetSidebarToggle = defineModel<boolean>('widgetSidebarToggle');
const widgetLockScreen = defineModel<boolean>('widgetLockScreen');
const appPreferencesButtonPosition = defineModel<string>(
'appPreferencesButtonPosition',
);
const positionItems = computed((): SelectOption[] => [
{
label: $t('preferences.position.header'),
value: 'header',
},
{
label: $t('preferences.position.fixed'),
value: 'fixed',
},
]);
</script>
<template>
@@ -38,4 +57,7 @@ const widgetLockScreen = defineModel<boolean>('widgetLockScreen');
<SwitchItem v-model="widgetSidebarToggle">
{{ $t('preferences.widget.sidebarToggle') }}
</SwitchItem>
<SelectItem v-model="appPreferencesButtonPosition" :items="positionItems">
{{ $t('preferences.position.title') }}
</SelectItem>
</template>

View File

@@ -13,9 +13,8 @@ defineOptions({
});
const modelValue = defineModel<string>({ default: 'auto' });
const themeSemiDarkMenu = defineModel<boolean>('themeSemiDarkMenu', {
default: true,
});
const themeSemiDarkSidebar = defineModel<boolean>('themeSemiDarkSidebar');
const themeSemiDarkHeader = defineModel<boolean>('themeSemiDarkHeader');
const THEME_PRESET: Array<{ icon: Component; name: ThemeModeType }> = [
{
@@ -71,11 +70,14 @@ function nameView(name: string) {
</template>
<SwitchItem
v-model="themeSemiDarkMenu"
v-model="themeSemiDarkSidebar"
:disabled="modelValue === 'dark'"
class="mt-6"
>
{{ $t('preferences.theme.darkMenu') }}
{{ $t('preferences.theme.darkSidebar') }}
</SwitchItem>
<SwitchItem v-model="themeSemiDarkHeader" :disabled="modelValue === 'dark'">
{{ $t('preferences.theme.darkHeader') }}
</SwitchItem>
</div>
</template>

View File

@@ -1,2 +1,3 @@
export { default as Preferences } from './preferences.vue';
export { default as PreferencesButton } from './preferences-button.vue';
export * from './use-open-preferences';

View File

@@ -0,0 +1,13 @@
<script lang="ts" setup>
import { Settings } from '@vben/icons';
import { VbenIconButton } from '@vben-core/shadcn-ui';
import Preferences from './preferences.vue';
</script>
<template>
<Preferences>
<VbenIconButton>
<Settings class="size-4" />
</VbenIconButton>
</Preferences>
</template>

View File

@@ -7,13 +7,14 @@ import type {
LayoutHeaderModeType,
LayoutType,
NavigationStyleType,
PreferencesButtonPositionType,
ThemeModeType,
} from '@vben/types';
import type { SegmentedItem } from '@vben-core/shadcn-ui';
import { computed, ref } from 'vue';
import { Copy, RotateCw, Settings2 } from '@vben/icons';
import { Copy, RotateCw, Settings } from '@vben/icons';
import { $t, loadLocaleMessages } from '@vben/locales';
import {
clearPreferencesCache,
@@ -63,6 +64,9 @@ const appColorWeakMode = defineModel<boolean>('appColorWeakMode');
const appContentCompact = defineModel<ContentCompactType>('appContentCompact');
const appWatermark = defineModel<boolean>('appWatermark');
const appEnableCheckUpdates = defineModel<boolean>('appEnableCheckUpdates');
const appPreferencesButtonPosition = defineModel<PreferencesButtonPositionType>(
'appPreferencesButtonPosition',
);
const transitionProgress = defineModel<boolean>('transitionProgress');
const transitionName = defineModel<string>('transitionName');
@@ -73,7 +77,8 @@ const themeColorPrimary = defineModel<string>('themeColorPrimary');
const themeBuiltinType = defineModel<BuiltinThemeType>('themeBuiltinType');
const themeMode = defineModel<ThemeModeType>('themeMode');
const themeRadius = defineModel<string>('themeRadius');
const themeSemiDarkMenu = defineModel<boolean>('themeSemiDarkMenu');
const themeSemiDarkSidebar = defineModel<boolean>('themeSemiDarkSidebar');
const themeSemiDarkHeader = defineModel<boolean>('themeSemiDarkHeader');
const sidebarEnable = defineModel<boolean>('sidebarEnable');
const sidebarWidth = defineModel<number>('sidebarWidth');
@@ -219,19 +224,21 @@ async function handleReset() {
</script>
<template>
<div class="z-100 fixed right-0 top-1/2">
<div>
<VbenSheet
v-model:open="openPreferences"
:description="$t('preferences.subtitle')"
:title="$t('preferences.title')"
>
<template #trigger>
<VbenButton
:title="$t('preferences.title')"
class="bg-primary flex-col-center h-10 w-10 cursor-pointer rounded-l-lg rounded-r-none border-none"
>
<Settings2 class="size-5" />
</VbenButton>
<slot name="trigger">
<VbenButton
:title="$t('preferences.title')"
class="bg-primary flex-col-center size-10 cursor-pointer rounded-l-lg rounded-r-none border-none"
>
<Settings class="size-5" />
</VbenButton>
</slot>
</template>
<template #extra>
<div class="flex items-center">
@@ -274,7 +281,8 @@ async function handleReset() {
<Block :title="$t('preferences.theme.title')">
<Theme
v-model="themeMode"
v-model:theme-semi-dark-menu="themeSemiDarkMenu"
v-model:theme-semi-dark-header="themeSemiDarkHeader"
v-model:theme-semi-dark-sidebar="themeSemiDarkSidebar"
/>
</Block>
<Block :title="$t('preferences.theme.builtin.title')">
@@ -356,6 +364,9 @@ async function handleReset() {
</Block>
<Block :title="$t('preferences.widget.title')">
<Widget
v-model:app-preferences-button-position="
appPreferencesButtonPosition
"
v-model:widget-fullscreen="widgetFullscreen"
v-model:widget-global-search="widgetGlobalSearch"
v-model:widget-language-toggle="widgetLanguageToggle"

View File

@@ -47,5 +47,9 @@ const listen = computed(() => {
});
</script>
<template>
<PreferencesSheet v-bind="attrs" v-on="listen" />
<PreferencesSheet v-bind="attrs" v-on="listen">
<template #trigger>
<slot></slot>
</template>
</PreferencesSheet>
</template>

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/request",
"version": "5.0.1",
"version": "5.1.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {