mirror of
https://gitee.com/dapppp/ruoyi-plus-vben5.git
synced 2026-03-24 19:04:32 +08:00
Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin
This commit is contained in:
@@ -35,7 +35,9 @@
|
||||
min-height: 100vh;
|
||||
|
||||
/* overflow: overlay; */
|
||||
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
/* 主体区域背景色 */
|
||||
--background-deep: 210 11.11% 96.47%;
|
||||
--foreground: 210 6% 21%;
|
||||
--foreground: 222 84% 5%;
|
||||
|
||||
/* Background color for <Card /> */
|
||||
--card: 0 0% 100%;
|
||||
|
||||
@@ -22,3 +22,5 @@ export const VBEN_PREVIEW_URL = 'https://www.vben.pro';
|
||||
export const VBEN_ELE_PREVIEW_URL = 'https://ele.vben.pro';
|
||||
|
||||
export const VBEN_NAIVE_PREVIEW_URL = 'https://naive.vben.pro';
|
||||
|
||||
export const VBEN_ANT_PREVIEW_URL = 'https://ant.vben.pro';
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialog as AlertDialogRoot,
|
||||
AlertDialogTitle,
|
||||
} from '@vben-core/shadcn-ui/components/ui/alert-dialog';
|
||||
} from '../ui/alert-dialog';
|
||||
|
||||
interface Props {
|
||||
cancelText?: string;
|
||||
|
||||
@@ -5,20 +5,15 @@ import type {
|
||||
AvatarRootProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from '@vben-core/shadcn-ui/components/ui/avatar';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
|
||||
|
||||
interface Props extends AvatarRootProps, AvatarFallbackProps, AvatarImageProps {
|
||||
alt?: string;
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
dot?: boolean;
|
||||
dotClass?: HTMLAttributes['class'];
|
||||
dotClass?: any;
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import type { IBreadcrumb } from './interface';
|
||||
import type { IBreadcrumb } from './types';
|
||||
|
||||
import { VbenIcon } from '../icon';
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script lang="ts" setup>
|
||||
import type { IBreadcrumb } from './interface';
|
||||
import type { IBreadcrumb } from './types';
|
||||
|
||||
import { ChevronDown } from '@vben-core/icons';
|
||||
|
||||
import { VbenIcon } from '../icon';
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
@@ -9,15 +11,13 @@ import {
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@vben-core/shadcn-ui/components/ui/breadcrumb';
|
||||
} from '../ui/breadcrumb';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/dropdown-menu';
|
||||
|
||||
import { VbenIcon } from '../icon';
|
||||
} from '../ui/dropdown-menu';
|
||||
|
||||
interface Props {
|
||||
breadcrumbs: IBreadcrumb[];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export { default as VbenBreadcrumb } from './breadcrumb.vue';
|
||||
export { default as VbenBackgroundBreadcrumb } from './breadcrumb-background.vue';
|
||||
|
||||
export type * from './interface';
|
||||
export type * from './types';
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { LoaderCircle } from '@vben-core/icons';
|
||||
import {
|
||||
type ButtonVariants,
|
||||
buttonVariants,
|
||||
} from '@vben-core/shadcn-ui/components/ui/button';
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
import { Primitive, type PrimitiveProps } from 'radix-vue';
|
||||
|
||||
import { type ButtonVariants, buttonVariants } from '../ui/button';
|
||||
|
||||
interface Props extends PrimitiveProps {
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
disabled?: boolean;
|
||||
loading?: boolean;
|
||||
size?: ButtonVariants['size'];
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import type { ButtonVariants } from '@vben-core/shadcn-ui/components/ui/button';
|
||||
import type { ButtonVariants } from '../ui/button';
|
||||
|
||||
import { computed, type HTMLAttributes, useSlots } from 'vue';
|
||||
import { computed, useSlots } from 'vue';
|
||||
|
||||
import { VbenTooltip } from '@vben-core/shadcn-ui/components/tooltip';
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
import { type PrimitiveProps } from 'radix-vue';
|
||||
|
||||
import { VbenTooltip } from '../tooltip';
|
||||
import VbenButton from './button.vue';
|
||||
|
||||
interface Props extends PrimitiveProps {
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
disabled?: boolean;
|
||||
onClick?: () => void;
|
||||
tooltip?: string;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { CheckboxRootEmits, CheckboxRootProps } from 'radix-vue';
|
||||
|
||||
import { Checkbox } from '@vben-core/shadcn-ui/components/ui/checkbox';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
import { Checkbox } from '../ui/checkbox';
|
||||
|
||||
const props = defineProps<
|
||||
{
|
||||
name: string;
|
||||
|
||||
@@ -7,9 +7,10 @@ import type {
|
||||
|
||||
import type { IContextMenuItem } from './interface';
|
||||
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
@@ -17,17 +18,15 @@ import {
|
||||
ContextMenuSeparator,
|
||||
ContextMenuShortcut,
|
||||
ContextMenuTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/context-menu';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
} from '../ui/context-menu';
|
||||
|
||||
const props = defineProps<
|
||||
{
|
||||
class?: HTMLAttributes['class'];
|
||||
contentClass?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
contentClass?: any;
|
||||
contentProps?: ContextMenuContentProps;
|
||||
handlerData?: Record<string, any>;
|
||||
itemClass?: HTMLAttributes['class'];
|
||||
itemClass?: any;
|
||||
menus: (data: any) => IContextMenuItem[];
|
||||
} & ContextMenuRootProps
|
||||
>();
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/dropdown-menu';
|
||||
} from '../ui/dropdown-menu';
|
||||
|
||||
interface Props extends DropdownMenuProps {}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/dropdown-menu';
|
||||
} from '../ui/dropdown-menu';
|
||||
|
||||
interface Props extends DropdownMenuProps {}
|
||||
|
||||
|
||||
@@ -5,24 +5,23 @@ import type {
|
||||
HoverCardRootProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/hover-card';
|
||||
} from '../ui/hover-card';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
interface Props extends HoverCardRootProps {
|
||||
class?: any;
|
||||
contentClass?: any;
|
||||
contentProps?: HoverCardContentProps;
|
||||
}
|
||||
|
||||
const props = defineProps<
|
||||
{
|
||||
class?: HTMLAttributes['class'];
|
||||
contentClass?: HTMLAttributes['class'];
|
||||
contentProps?: HoverCardContentProps;
|
||||
} & HoverCardRootProps
|
||||
>();
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emits = defineEmits<HoverCardRootEmits>();
|
||||
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
import { ref, useSlots } from 'vue';
|
||||
|
||||
import { Eye, EyeOff } from '@vben-core/icons';
|
||||
import {
|
||||
type InputProps,
|
||||
VbenInput,
|
||||
} from '@vben-core/shadcn-ui/components/input';
|
||||
|
||||
import { useForwardProps } from 'radix-vue';
|
||||
|
||||
import { type InputProps, VbenInput } from '../input';
|
||||
import PasswordStrength from './password-strength.vue';
|
||||
|
||||
interface Props extends InputProps {}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { default as VbenInput } from './input.vue';
|
||||
export type * from './interface';
|
||||
export type * from './types';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { InputProps } from './interface';
|
||||
import type { InputProps } from './types';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
|
||||
interface InputProps {
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
/**
|
||||
* 错误提示信息
|
||||
*/
|
||||
@@ -1,12 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
import { Primitive, type PrimitiveProps } from 'radix-vue';
|
||||
|
||||
interface Props extends PrimitiveProps {
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
href: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { default as VbenPinInput } from './input.vue';
|
||||
|
||||
export type * from './interface';
|
||||
export type * from './types';
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { PinInputProps } from './interface';
|
||||
import type { PinInputProps } from './types';
|
||||
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { VbenButton } from '@vben-core/shadcn-ui/components/button';
|
||||
import {
|
||||
PinInput,
|
||||
PinInputGroup,
|
||||
PinInputInput,
|
||||
} from '@vben-core/shadcn-ui/components/ui/pin-input';
|
||||
import { VbenButton } from '../button';
|
||||
import { PinInput, PinInputGroup, PinInputInput } from '../ui/pin-input';
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
|
||||
interface PinInputProps {
|
||||
/**
|
||||
* 发送验证码按钮loading
|
||||
@@ -9,7 +7,7 @@ interface PinInputProps {
|
||||
* 发送验证码按钮文本
|
||||
*/
|
||||
btnText?: string;
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
/**
|
||||
* 验证码长度
|
||||
*/
|
||||
@@ -5,27 +5,23 @@ import type {
|
||||
PopoverRootProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
import {
|
||||
PopoverContent,
|
||||
Popover as PopoverRoot,
|
||||
PopoverTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/popover';
|
||||
} from '../ui/popover';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
interface Props extends PopoverRootProps {
|
||||
class?: any;
|
||||
contentClass?: any;
|
||||
contentProps?: PopoverContentProps;
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<
|
||||
{
|
||||
class?: HTMLAttributes['class'];
|
||||
contentClass?: HTMLAttributes['class'];
|
||||
contentProps?: PopoverContentProps;
|
||||
} & PopoverRootProps
|
||||
>(),
|
||||
{},
|
||||
);
|
||||
const props = withDefaults(defineProps<Props>(), {});
|
||||
|
||||
const emits = defineEmits<PopoverRootEmits>();
|
||||
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
import {
|
||||
ScrollArea,
|
||||
ScrollBar,
|
||||
} from '@vben-core/shadcn-ui/components/ui/scroll-area';
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
import { ScrollArea, ScrollBar } from '../ui/scroll-area';
|
||||
|
||||
interface Props {
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: any;
|
||||
horizontal?: boolean;
|
||||
scrollBarClass?: HTMLAttributes['class'];
|
||||
scrollBarClass?: any;
|
||||
shadow?: boolean;
|
||||
shadowBorder?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export type * from './interface';
|
||||
|
||||
export { default as VbenSegmented } from './segmented.vue';
|
||||
|
||||
export type * from './types';
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { SegmentedItem } from './interface';
|
||||
import type { SegmentedItem } from './types';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
} from '@vben-core/shadcn-ui/components/ui/tabs';
|
||||
|
||||
import { TabsTrigger } from 'radix-vue';
|
||||
|
||||
import { Tabs, TabsContent, TabsList } from '../ui/tabs';
|
||||
import TabsIndicator from './tabs-indicator.vue';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, type HTMLAttributes } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
@@ -9,9 +9,7 @@ import {
|
||||
useForwardProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
const props = defineProps<
|
||||
{ class?: HTMLAttributes['class'] } & TabsIndicatorProps
|
||||
>();
|
||||
const props = defineProps<{ class?: any } & TabsIndicatorProps>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, useSlots } from 'vue';
|
||||
|
||||
import {
|
||||
VbenButton,
|
||||
VbenIconButton,
|
||||
} from '@vben-core/shadcn-ui/components/button';
|
||||
import { VbenScrollbar } from '@vben-core/shadcn-ui/components/scrollbar';
|
||||
import { X } from 'lucide-vue-next';
|
||||
|
||||
import { VbenButton, VbenIconButton } from '../button';
|
||||
import { VbenScrollbar } from '../scrollbar';
|
||||
import {
|
||||
Sheet,
|
||||
SheetClose,
|
||||
@@ -15,9 +14,7 @@ import {
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/sheet';
|
||||
|
||||
import { X } from 'lucide-vue-next';
|
||||
} from '../ui/sheet';
|
||||
|
||||
interface Props {
|
||||
cancelText?: string;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import type { TooltipContentProps } from 'radix-vue';
|
||||
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import type { StyleValue } from 'vue';
|
||||
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@vben-core/shadcn-ui/components/ui/tooltip';
|
||||
} from '../ui/tooltip';
|
||||
|
||||
interface Props {
|
||||
contentClass?: HTMLAttributes['class'];
|
||||
contentStyle?: HTMLAttributes['style'];
|
||||
contentClass?: any;
|
||||
contentStyle?: StyleValue;
|
||||
delayDuration?: number;
|
||||
side: TooltipContentProps['side'];
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, type HTMLAttributes } from 'vue';
|
||||
|
||||
import { buttonVariants } from '@vben-core/shadcn-ui/components/ui/button';
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
import { AlertDialogAction, type AlertDialogActionProps } from 'radix-vue';
|
||||
|
||||
import { buttonVariants } from '../button';
|
||||
|
||||
const props = defineProps<
|
||||
{ class?: HTMLAttributes['class'] } & AlertDialogActionProps
|
||||
>();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, type HTMLAttributes } from 'vue';
|
||||
|
||||
import { buttonVariants } from '@vben-core/shadcn-ui/components/ui/button';
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
import { AlertDialogCancel, type AlertDialogCancelProps } from 'radix-vue';
|
||||
|
||||
import { buttonVariants } from '../button';
|
||||
|
||||
const props = defineProps<
|
||||
{ class?: HTMLAttributes['class'] } & AlertDialogCancelProps
|
||||
>();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import type { toggleVariants } from '@vben-core/shadcn-ui/components/ui/toggle';
|
||||
import type { VariantProps } from 'class-variance-authority';
|
||||
|
||||
import type { toggleVariants } from '../toggle';
|
||||
|
||||
import { computed, type HTMLAttributes, provide } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { VariantProps } from 'class-variance-authority';
|
||||
|
||||
import { computed, type HTMLAttributes, inject } from 'vue';
|
||||
|
||||
import { toggleVariants } from '@vben-core/shadcn-ui/components/ui/toggle';
|
||||
import { cn } from '@vben-core/shared';
|
||||
|
||||
import {
|
||||
@@ -12,6 +11,8 @@ import {
|
||||
useForwardProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import { toggleVariants } from '../toggle';
|
||||
|
||||
type ToggleGroupVariants = VariantProps<typeof toggleVariants>;
|
||||
|
||||
const props = defineProps<
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Effects 目录
|
||||
|
||||
`effects` 目录专门用于存放与副作用相关的代码和逻辑。如果你的包具有以下特点,建议将其放置在 `effects` 目录下:
|
||||
`effects` 目录专门用于存放与轻微耦合相关的代码和逻辑。如果你的包具有以下特点,建议将其放置在 `effects` 目录下:
|
||||
|
||||
- **状态管理**:使用状态管理框架 `pinia`,并包含处理副作用(如异步操作、API 调用)的部分。
|
||||
- **用户偏好设置**:使用 `@vben-core/preferences` 处理用户偏好设置,涉及本地存储或浏览器缓存逻辑(如使用 `localStorage`)。
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { EllipsisText } from '..';
|
||||
|
||||
describe('ellipsis-text.vue', () => {
|
||||
it('renders the correct content and truncates text', async () => {
|
||||
const wrapper = mount(EllipsisText, {
|
||||
props: {
|
||||
line: 1,
|
||||
title: 'Test Title',
|
||||
},
|
||||
slots: {
|
||||
default: 'This is a very long text that should be truncated.',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain('This is a very long text');
|
||||
// 检查 ellipsis 是否应用了正确的 class
|
||||
const ellipsis = wrapper.find('.truncate');
|
||||
expect(ellipsis.exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('expands text on click if expand is true', async () => {
|
||||
const wrapper = mount(EllipsisText, {
|
||||
props: {
|
||||
expand: true,
|
||||
line: 1,
|
||||
},
|
||||
slots: {
|
||||
default: 'This is a very long text that should be truncated.',
|
||||
},
|
||||
});
|
||||
|
||||
const ellipsis = wrapper.find('.truncate');
|
||||
await ellipsis.trigger('click');
|
||||
expect(wrapper.emitted('expandChange')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -23,7 +23,7 @@ interface Props {
|
||||
* 提示框位置
|
||||
* @default 'top'
|
||||
*/
|
||||
placement: 'bottom' | 'left' | 'right' | 'top';
|
||||
placement?: 'bottom' | 'left' | 'right' | 'top';
|
||||
/**
|
||||
* 是否启用文本提示框
|
||||
* @default true
|
||||
@@ -49,8 +49,9 @@ interface Props {
|
||||
* 提示框内容区域样式
|
||||
* @default { textAlign: 'justify' }
|
||||
*/
|
||||
tooltipOverlayStyle?: CSSProperties; // 提示框内容区域样式
|
||||
tooltipOverlayStyle?: CSSProperties;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
expand: false,
|
||||
line: 1,
|
||||
@@ -99,6 +100,14 @@ function onExpand() {
|
||||
|
||||
emit('expandChange', !isExpanded);
|
||||
}
|
||||
|
||||
function handleExpand() {
|
||||
if (props.expand) {
|
||||
onExpand();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<VbenTooltip
|
||||
@@ -110,7 +119,6 @@ function onExpand() {
|
||||
backgroundColor: tooltipBackgroundColor,
|
||||
}"
|
||||
:disabled="!showTooltip"
|
||||
:overlay-style="tooltipOverlayStyle"
|
||||
:side="placement"
|
||||
>
|
||||
<slot name="tooltip">
|
||||
@@ -127,7 +135,7 @@ function onExpand() {
|
||||
}"
|
||||
:style="`-webkit-line-clamp: ${line}; max-width: ${textMaxWidth};`"
|
||||
class="cursor-text overflow-hidden"
|
||||
@click="expand ? onExpand() : () => false"
|
||||
@click="handleExpand"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<slot></slot>
|
||||
2
packages/effects/common-ui/src/components/index.ts
Normal file
2
packages/effects/common-ui/src/components/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './ellipsis-text';
|
||||
export * from './page';
|
||||
@@ -0,0 +1,74 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Page } from '..';
|
||||
|
||||
describe('page.vue', () => {
|
||||
it('renders title when passed', () => {
|
||||
const wrapper = mount(Page, {
|
||||
props: {
|
||||
title: 'Test Title',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain('Test Title');
|
||||
});
|
||||
|
||||
it('renders description when passed', () => {
|
||||
const wrapper = mount(Page, {
|
||||
props: {
|
||||
description: 'Test Description',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain('Test Description');
|
||||
});
|
||||
|
||||
it('renders default slot content', () => {
|
||||
const wrapper = mount(Page, {
|
||||
slots: {
|
||||
default: '<p>Default Slot Content</p>',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toContain('<p>Default Slot Content</p>');
|
||||
});
|
||||
|
||||
it('renders footer slot when showFooter is true', () => {
|
||||
const wrapper = mount(Page, {
|
||||
props: {
|
||||
showFooter: true,
|
||||
},
|
||||
slots: {
|
||||
footer: '<p>Footer Slot Content</p>',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toContain('<p>Footer Slot Content</p>');
|
||||
});
|
||||
|
||||
it('applies the custom contentClass', () => {
|
||||
const wrapper = mount(Page, {
|
||||
props: {
|
||||
contentClass: 'custom-class',
|
||||
},
|
||||
});
|
||||
|
||||
const contentDiv = wrapper.find('.m-4');
|
||||
expect(contentDiv.classes()).toContain('custom-class');
|
||||
});
|
||||
|
||||
it('does not render description slot if description prop is provided', () => {
|
||||
const wrapper = mount(Page, {
|
||||
props: {
|
||||
description: 'Test Description',
|
||||
},
|
||||
slots: {
|
||||
description: '<p>Description Slot Content</p>',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain('Test Description');
|
||||
expect(wrapper.html()).not.toContain('Description Slot Content');
|
||||
});
|
||||
});
|
||||
1
packages/effects/common-ui/src/components/page/index.ts
Normal file
1
packages/effects/common-ui/src/components/page/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as Page } from './page.vue';
|
||||
45
packages/effects/common-ui/src/components/page/page.vue
Normal file
45
packages/effects/common-ui/src/components/page/page.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
contentClass?: string;
|
||||
showFooter?: boolean;
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
name: 'Page',
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
contentClass: '',
|
||||
description: '',
|
||||
showFooter: false,
|
||||
title: '',
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative h-full">
|
||||
<div
|
||||
v-if="description || $slots.description || title"
|
||||
class="bg-card px-6 py-4"
|
||||
>
|
||||
<div class="mb-2 flex justify-between text-xl font-bold leading-10">
|
||||
{{ title }}
|
||||
</div>
|
||||
<template v-if="description">{{ description }}</template>
|
||||
<slot v-else name="description"></slot>
|
||||
</div>
|
||||
|
||||
<div :class="contentClass" class="m-4">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="props.showFooter"
|
||||
class="bg-card align-center absolute bottom-0 left-0 right-0 flex px-6 py-4"
|
||||
>
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,6 +1,3 @@
|
||||
export * from './about';
|
||||
export * from './authentication';
|
||||
export * from './dashboard';
|
||||
export * from './ellipsis-text';
|
||||
export * from './fallback';
|
||||
export * from './components';
|
||||
export * from './ui';
|
||||
export { useToast } from '@vben-core/shadcn-ui';
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
} from '@vben/constants';
|
||||
import { VbenLink, VbenRenderContent } from '@vben-core/shadcn-ui';
|
||||
|
||||
import { Page } from '../../components';
|
||||
|
||||
interface Props extends AboutProps {}
|
||||
|
||||
defineOptions({
|
||||
@@ -119,18 +121,18 @@ const devDependenciesItems = Object.keys(devDependencies).map((key) => ({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-5">
|
||||
<Page :title="title">
|
||||
<template #description>
|
||||
<p class="text-foreground mt-3 text-sm leading-6">
|
||||
<VbenLink :href="VBEN_GITHUB_URL">
|
||||
{{ name }}
|
||||
</VbenLink>
|
||||
{{ description }}
|
||||
</p>
|
||||
</template>
|
||||
<div class="card-box p-5">
|
||||
<div>
|
||||
<h3 class="text-foreground text-2xl font-semibold leading-7">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<p class="text-foreground/80 mt-3 text-sm leading-6">
|
||||
<VbenLink :href="VBEN_GITHUB_URL">
|
||||
{{ name }}
|
||||
</VbenLink>
|
||||
{{ description }}
|
||||
</p>
|
||||
<h5 class="text-foreground text-lg">基本信息</h5>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<dl class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
||||
@@ -139,7 +141,7 @@ const devDependenciesItems = Object.keys(devDependencies).map((key) => ({
|
||||
<dt class="text-foreground text-sm font-medium leading-6">
|
||||
{{ item.title }}
|
||||
</dt>
|
||||
<dd class="text-foreground/80 mt-1 text-sm leading-6 sm:mt-2">
|
||||
<dd class="text-foreground mt-1 text-sm leading-6 sm:mt-2">
|
||||
<VbenRenderContent :content="item.content" />
|
||||
</dd>
|
||||
</div>
|
||||
@@ -159,7 +161,7 @@ const devDependenciesItems = Object.keys(devDependencies).map((key) => ({
|
||||
<dt class="text-foreground text-sm">
|
||||
{{ item.title }}
|
||||
</dt>
|
||||
<dd class="text-foreground/60 mt-1 text-sm sm:mt-2">
|
||||
<dd class="text-foreground/80 mt-1 text-sm sm:mt-2">
|
||||
<VbenRenderContent :content="item.content" />
|
||||
</dd>
|
||||
</div>
|
||||
@@ -178,7 +180,7 @@ const devDependenciesItems = Object.keys(devDependencies).map((key) => ({
|
||||
<dt class="text-foreground text-sm">
|
||||
{{ item.title }}
|
||||
</dt>
|
||||
<dd class="text-foreground/60 mt-1 text-sm sm:mt-2">
|
||||
<dd class="text-foreground/80 mt-1 text-sm sm:mt-2">
|
||||
<VbenRenderContent :content="item.content" />
|
||||
</dd>
|
||||
</div>
|
||||
@@ -186,5 +188,5 @@ const devDependenciesItems = Object.keys(devDependencies).map((key) => ({
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { LoginCodeEmits } from './typings';
|
||||
import type { LoginCodeEmits } from './types';
|
||||
|
||||
import { computed, onBeforeUnmount, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -8,4 +8,4 @@ export type {
|
||||
AuthenticationProps,
|
||||
LoginAndRegisterParams,
|
||||
LoginCodeParams,
|
||||
} from './typings';
|
||||
} from './types';
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { AuthenticationProps, LoginAndRegisterParams } from './typings';
|
||||
import type { AuthenticationProps, LoginAndRegisterParams } from './types';
|
||||
|
||||
import { useForwardPropsEmits } from '@vben/hooks';
|
||||
import {
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { AuthenticationProps, LoginEmits } from './typings';
|
||||
import type { AuthenticationProps, LoginEmits } from './types';
|
||||
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { RegisterEmits } from './typings';
|
||||
import type { RegisterEmits } from './types';
|
||||
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
4
packages/effects/common-ui/src/ui/index.ts
Normal file
4
packages/effects/common-ui/src/ui/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './about';
|
||||
export * from './authentication';
|
||||
export * from './dashboard';
|
||||
export * from './fallback';
|
||||
@@ -6,7 +6,6 @@ import { preferences, usePreferences } from '@vben/preferences';
|
||||
|
||||
import AuthenticationFormView from './form.vue';
|
||||
import SloganIcon from './icons/slogan.vue';
|
||||
import Toolbar from './toolbar.vue';
|
||||
|
||||
defineOptions({ name: 'Authentication' });
|
||||
|
||||
@@ -56,11 +55,7 @@ const logoSource = computed(() => preferences.logo.source);
|
||||
<div v-if="authPanelCenter" class="flex-center bg-authentication w-full">
|
||||
<AuthenticationFormView
|
||||
class="md:bg-background w-full rounded-3xl pb-20 shadow-2xl md:w-2/3 lg:w-1/2 xl:w-2/5"
|
||||
>
|
||||
<template #toolbar>
|
||||
<Toolbar />
|
||||
</template>
|
||||
</AuthenticationFormView>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 右侧认证面板 -->
|
||||
|
||||
@@ -30,7 +30,7 @@ async function handleSelect(key: string) {
|
||||
<Menu
|
||||
:accordion="accordion"
|
||||
:collapse="collapse"
|
||||
:default-active="route.path"
|
||||
:default-active="route.meta?.activePath || route.path"
|
||||
:menus="menus"
|
||||
:rounded="rounded"
|
||||
:theme="theme"
|
||||
|
||||
@@ -81,7 +81,7 @@ function useExtraMenu() {
|
||||
watch(
|
||||
() => route.path,
|
||||
(path) => {
|
||||
const currentPath = path;
|
||||
const currentPath = route.meta?.activePath || path;
|
||||
// if (preferences.sidebar.expandOnHover) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
@@ -113,7 +113,7 @@ function useMixedMenu() {
|
||||
|
||||
// 初始化计算侧边菜单
|
||||
onBeforeMount(() => {
|
||||
calcSideMenus();
|
||||
calcSideMenus(route.meta?.activePath || route.path);
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -100,15 +100,11 @@ export function useTabbar() {
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
// 这里不能用route,用route时,vue-router会自动将父级meta进行合并
|
||||
const routes = router.getRoutes();
|
||||
const currentRoute = routes.find((item) => item.path === route.path);
|
||||
if (currentRoute) {
|
||||
tabbarStore.addTab({
|
||||
...route,
|
||||
meta: currentRoute.meta,
|
||||
} as unknown as RouteLocationNormalizedGeneric);
|
||||
}
|
||||
const meta = route.matched?.[route.matched.length - 1]?.meta;
|
||||
tabbarStore.addTab({
|
||||
...route,
|
||||
meta: meta || route.meta,
|
||||
});
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import type { RegisterEmits } from './typings';
|
||||
|
||||
import { computed, reactive } from 'vue';
|
||||
|
||||
import {
|
||||
@@ -19,6 +17,14 @@ interface Props {
|
||||
text?: string;
|
||||
}
|
||||
|
||||
interface LockAndRegisterParams {
|
||||
lockScreenPassword: string;
|
||||
}
|
||||
|
||||
interface RegisterEmits {
|
||||
submit: [LockAndRegisterParams];
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
name: 'LockScreenModal',
|
||||
});
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
interface LockAndRegisterParams {
|
||||
lockScreenPassword: string;
|
||||
}
|
||||
|
||||
interface RegisterEmits {
|
||||
submit: [LockAndRegisterParams];
|
||||
}
|
||||
|
||||
export type { LockAndRegisterParams, RegisterEmits };
|
||||
Reference in New Issue
Block a user