Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
This commit is contained in:
@@ -66,7 +66,7 @@ async function generateAccessible(
|
||||
}
|
||||
|
||||
// 生成菜单
|
||||
const accessibleMenus = await generateMenus(accessibleRoutes, options.router);
|
||||
const accessibleMenus = generateMenus(accessibleRoutes, options.router);
|
||||
|
||||
return { accessibleMenus, accessibleRoutes };
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { VNode } from 'vue';
|
||||
|
||||
import { computed, ref, watch, watchEffect } from 'vue';
|
||||
import { computed, ref, useAttrs, watch, watchEffect } from 'vue';
|
||||
|
||||
import { usePagination } from '@vben/hooks';
|
||||
import { EmptyIcon, Grip, listIcons } from '@vben/icons';
|
||||
@@ -22,8 +22,9 @@ import {
|
||||
VbenIconButton,
|
||||
VbenPopover,
|
||||
} from '@vben-core/shadcn-ui';
|
||||
import { isFunction } from '@vben-core/shared/utils';
|
||||
|
||||
import { refDebounced, watchDebounced } from '@vueuse/core';
|
||||
import { objectOmit, refDebounced, watchDebounced } from '@vueuse/core';
|
||||
|
||||
import { fetchIconsData } from './icons';
|
||||
|
||||
@@ -64,6 +65,8 @@ const emit = defineEmits<{
|
||||
change: [string];
|
||||
}>();
|
||||
|
||||
const attrs = useAttrs();
|
||||
|
||||
const modelValue = defineModel({ default: '', type: String });
|
||||
|
||||
const visible = ref(false);
|
||||
@@ -167,7 +170,14 @@ const searchInputProps = computed(() => {
|
||||
|
||||
function updateCurrentSelect(v: string) {
|
||||
currentSelect.value = v;
|
||||
const eventKey = `onUpdate:${props.modelValueProp}`;
|
||||
if (attrs[eventKey] && isFunction(attrs[eventKey])) {
|
||||
attrs[eventKey](v);
|
||||
}
|
||||
}
|
||||
const getBindAttrs = computed(() => {
|
||||
return objectOmit(attrs, [`onUpdate:${props.modelValueProp}`]);
|
||||
});
|
||||
|
||||
defineExpose({ toggleOpenState, open, close });
|
||||
</script>
|
||||
@@ -189,7 +199,7 @@ defineExpose({ toggleOpenState, open, close });
|
||||
:aria-label="$t('ui.iconPicker.placeholder')"
|
||||
aria-expanded="visible"
|
||||
:[`onUpdate:${modelValueProp}`]="updateCurrentSelect"
|
||||
v-bind="$attrs"
|
||||
v-bind="getBindAttrs"
|
||||
>
|
||||
<template #[iconSlot]>
|
||||
<VbenIcon
|
||||
|
||||
@@ -37,6 +37,7 @@ function handleMenuOpen(key: string, path: string[]) {
|
||||
:menus="menus"
|
||||
:mode="mode"
|
||||
:rounded="rounded"
|
||||
scroll-to-active
|
||||
:theme="theme"
|
||||
@open="handleMenuOpen"
|
||||
@select="handleMenuSelect"
|
||||
|
||||
@@ -6,39 +6,55 @@ import { isHttpUrl, openRouteInNewWindow, openWindow } from '@vben/utils';
|
||||
|
||||
function useNavigation() {
|
||||
const router = useRouter();
|
||||
const routes = router.getRoutes();
|
||||
|
||||
const routeMetaMap = new Map<string, RouteRecordNormalized>();
|
||||
|
||||
routes.forEach((route) => {
|
||||
routeMetaMap.set(route.path, route);
|
||||
// 初始化路由映射
|
||||
const initRouteMetaMap = () => {
|
||||
const routes = router.getRoutes();
|
||||
routes.forEach((route) => {
|
||||
routeMetaMap.set(route.path, route);
|
||||
});
|
||||
};
|
||||
|
||||
initRouteMetaMap();
|
||||
|
||||
// 监听路由变化
|
||||
router.afterEach(() => {
|
||||
initRouteMetaMap();
|
||||
});
|
||||
|
||||
const navigation = async (path: string) => {
|
||||
const route = routeMetaMap.get(path);
|
||||
const { openInNewWindow = false, query = {} } = route?.meta ?? {};
|
||||
// 检查是否应该在新窗口打开
|
||||
const shouldOpenInNewWindow = (path: string): boolean => {
|
||||
if (isHttpUrl(path)) {
|
||||
openWindow(path, { target: '_blank' });
|
||||
} else if (openInNewWindow) {
|
||||
openRouteInNewWindow(path);
|
||||
} else {
|
||||
await router.push({
|
||||
path,
|
||||
query,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
const route = routeMetaMap.get(path);
|
||||
return route?.meta?.openInNewWindow ?? false;
|
||||
};
|
||||
|
||||
const navigation = async (path: string) => {
|
||||
try {
|
||||
const route = routeMetaMap.get(path);
|
||||
const { openInNewWindow = false, query = {} } = route?.meta ?? {};
|
||||
|
||||
if (isHttpUrl(path)) {
|
||||
openWindow(path, { target: '_blank' });
|
||||
} else if (openInNewWindow) {
|
||||
openRouteInNewWindow(path);
|
||||
} else {
|
||||
await router.push({
|
||||
path,
|
||||
query,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Navigation failed:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const willOpenedByWindow = (path: string) => {
|
||||
const route = routeMetaMap.get(path);
|
||||
const { openInNewWindow = false } = route?.meta ?? {};
|
||||
if (isHttpUrl(path)) {
|
||||
return true;
|
||||
} else if (openInNewWindow) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return shouldOpenInNewWindow(path);
|
||||
};
|
||||
|
||||
return { navigation, willOpenedByWindow };
|
||||
|
||||
@@ -12,7 +12,8 @@ defineOptions({
|
||||
name: 'LanguageToggle',
|
||||
});
|
||||
|
||||
async function handleUpdate(value: string) {
|
||||
async function handleUpdate(value: string | undefined) {
|
||||
if (!value) return;
|
||||
const locale = value as SupportedLanguagesType;
|
||||
updatePreferences({
|
||||
app: {
|
||||
|
||||
@@ -39,7 +39,8 @@ const menus = computed((): VbenDropdownMenuItem[] => [
|
||||
|
||||
const { authPanelCenter, authPanelLeft, authPanelRight } = usePreferences();
|
||||
|
||||
function handleUpdate(value: string) {
|
||||
function handleUpdate(value: string | undefined) {
|
||||
if (!value) return;
|
||||
updatePreferences({
|
||||
app: {
|
||||
authPageLayout: value as AuthPageLayoutType,
|
||||
|
||||
@@ -25,7 +25,7 @@ withDefaults(defineProps<{ shouldOnHover?: boolean }>(), {
|
||||
shouldOnHover: false,
|
||||
});
|
||||
|
||||
function handleChange(isDark: boolean) {
|
||||
function handleChange(isDark: boolean | undefined) {
|
||||
updatePreferences({
|
||||
theme: { mode: isDark ? 'dark' : 'light' },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user