col-page.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <script lang="ts" setup>
  2. import type { ColPageProps } from './types';
  3. import { computed, ref, useSlots } from 'vue';
  4. import {
  5. ResizableHandle,
  6. ResizablePanel,
  7. ResizablePanelGroup,
  8. } from '@vben-core/shadcn-ui';
  9. import Page from '../page/page.vue';
  10. defineOptions({
  11. name: 'ColPage',
  12. inheritAttrs: false,
  13. });
  14. const props = withDefaults(defineProps<ColPageProps>(), {
  15. leftWidth: 30,
  16. rightWidth: 70,
  17. resizable: true,
  18. });
  19. const delegatedProps = computed(() => {
  20. const { leftWidth: _, ...delegated } = props;
  21. return delegated;
  22. });
  23. const slots = useSlots();
  24. const delegatedSlots = computed(() => {
  25. const resultSlots: string[] = [];
  26. for (const key of Object.keys(slots)) {
  27. if (!['default', 'left'].includes(key)) {
  28. resultSlots.push(key);
  29. }
  30. }
  31. return resultSlots;
  32. });
  33. const leftPanelRef = ref<InstanceType<typeof ResizablePanel>>();
  34. function expandLeft() {
  35. leftPanelRef.value?.expand();
  36. }
  37. function collapseLeft() {
  38. leftPanelRef.value?.collapse();
  39. }
  40. defineExpose({
  41. expandLeft,
  42. collapseLeft,
  43. });
  44. </script>
  45. <template>
  46. <Page v-bind="delegatedProps">
  47. <!-- 继承默认的slot -->
  48. <template
  49. v-for="slotName in delegatedSlots"
  50. :key="slotName"
  51. #[slotName]="slotProps"
  52. >
  53. <slot :name="slotName" v-bind="slotProps"></slot>
  54. </template>
  55. <ResizablePanelGroup class="w-full" direction="horizontal">
  56. <ResizablePanel
  57. ref="leftPanelRef"
  58. :collapsed-size="leftCollapsedWidth"
  59. :collapsible="leftCollapsible"
  60. :default-size="leftWidth"
  61. :max-size="leftMaxWidth"
  62. :min-size="leftMinWidth"
  63. >
  64. <template #default="slotProps">
  65. <slot
  66. name="left"
  67. v-bind="{
  68. ...slotProps,
  69. expand: expandLeft,
  70. collapse: collapseLeft,
  71. }"
  72. ></slot>
  73. </template>
  74. </ResizablePanel>
  75. <ResizableHandle
  76. v-if="resizable"
  77. :style="{ backgroundColor: splitLine ? undefined : 'transparent' }"
  78. :with-handle="splitHandle"
  79. />
  80. <ResizablePanel
  81. :collapsed-size="rightCollapsedWidth"
  82. :collapsible="rightCollapsible"
  83. :default-size="rightWidth"
  84. :max-size="rightMaxWidth"
  85. :min-size="rightMinWidth"
  86. >
  87. <template #default>
  88. <slot></slot>
  89. </template>
  90. </ResizablePanel>
  91. </ResizablePanelGroup>
  92. </Page>
  93. </template>