Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev-v5
commit
e4240806b7
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
## 新增组件库应用
|
## 新增组件库应用
|
||||||
|
|
||||||
如果你想用其他别的组件库,你只需要按一下步骤进行操作:
|
如果你想用其他别的组件库,你只需要按以下步骤进行操作:
|
||||||
|
|
||||||
1. 在`apps`内创建一个新的文件夹,例如`apps/web-xxx`。
|
1. 在`apps`内创建一个新的文件夹,例如`apps/web-xxx`。
|
||||||
2. 更改`apps/web-xxx/package.json`的`name`字段为`web-xxx`。
|
2. 更改`apps/web-xxx/package.json`的`name`字段为`web-xxx`。
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { interopDefault } from '../util';
|
||||||
|
|
||||||
export async function vue(): Promise<Linter.Config[]> {
|
export async function vue(): Promise<Linter.Config[]> {
|
||||||
const [pluginVue, parserVue, parserTs] = await Promise.all([
|
const [pluginVue, parserVue, parserTs] = await Promise.all([
|
||||||
// @ts-expect-error missing types
|
|
||||||
interopDefault(import('eslint-plugin-vue')),
|
interopDefault(import('eslint-plugin-vue')),
|
||||||
interopDefault(import('vue-eslint-parser')),
|
interopDefault(import('vue-eslint-parser')),
|
||||||
// @ts-expect-error missing types
|
// @ts-expect-error missing types
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { UserConfig } from 'vite';
|
import type { CSSOptions, UserConfig } from 'vite';
|
||||||
|
|
||||||
import type { DefineApplicationOptions } from '../typing';
|
import type { DefineApplicationOptions } from '../typing';
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCssOptions(injectGlobalScss = true) {
|
function createCssOptions(injectGlobalScss = true): CSSOptions {
|
||||||
const root = findMonorepoRoot();
|
const root = findMonorepoRoot();
|
||||||
return {
|
return {
|
||||||
preprocessorOptions: injectGlobalScss
|
preprocessorOptions: injectGlobalScss
|
||||||
|
|
|
@ -110,6 +110,7 @@
|
||||||
"@ast-grep/napi": "catalog:",
|
"@ast-grep/napi": "catalog:",
|
||||||
"@ctrl/tinycolor": "catalog:",
|
"@ctrl/tinycolor": "catalog:",
|
||||||
"clsx": "catalog:",
|
"clsx": "catalog:",
|
||||||
|
"esbuild": "0.24.0",
|
||||||
"pinia": "catalog:",
|
"pinia": "catalog:",
|
||||||
"vue": "catalog:"
|
"vue": "catalog:"
|
||||||
},
|
},
|
||||||
|
|
|
@ -28,6 +28,7 @@ export {
|
||||||
Fullscreen,
|
Fullscreen,
|
||||||
Github,
|
Github,
|
||||||
Grip,
|
Grip,
|
||||||
|
GripVertical,
|
||||||
Info,
|
Info,
|
||||||
InspectionPanel,
|
InspectionPanel,
|
||||||
Languages,
|
Languages,
|
||||||
|
|
|
@ -166,7 +166,7 @@ const headerStyle = computed((): CSSProperties => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...(isSidebarMixed ? { display: 'flex', justifyContent: 'center' } : {}),
|
...(isSidebarMixed ? { display: 'flex', justifyContent: 'center' } : {}),
|
||||||
height: `${headerHeight}px`,
|
height: `${headerHeight - 1}px`,
|
||||||
...contentWidthStyle.value,
|
...contentWidthStyle.value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ export * from './pagination';
|
||||||
export * from './pin-input';
|
export * from './pin-input';
|
||||||
export * from './popover';
|
export * from './popover';
|
||||||
export * from './radio-group';
|
export * from './radio-group';
|
||||||
|
export * from './resizable';
|
||||||
export * from './scroll-area';
|
export * from './scroll-area';
|
||||||
export * from './select';
|
export * from './select';
|
||||||
export * from './separator';
|
export * from './separator';
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, type HTMLAttributes } from 'vue';
|
||||||
|
|
||||||
|
import { GripVertical } from '@vben-core/icons';
|
||||||
|
import { cn } from '@vben-core/shared/utils';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SplitterResizeHandle,
|
||||||
|
type SplitterResizeHandleEmits,
|
||||||
|
type SplitterResizeHandleProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue';
|
||||||
|
|
||||||
|
const props = defineProps<
|
||||||
|
{
|
||||||
|
class?: HTMLAttributes['class'];
|
||||||
|
withHandle?: boolean;
|
||||||
|
} & SplitterResizeHandleProps
|
||||||
|
>();
|
||||||
|
const emits = defineEmits<SplitterResizeHandleEmits>();
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props;
|
||||||
|
return delegated;
|
||||||
|
});
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SplitterResizeHandle
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-1 [&[data-orientation=vertical]>div]:rotate-90 [&[data-orientation=vertical]]:h-px [&[data-orientation=vertical]]:w-full [&[data-orientation=vertical]]:after:left-0 [&[data-orientation=vertical]]:after:h-1 [&[data-orientation=vertical]]:after:w-full [&[data-orientation=vertical]]:after:-translate-y-1/2 [&[data-orientation=vertical]]:after:translate-x-0',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template v-if="props.withHandle">
|
||||||
|
<div
|
||||||
|
class="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-sm border"
|
||||||
|
>
|
||||||
|
<GripVertical class="h-2.5 w-2.5" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</SplitterResizeHandle>
|
||||||
|
</template>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, type HTMLAttributes } from 'vue';
|
||||||
|
|
||||||
|
import { cn } from '@vben-core/shared/utils';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SplitterGroup,
|
||||||
|
type SplitterGroupEmits,
|
||||||
|
type SplitterGroupProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue';
|
||||||
|
|
||||||
|
const props = defineProps<
|
||||||
|
{ class?: HTMLAttributes['class'] } & SplitterGroupProps
|
||||||
|
>();
|
||||||
|
const emits = defineEmits<SplitterGroupEmits>();
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props;
|
||||||
|
return delegated;
|
||||||
|
});
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SplitterGroup
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'flex h-full w-full data-[panel-group-direction=vertical]:flex-col',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</SplitterGroup>
|
||||||
|
</template>
|
|
@ -0,0 +1,3 @@
|
||||||
|
export { default as ResizableHandle } from './ResizableHandle.vue';
|
||||||
|
export { default as ResizablePanelGroup } from './ResizablePanelGroup.vue';
|
||||||
|
export { SplitterPanel as ResizablePanel } from 'radix-vue';
|
|
@ -38,7 +38,7 @@ const delegatedProps = computed(() => {
|
||||||
>
|
>
|
||||||
<ScrollAreaViewport
|
<ScrollAreaViewport
|
||||||
as-child
|
as-child
|
||||||
class="h-full w-full rounded-[inherit]"
|
class="h-full w-full rounded-[inherit] focus:outline-none"
|
||||||
@scroll="onScroll"
|
@scroll="onScroll"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { ColPageProps } from './types';
|
||||||
|
|
||||||
|
import { computed, ref, useSlots } from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ResizableHandle,
|
||||||
|
ResizablePanel,
|
||||||
|
ResizablePanelGroup,
|
||||||
|
} from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
|
import Page from '../page/page.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ColPage',
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<ColPageProps>(), {
|
||||||
|
leftWidth: 30,
|
||||||
|
rightWidth: 70,
|
||||||
|
resizable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { leftWidth: _, ...delegated } = props;
|
||||||
|
return delegated;
|
||||||
|
});
|
||||||
|
|
||||||
|
const slots = useSlots();
|
||||||
|
|
||||||
|
const delegatedSlots = computed(() => {
|
||||||
|
const resultSlots: string[] = [];
|
||||||
|
|
||||||
|
for (const key of Object.keys(slots)) {
|
||||||
|
if (!['default', 'left'].includes(key)) {
|
||||||
|
resultSlots.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultSlots;
|
||||||
|
});
|
||||||
|
|
||||||
|
const leftPanelRef = ref<InstanceType<typeof ResizablePanel>>();
|
||||||
|
|
||||||
|
function expandLeft() {
|
||||||
|
leftPanelRef.value?.expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
function collapseLeft() {
|
||||||
|
leftPanelRef.value?.collapse();
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
expandLeft,
|
||||||
|
collapseLeft,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Page v-bind="delegatedProps">
|
||||||
|
<!-- 继承默认的slot -->
|
||||||
|
<template
|
||||||
|
v-for="slotName in delegatedSlots"
|
||||||
|
:key="slotName"
|
||||||
|
#[slotName]="slotProps"
|
||||||
|
>
|
||||||
|
<slot :name="slotName" v-bind="slotProps"></slot>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<ResizablePanelGroup class="w-full" direction="horizontal">
|
||||||
|
<ResizablePanel
|
||||||
|
ref="leftPanelRef"
|
||||||
|
:collapsed-size="leftCollapsedWidth"
|
||||||
|
:collapsible="leftCollapsible"
|
||||||
|
:default-size="leftWidth"
|
||||||
|
:max-size="leftMaxWidth"
|
||||||
|
:min-size="leftMinWidth"
|
||||||
|
>
|
||||||
|
<template #default="slotProps">
|
||||||
|
<slot
|
||||||
|
name="left"
|
||||||
|
v-bind="{
|
||||||
|
...slotProps,
|
||||||
|
expand: expandLeft,
|
||||||
|
collapse: collapseLeft,
|
||||||
|
}"
|
||||||
|
></slot>
|
||||||
|
</template>
|
||||||
|
</ResizablePanel>
|
||||||
|
<ResizableHandle
|
||||||
|
v-if="resizable"
|
||||||
|
:style="{ backgroundColor: splitLine ? undefined : 'transparent' }"
|
||||||
|
:with-handle="splitHandle"
|
||||||
|
/>
|
||||||
|
<ResizablePanel
|
||||||
|
:collapsed-size="rightCollapsedWidth"
|
||||||
|
:collapsible="rightCollapsible"
|
||||||
|
:default-size="rightWidth"
|
||||||
|
:max-size="rightMaxWidth"
|
||||||
|
:min-size="rightMinWidth"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
<slot></slot>
|
||||||
|
</template>
|
||||||
|
</ResizablePanel>
|
||||||
|
</ResizablePanelGroup>
|
||||||
|
</Page>
|
||||||
|
</template>
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as ColPage } from './col-page.vue';
|
||||||
|
export * from './types';
|
|
@ -0,0 +1,26 @@
|
||||||
|
import type { PageProps } from '../page/types';
|
||||||
|
|
||||||
|
export interface ColPageProps extends PageProps {
|
||||||
|
/**
|
||||||
|
* 左侧宽度
|
||||||
|
* @default 30
|
||||||
|
*/
|
||||||
|
leftWidth?: number;
|
||||||
|
leftMinWidth?: number;
|
||||||
|
leftMaxWidth?: number;
|
||||||
|
leftCollapsedWidth?: number;
|
||||||
|
leftCollapsible?: boolean;
|
||||||
|
/**
|
||||||
|
* 右侧宽度
|
||||||
|
* @default 70
|
||||||
|
*/
|
||||||
|
rightWidth?: number;
|
||||||
|
rightMinWidth?: number;
|
||||||
|
rightCollapsedWidth?: number;
|
||||||
|
rightMaxWidth?: number;
|
||||||
|
rightCollapsible?: boolean;
|
||||||
|
|
||||||
|
resizable?: boolean;
|
||||||
|
splitLine?: boolean;
|
||||||
|
splitHandle?: boolean;
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
export * from './api-component';
|
export * from './api-component';
|
||||||
export * from './captcha';
|
export * from './captcha';
|
||||||
|
export * from './col-page';
|
||||||
export * from './ellipsis-text';
|
export * from './ellipsis-text';
|
||||||
export * from './icon-picker';
|
export * from './icon-picker';
|
||||||
export * from './page';
|
export * from './page';
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export { default as Page } from './page.vue';
|
export { default as Page } from './page.vue';
|
||||||
|
export * from './types';
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { PageProps } from './types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
nextTick,
|
nextTick,
|
||||||
|
@ -11,23 +13,11 @@ import {
|
||||||
import { CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT } from '@vben-core/shared/constants';
|
import { CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT } from '@vben-core/shared/constants';
|
||||||
import { cn } from '@vben-core/shared/utils';
|
import { cn } from '@vben-core/shared/utils';
|
||||||
|
|
||||||
interface Props {
|
|
||||||
title?: string;
|
|
||||||
description?: string;
|
|
||||||
contentClass?: string;
|
|
||||||
/**
|
|
||||||
* 根据content可见高度自适应
|
|
||||||
*/
|
|
||||||
autoContentHeight?: boolean;
|
|
||||||
headerClass?: string;
|
|
||||||
footerClass?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'Page',
|
name: 'Page',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { autoContentHeight = false } = defineProps<Props>();
|
const { autoContentHeight = false } = defineProps<PageProps>();
|
||||||
|
|
||||||
const headerHeight = ref(0);
|
const headerHeight = ref(0);
|
||||||
const footerHeight = ref(0);
|
const footerHeight = ref(0);
|
||||||
|
@ -100,7 +90,7 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="contentClass" :style="contentStyle" class="h-full p-4">
|
<div :class="cn('h-full p-4', contentClass)" :style="contentStyle">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
export interface PageProps {
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
contentClass?: string;
|
||||||
|
/**
|
||||||
|
* 根据content可见高度自适应
|
||||||
|
*/
|
||||||
|
autoContentHeight?: boolean;
|
||||||
|
headerClass?: string;
|
||||||
|
footerClass?: string;
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ defineEmits(['click']);
|
||||||
'border-b-0': index < 3,
|
'border-b-0': index < 3,
|
||||||
'pb-4': index > 2,
|
'pb-4': index > 2,
|
||||||
}"
|
}"
|
||||||
class="border-border group w-full cursor-pointer border-b border-r border-t p-4 transition-all hover:shadow-xl md:w-1/2 lg:w-1/3"
|
class="border-border group w-full cursor-pointer border-r border-t p-4 transition-all hover:shadow-xl md:w-1/2 lg:w-1/3"
|
||||||
>
|
>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<VbenIcon
|
<VbenIcon
|
||||||
|
|
|
@ -38,7 +38,7 @@ defineEmits(['click']);
|
||||||
'pb-4': index > 2,
|
'pb-4': index > 2,
|
||||||
'border-b-0': index < 3,
|
'border-b-0': index < 3,
|
||||||
}"
|
}"
|
||||||
class="flex-col-center border-border group w-1/3 cursor-pointer border-b border-r border-t py-8 hover:shadow-xl"
|
class="flex-col-center border-border group w-1/3 cursor-pointer border-r border-t py-8 hover:shadow-xl"
|
||||||
@click="$emit('click', item)"
|
@click="$emit('click', item)"
|
||||||
>
|
>
|
||||||
<VbenIcon
|
<VbenIcon
|
||||||
|
|
|
@ -152,7 +152,7 @@ watch(
|
||||||
);
|
);
|
||||||
|
|
||||||
// 语言更新后,刷新页面
|
// 语言更新后,刷新页面
|
||||||
watch(() => preferences.app.locale, refresh);
|
watch(() => preferences.app.locale, refresh, { flush: 'post' });
|
||||||
|
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
const headerSlots = computed(() => {
|
const headerSlots = computed(() => {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import type {
|
||||||
VxeGridListeners,
|
VxeGridListeners,
|
||||||
VxeGridPropTypes,
|
VxeGridPropTypes,
|
||||||
VxeGridProps as VxeTableGridProps,
|
VxeGridProps as VxeTableGridProps,
|
||||||
|
VxeToolbarPropTypes,
|
||||||
} from 'vxe-table';
|
} from 'vxe-table';
|
||||||
|
|
||||||
import type { ExtendedVxeGridApi, VxeGridProps } from './types';
|
import type { ExtendedVxeGridApi, VxeGridProps } from './types';
|
||||||
|
@ -107,28 +108,28 @@ const showToolbar = computed(() => {
|
||||||
const toolbarOptions = computed(() => {
|
const toolbarOptions = computed(() => {
|
||||||
const slotActions = slots[TOOLBAR_ACTIONS]?.();
|
const slotActions = slots[TOOLBAR_ACTIONS]?.();
|
||||||
const slotTools = slots[TOOLBAR_TOOLS]?.();
|
const slotTools = slots[TOOLBAR_TOOLS]?.();
|
||||||
|
const searchBtn: VxeToolbarPropTypes.ToolConfig = {
|
||||||
const toolbarConfig: VxeGridPropTypes.ToolbarConfig = {
|
|
||||||
tools:
|
|
||||||
gridOptions.value?.toolbarConfig?.search && !!formOptions.value
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
code: 'search',
|
code: 'search',
|
||||||
icon: 'vxe-icon--search',
|
icon: 'vxe-icon--search',
|
||||||
circle: true,
|
circle: true,
|
||||||
status: showSearchForm.value ? 'primary' : undefined,
|
status: showSearchForm.value ? 'primary' : undefined,
|
||||||
title: $t('common.search'),
|
title: $t('common.search'),
|
||||||
},
|
|
||||||
]
|
|
||||||
: [],
|
|
||||||
};
|
};
|
||||||
|
// 将搜索按钮合并到用户配置的toolbarConfig.tools中
|
||||||
|
const toolbarConfig: VxeGridPropTypes.ToolbarConfig = {
|
||||||
|
tools: (gridOptions.value?.toolbarConfig?.tools ??
|
||||||
|
[]) as VxeToolbarPropTypes.ToolConfig[],
|
||||||
|
};
|
||||||
|
if (gridOptions.value?.toolbarConfig?.search && !!formOptions.value) {
|
||||||
|
toolbarConfig.tools = Array.isArray(toolbarConfig.tools)
|
||||||
|
? [...toolbarConfig.tools, searchBtn]
|
||||||
|
: [searchBtn];
|
||||||
|
}
|
||||||
|
|
||||||
if (!showToolbar.value) {
|
if (!showToolbar.value) {
|
||||||
return { toolbarConfig };
|
return { toolbarConfig };
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (gridOptions.value?.toolbarConfig?.search) {
|
|
||||||
// }
|
|
||||||
// 强制使用固定的toolbar配置,不允许用户自定义
|
// 强制使用固定的toolbar配置,不允许用户自定义
|
||||||
// 减少配置的复杂度,以及后续维护的成本
|
// 减少配置的复杂度,以及后续维护的成本
|
||||||
toolbarConfig.slots = {
|
toolbarConfig.slots = {
|
||||||
|
@ -137,7 +138,6 @@ const toolbarOptions = computed(() => {
|
||||||
: {}),
|
: {}),
|
||||||
...(slotTools ? { tools: TOOLBAR_TOOLS } : {}),
|
...(slotTools ? { tools: TOOLBAR_TOOLS } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
return { toolbarConfig };
|
return { toolbarConfig };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ const options = computed(() => {
|
||||||
const mergedOptions: VxeTableGridProps = cloneDeep(
|
const mergedOptions: VxeTableGridProps = cloneDeep(
|
||||||
mergeWithArrayOverride(
|
mergeWithArrayOverride(
|
||||||
{},
|
{},
|
||||||
toolbarOptions.value,
|
toRaw(toolbarOptions.value),
|
||||||
toRaw(gridOptions.value),
|
toRaw(gridOptions.value),
|
||||||
globalGridConfig,
|
globalGridConfig,
|
||||||
),
|
),
|
||||||
|
@ -306,7 +306,7 @@ onUnmounted(() => {
|
||||||
ref="gridRef"
|
ref="gridRef"
|
||||||
:class="
|
:class="
|
||||||
cn(
|
cn(
|
||||||
'p-2 pt-0',
|
'p-2',
|
||||||
{
|
{
|
||||||
'pt-0': showToolbar && !formOptions,
|
'pt-0': showToolbar && !formOptions,
|
||||||
},
|
},
|
||||||
|
|
|
@ -56,5 +56,11 @@
|
||||||
"timestamp": "Timestamp:",
|
"timestamp": "Timestamp:",
|
||||||
"x": "x:",
|
"x": "x:",
|
||||||
"y": "y:"
|
"y": "y:"
|
||||||
|
},
|
||||||
|
"resize": {
|
||||||
|
"title": "Resize"
|
||||||
|
},
|
||||||
|
"layout": {
|
||||||
|
"col-page": "ColPage Layout"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,5 +59,8 @@
|
||||||
"timestamp": "时间戳:",
|
"timestamp": "时间戳:",
|
||||||
"x": "x:",
|
"x": "x:",
|
||||||
"y": "y:"
|
"y": "y:"
|
||||||
|
},
|
||||||
|
"layout": {
|
||||||
|
"col-page": "双列布局"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,6 +237,17 @@ const routes: RouteRecordRaw[] = [
|
||||||
title: $t('examples.resize.title'),
|
title: $t('examples.resize.title'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'ColPageDemo',
|
||||||
|
path: '/examples/layout/col-page',
|
||||||
|
component: () => import('#/views/examples/layout/col-page.vue'),
|
||||||
|
meta: {
|
||||||
|
badge: 'Alpha',
|
||||||
|
badgeVariants: 'destructive',
|
||||||
|
icon: 'material-symbols:horizontal-distribute',
|
||||||
|
title: $t('examples.layout.col-page'),
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
import { ColPage } from '@vben/common-ui';
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Checkbox,
|
||||||
|
Slider,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
const props = reactive({
|
||||||
|
leftCollapsedWidth: 5,
|
||||||
|
leftCollapsible: true,
|
||||||
|
leftMaxWidth: 50,
|
||||||
|
leftMinWidth: 20,
|
||||||
|
leftWidth: 30,
|
||||||
|
resizable: true,
|
||||||
|
rightWidth: 70,
|
||||||
|
splitHandle: false,
|
||||||
|
splitLine: false,
|
||||||
|
});
|
||||||
|
const leftMinWidth = ref(props.leftMinWidth || 1);
|
||||||
|
const leftMaxWidth = ref(props.leftMaxWidth || 100);
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<ColPage
|
||||||
|
auto-content-height
|
||||||
|
description="ColPage 是一个双列布局组件,支持左侧折叠、拖拽调整宽度等功能。"
|
||||||
|
v-bind="props"
|
||||||
|
title="ColPage 双列布局组件"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<span class="mr-2 text-2xl font-bold">ColPage 双列布局组件</span>
|
||||||
|
<Tag color="hsl(var(--destructive))">Alpha</Tag>
|
||||||
|
</template>
|
||||||
|
<template #left="{ isCollapsed, expand }">
|
||||||
|
<div v-if="isCollapsed" @click="expand">
|
||||||
|
<Tooltip title="点击展开左侧">
|
||||||
|
<Button shape="circle" type="primary">
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon class="text-2xl" icon="bi:arrow-right" />
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
:style="{ minWidth: '200px' }"
|
||||||
|
class="border-border bg-card mr-2 rounded-[var(--radius)] border p-2"
|
||||||
|
>
|
||||||
|
<p>这里是左侧内容</p>
|
||||||
|
<p>这里是左侧内容</p>
|
||||||
|
<p>这里是左侧内容</p>
|
||||||
|
<p>这里是左侧内容</p>
|
||||||
|
<p>这里是左侧内容</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<Card class="ml-2" title="基本使用">
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Checkbox v-model:checked="props.resizable">可拖动调整宽度</Checkbox>
|
||||||
|
<Checkbox v-model:checked="props.splitLine">显示拖动分隔线</Checkbox>
|
||||||
|
<Checkbox v-model:checked="props.splitHandle">显示拖动手柄</Checkbox>
|
||||||
|
<Checkbox v-model:checked="props.leftCollapsible">
|
||||||
|
左侧可折叠
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span>左侧最小宽度百分比:</span>
|
||||||
|
<Slider
|
||||||
|
v-model:value="leftMinWidth"
|
||||||
|
:max="props.leftMaxWidth - 1"
|
||||||
|
:min="1"
|
||||||
|
style="width: 100px"
|
||||||
|
@after-change="(value) => (props.leftMinWidth = value as number)"
|
||||||
|
/>
|
||||||
|
<span>左侧最大宽度百分比:</span>
|
||||||
|
<Slider
|
||||||
|
v-model:value="props.leftMaxWidth"
|
||||||
|
:max="100"
|
||||||
|
:min="leftMaxWidth + 1"
|
||||||
|
style="width: 100px"
|
||||||
|
@after-change="(value) => (props.leftMaxWidth = value as number)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Alert message="实验性的组件" show-icon type="warning">
|
||||||
|
<template #description>
|
||||||
|
<p>
|
||||||
|
双列布局组件是一个在Page组件上扩展的相对基础的布局组件,支持左侧折叠(当拖拽导致左侧宽度比最小宽度还要小时,还可以进入折叠状态)、拖拽调整宽度等功能。
|
||||||
|
</p>
|
||||||
|
<p>以上宽度设置的数值是百分比,最小值为1,最大值为100。</p>
|
||||||
|
<p class="font-bold text-red-600">
|
||||||
|
这是一个实验性的组件,用法可能会发生变动,也可能最终不会被采用。在其用法正式出现在文档中之前,不建议在生产环境中使用。
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</Alert>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</ColPage>
|
||||||
|
</template>
|
808
pnpm-lock.yaml
808
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -15,15 +15,15 @@ packages:
|
||||||
catalog:
|
catalog:
|
||||||
'@ast-grep/napi': ^0.31.1
|
'@ast-grep/napi': ^0.31.1
|
||||||
'@changesets/changelog-github': ^0.5.0
|
'@changesets/changelog-github': ^0.5.0
|
||||||
'@changesets/cli': ^2.27.10
|
'@changesets/cli': ^2.27.11
|
||||||
'@changesets/git': ^3.0.2
|
'@changesets/git': ^3.0.2
|
||||||
'@clack/prompts': ^0.8.2
|
'@clack/prompts': ^0.9.0
|
||||||
'@commitlint/cli': ^19.6.0
|
'@commitlint/cli': ^19.6.1
|
||||||
'@commitlint/config-conventional': ^19.6.0
|
'@commitlint/config-conventional': ^19.6.0
|
||||||
'@ctrl/tinycolor': ^4.1.0
|
'@ctrl/tinycolor': ^4.1.0
|
||||||
'@eslint/js': ^9.16.0
|
'@eslint/js': ^9.17.0
|
||||||
'@faker-js/faker': ^9.3.0
|
'@faker-js/faker': ^9.3.0
|
||||||
'@iconify/json': ^2.2.281
|
'@iconify/json': ^2.2.286
|
||||||
'@iconify/tailwind': ^1.2.0
|
'@iconify/tailwind': ^1.2.0
|
||||||
'@iconify/vue': ^4.2.0
|
'@iconify/vue': ^4.2.0
|
||||||
'@intlify/core-base': ^10.0.5
|
'@intlify/core-base': ^10.0.5
|
||||||
|
@ -32,11 +32,11 @@ catalog:
|
||||||
'@manypkg/get-packages': ^2.2.2
|
'@manypkg/get-packages': ^2.2.2
|
||||||
'@nolebase/vitepress-plugin-git-changelog': ^2.11.1
|
'@nolebase/vitepress-plugin-git-changelog': ^2.11.1
|
||||||
'@playwright/test': ^1.49.1
|
'@playwright/test': ^1.49.1
|
||||||
'@pnpm/workspace.read-manifest': ^1000.0.0
|
'@pnpm/workspace.read-manifest': ^1000.0.1
|
||||||
'@stylistic/stylelint-plugin': ^3.1.1
|
'@stylistic/stylelint-plugin': ^3.1.1
|
||||||
'@tailwindcss/nesting': 0.0.0-insiders.565cd3e
|
'@tailwindcss/nesting': 0.0.0-insiders.565cd3e
|
||||||
'@tailwindcss/typography': ^0.5.15
|
'@tailwindcss/typography': ^0.5.15
|
||||||
'@tanstack/vue-query': ^5.62.7
|
'@tanstack/vue-query': ^5.62.8
|
||||||
'@tanstack/vue-store': ^0.6.0
|
'@tanstack/vue-store': ^0.6.0
|
||||||
'@types/archiver': ^6.0.3
|
'@types/archiver': ^6.0.3
|
||||||
'@types/crypto-js': ^4.2.2
|
'@types/crypto-js': ^4.2.2
|
||||||
|
@ -46,14 +46,14 @@ catalog:
|
||||||
'@types/lodash.clonedeep': ^4.5.9
|
'@types/lodash.clonedeep': ^4.5.9
|
||||||
'@types/lodash.get': ^4.4.9
|
'@types/lodash.get': ^4.4.9
|
||||||
'@types/lodash.isequal': ^4.5.8
|
'@types/lodash.isequal': ^4.5.8
|
||||||
'@types/node': ^22.10.1
|
'@types/node': ^22.10.2
|
||||||
'@types/nprogress': ^0.2.3
|
'@types/nprogress': ^0.2.3
|
||||||
'@types/postcss-import': ^14.0.3
|
'@types/postcss-import': ^14.0.3
|
||||||
'@types/qrcode': ^1.5.5
|
'@types/qrcode': ^1.5.5
|
||||||
'@types/qs': ^6.9.17
|
'@types/qs': ^6.9.17
|
||||||
'@types/sortablejs': ^1.15.8
|
'@types/sortablejs': ^1.15.8
|
||||||
'@typescript-eslint/eslint-plugin': ^8.18.0
|
'@typescript-eslint/eslint-plugin': ^8.18.1
|
||||||
'@typescript-eslint/parser': ^8.18.0
|
'@typescript-eslint/parser': ^8.18.1
|
||||||
'@vee-validate/zod': ^4.14.7
|
'@vee-validate/zod': ^4.14.7
|
||||||
'@vite-pwa/vitepress': ^0.5.3
|
'@vite-pwa/vitepress': ^0.5.3
|
||||||
'@vitejs/plugin-vue': ^5.2.1
|
'@vitejs/plugin-vue': ^5.2.1
|
||||||
|
@ -69,13 +69,13 @@ catalog:
|
||||||
axios: ^1.7.9
|
axios: ^1.7.9
|
||||||
axios-mock-adapter: ^2.1.0
|
axios-mock-adapter: ^2.1.0
|
||||||
cac: ^6.7.14
|
cac: ^6.7.14
|
||||||
chalk: ^5.3.0
|
chalk: ^5.4.0
|
||||||
cheerio: 1.0.0
|
cheerio: 1.0.0
|
||||||
circular-dependency-scanner: ^2.3.0
|
circular-dependency-scanner: ^2.3.0
|
||||||
class-variance-authority: ^0.7.1
|
class-variance-authority: ^0.7.1
|
||||||
clsx: ^2.1.1
|
clsx: ^2.1.1
|
||||||
commitlint-plugin-function-rules: ^4.0.1
|
commitlint-plugin-function-rules: ^4.0.1
|
||||||
consola: ^3.2.3
|
consola: ^3.3.0
|
||||||
cross-env: ^7.0.3
|
cross-env: ^7.0.3
|
||||||
crypto-js: ^4.2.0
|
crypto-js: ^4.2.0
|
||||||
cspell: ^8.16.1
|
cspell: ^8.16.1
|
||||||
|
@ -87,15 +87,15 @@ catalog:
|
||||||
depcheck: ^1.4.7
|
depcheck: ^1.4.7
|
||||||
dotenv: ^16.4.7
|
dotenv: ^16.4.7
|
||||||
echarts: ^5.5.1
|
echarts: ^5.5.1
|
||||||
element-plus: ^2.9.0
|
element-plus: ^2.9.1
|
||||||
eslint: ^9.16.0
|
eslint: ^9.17.0
|
||||||
eslint-config-turbo: ^2.3.3
|
eslint-config-turbo: ^2.3.3
|
||||||
eslint-plugin-command: ^0.2.6
|
eslint-plugin-command: ^0.2.7
|
||||||
eslint-plugin-eslint-comments: ^3.2.0
|
eslint-plugin-eslint-comments: ^3.2.0
|
||||||
eslint-plugin-import-x: ^4.5.0
|
eslint-plugin-import-x: ^4.6.1
|
||||||
eslint-plugin-jsdoc: ^50.6.1
|
eslint-plugin-jsdoc: ^50.6.1
|
||||||
eslint-plugin-jsonc: ^2.18.2
|
eslint-plugin-jsonc: ^2.18.2
|
||||||
eslint-plugin-n: ^17.15.0
|
eslint-plugin-n: ^17.15.1
|
||||||
eslint-plugin-no-only-tests: ^3.3.0
|
eslint-plugin-no-only-tests: ^3.3.0
|
||||||
eslint-plugin-perfectionist: ^3.9.1
|
eslint-plugin-perfectionist: ^3.9.1
|
||||||
eslint-plugin-prettier: ^5.2.1
|
eslint-plugin-prettier: ^5.2.1
|
||||||
|
@ -107,34 +107,34 @@ catalog:
|
||||||
execa: ^9.5.2
|
execa: ^9.5.2
|
||||||
find-up: ^7.0.0
|
find-up: ^7.0.0
|
||||||
get-port: ^7.1.0
|
get-port: ^7.1.0
|
||||||
globals: ^15.13.0
|
globals: ^15.14.0
|
||||||
h3: ^1.13.0
|
h3: ^1.13.0
|
||||||
happy-dom: ^15.11.6
|
happy-dom: ^15.11.6
|
||||||
highlight.js: ^11.10.0
|
highlight.js: ^11.10.0
|
||||||
html-minifier-terser: ^7.2.0
|
html-minifier-terser: ^7.2.0
|
||||||
husky: ^9.1.7
|
husky: ^9.1.7
|
||||||
is-ci: ^3.0.1
|
is-ci: ^4.1.0
|
||||||
jsonc-eslint-parser: ^2.4.0
|
jsonc-eslint-parser: ^2.4.0
|
||||||
jsonwebtoken: ^9.0.2
|
jsonwebtoken: ^9.0.2
|
||||||
lint-staged: ^15.2.11
|
lint-staged: ^15.2.11
|
||||||
lodash.clonedeep: ^4.5.0
|
lodash.clonedeep: ^4.5.0
|
||||||
lodash.get: ^4.4.2
|
lodash.get: ^4.4.2
|
||||||
lodash.isequal: ^4.5.0
|
lodash.isequal: ^4.5.0
|
||||||
lucide-vue-next: ^0.465.0
|
lucide-vue-next: ^0.469.0
|
||||||
medium-zoom: ^1.1.0
|
medium-zoom: ^1.1.0
|
||||||
naive-ui: ^2.40.3
|
naive-ui: ^2.40.4
|
||||||
nitropack: ^2.10.4
|
nitropack: ^2.10.4
|
||||||
nprogress: ^0.2.0
|
nprogress: ^0.2.0
|
||||||
ora: ^8.1.1
|
ora: ^8.1.1
|
||||||
pinia: 2.2.2
|
pinia: 2.2.2
|
||||||
pinia-plugin-persistedstate: ^4.1.3
|
pinia-plugin-persistedstate: ^4.2.0
|
||||||
pkg-types: ^1.2.1
|
pkg-types: ^1.2.1
|
||||||
playwright: ^1.49.1
|
playwright: ^1.49.1
|
||||||
postcss: ^8.4.49
|
postcss: ^8.4.49
|
||||||
postcss-antd-fixes: ^0.2.0
|
postcss-antd-fixes: ^0.2.0
|
||||||
postcss-html: ^1.7.0
|
postcss-html: ^1.7.0
|
||||||
postcss-import: ^16.1.0
|
postcss-import: ^16.1.0
|
||||||
postcss-preset-env: ^10.1.1
|
postcss-preset-env: ^10.1.2
|
||||||
postcss-scss: ^4.0.9
|
postcss-scss: ^4.0.9
|
||||||
prettier: ^3.4.2
|
prettier: ^3.4.2
|
||||||
prettier-plugin-tailwindcss: ^0.6.9
|
prettier-plugin-tailwindcss: ^0.6.9
|
||||||
|
@ -148,7 +148,7 @@ catalog:
|
||||||
rollup-plugin-visualizer: ^5.12.0
|
rollup-plugin-visualizer: ^5.12.0
|
||||||
sass: 1.80.6
|
sass: 1.80.6
|
||||||
sortablejs: ^1.15.6
|
sortablejs: ^1.15.6
|
||||||
stylelint: ^16.11.0
|
stylelint: ^16.12.0
|
||||||
stylelint-config-recess-order: ^5.1.1
|
stylelint-config-recess-order: ^5.1.1
|
||||||
stylelint-config-recommended: ^14.0.1
|
stylelint-config-recommended: ^14.0.1
|
||||||
stylelint-config-recommended-scss: ^14.1.0
|
stylelint-config-recommended-scss: ^14.1.0
|
||||||
|
@ -158,23 +158,23 @@ catalog:
|
||||||
stylelint-prettier: ^5.0.2
|
stylelint-prettier: ^5.0.2
|
||||||
stylelint-scss: ^6.10.0
|
stylelint-scss: ^6.10.0
|
||||||
tailwind-merge: ^2.5.5
|
tailwind-merge: ^2.5.5
|
||||||
tailwindcss: ^3.4.16
|
tailwindcss: ^3.4.17
|
||||||
tailwindcss-animate: ^1.0.7
|
tailwindcss-animate: ^1.0.7
|
||||||
theme-colors: ^0.1.0
|
theme-colors: ^0.1.0
|
||||||
turbo: ^2.3.3
|
turbo: ^2.3.3
|
||||||
typescript: 5.6.3
|
typescript: 5.6.3
|
||||||
unbuild: ^3.0.0-rc.11
|
unbuild: ^3.0.1
|
||||||
unplugin-element-plus: ^0.8.0
|
unplugin-element-plus: ^0.8.0
|
||||||
vee-validate: ^4.14.7
|
vee-validate: ^4.14.7
|
||||||
vite: ^6.0.3
|
vite: ^6.0.5
|
||||||
vite-plugin-compression: ^0.5.1
|
vite-plugin-compression: ^0.5.1
|
||||||
vite-plugin-dts: 4.2.1
|
vite-plugin-dts: 4.2.1
|
||||||
vite-plugin-html: ^3.2.2
|
vite-plugin-html: ^3.2.2
|
||||||
vite-plugin-lazy-import: ^1.0.7
|
vite-plugin-lazy-import: ^1.0.7
|
||||||
vite-plugin-pwa: ^0.21.1
|
vite-plugin-pwa: ^0.21.1
|
||||||
vite-plugin-vue-devtools: ^7.6.7
|
vite-plugin-vue-devtools: ^7.6.8
|
||||||
vitepress: ^1.5.0
|
vitepress: ^1.5.0
|
||||||
vitepress-plugin-group-icons: ^1.3.1
|
vitepress-plugin-group-icons: ^1.3.2
|
||||||
vitest: ^2.1.8
|
vitest: ^2.1.8
|
||||||
vue: ^3.5.13
|
vue: ^3.5.13
|
||||||
vue-dompurify-html: ^5.2.0
|
vue-dompurify-html: ^5.2.0
|
||||||
|
@ -182,8 +182,8 @@ catalog:
|
||||||
vue-i18n: ^10.0.5
|
vue-i18n: ^10.0.5
|
||||||
vue-router: ^4.5.0
|
vue-router: ^4.5.0
|
||||||
vue-tsc: ^2.1.10
|
vue-tsc: ^2.1.10
|
||||||
vxe-pc-ui: ^4.3.27
|
vxe-pc-ui: ^4.3.40
|
||||||
vxe-table: ^4.9.23
|
vxe-table: ^4.9.33
|
||||||
watermark-js-plus: ^1.5.7
|
watermark-js-plus: ^1.5.7
|
||||||
zod: ^3.24.1
|
zod: ^3.24.1
|
||||||
zod-defaults: ^0.1.3
|
zod-defaults: ^0.1.3
|
||||||
|
|
Loading…
Reference in New Issue