feat: Feature/pro docs (#70)
* chore: merge main * feat: update docs * feat: remove coze-assistant * feat: add watermark plugin * feat: update preferences * feat: update docs --------- Co-authored-by: vince <vince292007@gmail.com>
This commit is contained in:
@@ -42,6 +42,6 @@
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben-core/typings": "workspace:*",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"vue": "^3.4.33"
|
||||
"vue": "^3.4.34"
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,6 @@
|
||||
"@vben-core/toolkit": "workspace:*",
|
||||
"@vben-core/typings": "workspace:*",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"vue": "^3.4.33"
|
||||
"vue": "^3.4.34"
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,10 @@ const subMenu = useSubMenuContext();
|
||||
const { parentMenu, parentPaths } = useMenu();
|
||||
|
||||
const active = computed(() => props.path === rootMenu?.activePath);
|
||||
const menuIcon = computed(() =>
|
||||
active.value ? props.activeIcon || props.icon : props.icon,
|
||||
);
|
||||
|
||||
const isTopLevelMenuItem = computed(
|
||||
() => parentMenu.value?.type.name === 'Menu',
|
||||
);
|
||||
@@ -94,7 +98,7 @@ onBeforeUnmount(() => {
|
||||
>
|
||||
<template #trigger>
|
||||
<div :class="[nsMenu.be('tooltip', 'trigger')]">
|
||||
<VbenIcon :class="nsMenu.e('icon')" :icon="icon" fallback />
|
||||
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" fallback />
|
||||
<slot></slot>
|
||||
<span v-if="collapseShowTitle" :class="nsMenu.e('name')">
|
||||
<slot name="title"></slot>
|
||||
@@ -109,7 +113,7 @@ onBeforeUnmount(() => {
|
||||
class="right-2"
|
||||
v-bind="props"
|
||||
/>
|
||||
<VbenIcon :class="nsMenu.e('icon')" :icon="icon" fallback />
|
||||
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" fallback />
|
||||
<slot></slot>
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
|
@@ -12,7 +12,7 @@ defineOptions({
|
||||
name: 'NormalMenu',
|
||||
});
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
activePath: '',
|
||||
collapse: false,
|
||||
menus: () => [],
|
||||
@@ -25,6 +25,12 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const { b, e, is } = useNamespace('normal-menu');
|
||||
|
||||
function menuIcon(menu: MenuRecordRaw) {
|
||||
return props.activePath === menu.path
|
||||
? menu.activeIcon || menu.icon
|
||||
: menu.icon;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -44,7 +50,8 @@ const { b, e, is } = useNamespace('normal-menu');
|
||||
@click="() => emit('select', menu)"
|
||||
@mouseenter="() => emit('enter', menu)"
|
||||
>
|
||||
<VbenIcon :class="e('icon')" :icon="menu.icon" fallback />
|
||||
<VbenIcon :class="e('icon')" :icon="menuIcon(menu)" fallback />
|
||||
|
||||
<span :class="e('name')" class="truncate"> {{ menu.name }}</span>
|
||||
</li>
|
||||
</template>
|
||||
|
@@ -172,6 +172,10 @@ function handleMouseleave(deepDispatch = false) {
|
||||
}
|
||||
}
|
||||
|
||||
const menuIcon = computed(() =>
|
||||
active.value ? props.activeIcon || props.icon : props.icon,
|
||||
);
|
||||
|
||||
const item = reactive({
|
||||
active,
|
||||
parentPaths,
|
||||
@@ -215,7 +219,7 @@ onBeforeUnmount(() => {
|
||||
<template #trigger>
|
||||
<SubMenuContent
|
||||
:class="is('active', active)"
|
||||
:icon="icon"
|
||||
:icon="menuIcon"
|
||||
:is-menu-more="isSubMenuMore"
|
||||
:is-top-level-menu-submenu="isTopLevelMenuSubmenu"
|
||||
:level="currentLevel"
|
||||
@@ -246,7 +250,7 @@ onBeforeUnmount(() => {
|
||||
<template v-else>
|
||||
<SubMenuContent
|
||||
:class="is('active', active)"
|
||||
:icon="icon"
|
||||
:icon="menuIcon"
|
||||
:is-menu-more="isSubMenuMore"
|
||||
:is-top-level-menu-submenu="isTopLevelMenuSubmenu"
|
||||
:level="currentLevel"
|
||||
|
@@ -50,6 +50,10 @@ interface MenuProps {
|
||||
}
|
||||
|
||||
interface SubMenuProps extends MenuRecordBadgeRaw {
|
||||
/**
|
||||
* @zh_CN 激活图标
|
||||
*/
|
||||
activeIcon?: string;
|
||||
/**
|
||||
* @zh_CN 是否禁用
|
||||
*/
|
||||
@@ -65,6 +69,10 @@ interface SubMenuProps extends MenuRecordBadgeRaw {
|
||||
}
|
||||
|
||||
interface MenuItemProps extends MenuRecordBadgeRaw {
|
||||
/**
|
||||
* @zh_CN 图标
|
||||
*/
|
||||
activeIcon?: string;
|
||||
/**
|
||||
* @zh_CN 是否禁用
|
||||
*/
|
||||
|
@@ -31,12 +31,19 @@ const hasChildren = computed(() => {
|
||||
Reflect.has(menu, 'children') && !!menu.children && menu.children.length > 0
|
||||
);
|
||||
});
|
||||
|
||||
// function menuIcon(menu: MenuRecordRaw) {
|
||||
// return props.activePath === menu.path
|
||||
// ? menu.activeIcon || menu.icon
|
||||
// : menu.icon;
|
||||
// }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MenuItem
|
||||
v-if="!hasChildren"
|
||||
:key="menu.path"
|
||||
:active-icon="menu.activeIcon"
|
||||
:badge="menu.badge"
|
||||
:badge-type="menu.badgeType"
|
||||
:badge-variants="menu.badgeVariants"
|
||||
@@ -48,6 +55,7 @@ const hasChildren = computed(() => {
|
||||
<SubMenuComp
|
||||
v-else
|
||||
:key="`${menu.path}_sub`"
|
||||
:active-icon="menu.activeIcon"
|
||||
:icon="menu.icon"
|
||||
:path="menu.path"
|
||||
>
|
||||
|
@@ -48,8 +48,8 @@
|
||||
"@vben-core/typings": "workspace:*",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"lucide-vue-next": "^0.414.0",
|
||||
"lucide-vue-next": "^0.416.0",
|
||||
"radix-vue": "^1.9.2",
|
||||
"vue": "^3.4.33"
|
||||
"vue": "^3.4.34"
|
||||
}
|
||||
}
|
||||
|
@@ -32,14 +32,14 @@ function handleItemClick(menu: IDropdownMenuItem) {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuGroup>
|
||||
<template v-for="menu in menus" :key="menu.key">
|
||||
<template v-for="menu in menus" :key="menu.value">
|
||||
<DropdownMenuItem
|
||||
:disabled="menu.disabled"
|
||||
class="data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground text-foreground/80 mb-1 cursor-pointer"
|
||||
@click="handleItemClick(menu)"
|
||||
>
|
||||
<component :is="menu.icon" v-if="menu.icon" class="mr-2 size-4" />
|
||||
{{ menu.text }}
|
||||
{{ menu.label }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator v-if="menu.separator" class="bg-border" />
|
||||
</template>
|
||||
|
@@ -30,18 +30,20 @@ function handleItemClick(value: string) {
|
||||
<template v-for="menu in menus" :key="menu.key">
|
||||
<DropdownMenuItem
|
||||
:class="
|
||||
menu.key === modelValue ? 'bg-accent text-accent-foreground' : ''
|
||||
menu.value === modelValue
|
||||
? 'bg-accent text-accent-foreground'
|
||||
: ''
|
||||
"
|
||||
class="data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground text-foreground/80 mb-1 cursor-pointer"
|
||||
@click="handleItemClick(menu.key)"
|
||||
@click="handleItemClick(menu.value)"
|
||||
>
|
||||
<component :is="menu.icon" v-if="menu.icon" class="mr-2 size-4" />
|
||||
<span
|
||||
v-if="!menu.icon"
|
||||
:class="menu.key === modelValue ? 'bg-foreground' : ''"
|
||||
:class="menu.value === modelValue ? 'bg-foreground' : ''"
|
||||
class="mr-2 size-1.5 rounded-full"
|
||||
></span>
|
||||
{{ menu.text }}
|
||||
{{ menu.label }}
|
||||
</DropdownMenuItem>
|
||||
</template>
|
||||
</DropdownMenuGroup>
|
||||
|
@@ -12,17 +12,17 @@ interface VbenDropdownMenuItem {
|
||||
*/
|
||||
icon?: Component;
|
||||
/**
|
||||
* @zh_CN 唯一标识
|
||||
* @zh_CN 标题
|
||||
*/
|
||||
key: string;
|
||||
label: string;
|
||||
/**
|
||||
* @zh_CN 是否是分割线
|
||||
*/
|
||||
separator?: boolean;
|
||||
/**
|
||||
* @zh_CN 标题
|
||||
* @zh_CN 唯一标识
|
||||
*/
|
||||
text: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface DropdownMenuProps {
|
||||
|
@@ -41,6 +41,6 @@
|
||||
"@vben-core/icons": "workspace:*",
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben-core/typings": "workspace:*",
|
||||
"vue": "^3.4.33"
|
||||
"vue": "^3.4.34"
|
||||
}
|
||||
}
|
||||
|
@@ -1,2 +1,3 @@
|
||||
export { default as TabsToolMore } from './tool-more.vue';
|
||||
export { default as TabsToolRefresh } from './tool-refresh.vue';
|
||||
export { default as TabsToolScreen } from './tool-screen.vue';
|
||||
|
@@ -0,0 +1,31 @@
|
||||
<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>
|
Reference in New Issue
Block a user