ソースを参照

fix: 替换分割折叠面板方案

jiaxing.liao 3 週間 前
コミット
edbaba595a

+ 30 - 43
src/renderer/src/components/SplitterCollapse/SplitterCollapseItem.vue

@@ -1,39 +1,43 @@
 <template>
-  <div class="flex flex-col" :style="{ height }">
-    <!-- header -->
-    <div
-      class="h-32px bg-bg-tertiary flex items-center justify-between px-1 cursor-pointer border-b-1px border-b-solid border-border"
-      @click="parent?.change(name)"
-    >
-      <div class="left">
-        <span class="mr-8px text-text-secondary">
-          <ai-outline-down :size="12" v-if="opened" />
-          <ai-outline-right :size="12" v-else />
-        </span>
-        <span class="text-14px text-text-secondary">{{ title }}</span>
+  <SplitterPanel collapsible :collapsed-size="0" ref="splitterPanelRef" style="min-height: 32px">
+    <template #default="{ isExpanded, collapse, expand }">
+      <div class="w-full h-full flex flex-col">
+        <!-- header -->
+        <div
+          class="h-32px bg-bg-tertiary flex items-center justify-between px-1 cursor-pointer border-b-1px border-b-solid border-border"
+          @click="isExpanded ? collapse() : expand()"
+        >
+          <div class="left">
+            <span class="mr-8px text-text-secondary">
+              <ai-outline-down :size="12" v-if="isExpanded" />
+              <ai-outline-right :size="12" v-else />
+            </span>
+            <span class="text-14px text-text-secondary">{{ title }}</span>
+          </div>
+          <div class="right">
+            <slot name="header-right"></slot>
+          </div>
+        </div>
+        <!-- content -->
+        <div class="flex-1 overflow-y-auto" v-show="isExpanded">
+          <slot></slot>
+        </div>
       </div>
-      <div class="right">
-        <slot name="header-right"></slot>
-      </div>
-    </div>
-    <!-- content -->
-    <div class="flex-1" v-show="opened">
-      <slot></slot>
-    </div>
-  </div>
+    </template>
+  </SplitterPanel>
+  <SplitterResizeHandle class="splitter-handle" />
 </template>
 
 <script setup lang="ts">
-import { defineProps, defineEmits, computed, inject, ref, withDefaults } from 'vue'
+import { defineProps, defineEmits, withDefaults } from 'vue'
 import { AiOutlineRight, AiOutlineDown } from 'vue-icons-plus/ai'
-import type { Ref } from 'vue'
+import { SplitterPanel, SplitterResizeHandle } from 'reka-ui'
 
-const HEADER_HEIGHT = 32
-const props = withDefaults(
+withDefaults(
   defineProps<{
-    name: string
     title: string
     min?: number
+    expand?: boolean
   }>(),
   {
     min: 0
@@ -41,23 +45,6 @@ const props = withDefaults(
 )
 
 const emit = defineEmits(['change'])
-const parent = inject<{
-  actives: Ref<string[]>
-  change: (name?: string) => void
-  lastChildName: string
-}>('info')
-
-const size = ref<number>(props.min)
-
-const height = computed(() => {
-  return `${opened.value ? Math.max(size.value, HEADER_HEIGHT) : HEADER_HEIGHT}px`
-})
-
-// 展开状态
-const opened = computed(() => {
-  const { actives } = parent || {}
-  return props.name && actives?.value?.includes(props.name)
-})
 </script>
 
 <style scoped></style>

+ 13 - 22
src/renderer/src/components/SplitterCollapse/index.vue

@@ -1,14 +1,17 @@
 <!-- 折叠分割面板 -->
 <template>
   <div class="w-full h-full">
-    <slot></slot>
+    <SplitterGroup :direction="layout" class="splitter-group">
+      <slot></slot>
+    </SplitterGroup collapsible>
   </div>
 </template>
 
 <script setup lang="ts">
-import { defineProps, withDefaults, ref, watch, provide, useSlots } from 'vue'
+import { defineProps, withDefaults, provide, useSlots } from 'vue'
+import { SplitterGroup } from 'reka-ui'
 
-const props = withDefaults(
+withDefaults(
   defineProps<{
     layout?: 'vertical' | 'horizontal'
     value?: string[]
@@ -19,32 +22,20 @@ const props = withDefaults(
 )
 
 const slots = useSlots()
-
 const emit = defineEmits<{
   (e: 'update:value', value: string[]): void
 }>()
 
-const actives = ref(props.value || [])
-
 provide('info', {
-  actives,
-  change: (name: string) => {
-    if (actives.value.includes(name)) {
-      actives.value = actives.value.filter((item) => item !== name)
-    } else {
-      actives.value.push(name)
-    }
-  },
   list: slots.default?.()?.map((item) => item.props?.name),
-  lastChildName: slots.default?.()?.[slots.default?.()?.length - 1]?.props?.name
 })
 
-watch(
-  () => actives.value,
-  (val) => {
-    emit('update:value', val)
-  }
-)
 </script>
 
-<style scoped></style>
+<style lang="less" scoped>
+::v-deep(.splitter-group) {
+  .splitter-handle:last-child {
+    display: none;
+  }
+}
+</style>

+ 2 - 2
src/renderer/src/views/designer/sidebar/Hierarchy.vue

@@ -1,6 +1,6 @@
 <template>
   <SplitterCollapse>
-    <SplitterCollapseItem title="屏幕页面" name="page" :min="200">
+    <SplitterCollapseItem title="屏幕页面">
       <el-tree
         ref="treeRef"
         style="max-width: 600px"
@@ -12,7 +12,7 @@
         :render-content="renderScreen"
       />
     </SplitterCollapseItem>
-    <SplitterCollapseItem title="图层" name="hierarchy" :min="200">
+    <SplitterCollapseItem title="图层">
       <el-tree
         ref="treeRef"
         style="max-width: 600px"

+ 13 - 7
src/renderer/src/views/designer/sidebar/Libary.vue

@@ -1,14 +1,20 @@
 <template>
   <SplitterCollapse>
-    <SplitterCollapseItem title="基础" name="base" :min="200">
-      <el-space>
-        <div v-for="item in 10" :key="item">控件{{ item }}</div>
+    <SplitterCollapseItem title="基础">
+      <el-space wrap>
+        <div
+          class="w-70px h-70px flex items-center text-text-secondary justify-center cursor-pointer hover:bg-bg-secondary hover:text-text-active"
+          v-for="item in 10"
+          :key="item"
+        >
+          控件{{ item }}
+        </div>
       </el-space>
     </SplitterCollapseItem>
-    <SplitterCollapseItem title="表单" name="form" :min="200"> </SplitterCollapseItem>
-    <SplitterCollapseItem title="容器" name="coniner" :min="200"> </SplitterCollapseItem>
-    <SplitterCollapseItem title="图文" name="image_text" :min="200"> </SplitterCollapseItem>
-    <SplitterCollapseItem title="媒体" name="media" :min="200"> </SplitterCollapseItem>
+    <SplitterCollapseItem title="表单"> </SplitterCollapseItem>
+    <SplitterCollapseItem title="容器"> </SplitterCollapseItem>
+    <SplitterCollapseItem title="图文"> </SplitterCollapseItem>
+    <SplitterCollapseItem title="媒体"> </SplitterCollapseItem>
   </SplitterCollapse>
 </template>
 

+ 7 - 7
src/renderer/src/views/designer/sidebar/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="w-full h-full flex">
-    <div class="w-50px h-full bg-bg-sidebar flex flex-col items-center justify-between">
+    <div class="w-50px h-full bg-bg-sidebar flex flex-col items-center justify-between shrink-0">
       <div class="w-full flex-1">
         <ul class="list-none p-0 m-0 text-12px text-text-secondary sidebar-menu">
           <li
@@ -13,9 +13,9 @@
             <el-tooltip
               :content="item.tooltip"
               :enterable="false"
+              :focus-on-show="false"
               placement="right"
               trigger="hover"
-              :focus-on-show="false"
             >
               <component :is="item.title" />
             </el-tooltip>
@@ -39,16 +39,16 @@
     <!-- 资源管理 -->
     <div class="flex-1" v-show="activeMenu === 'resource'">
       <SplitterCollapse>
-        <SplitterCollapseItem title="图片" name="image" :min="200"> </SplitterCollapseItem>
-        <SplitterCollapseItem title="字体" name="font"> </SplitterCollapseItem>
-        <SplitterCollapseItem title="其他数据" name="other"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="图片"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="字体"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="其他数据"> </SplitterCollapseItem>
       </SplitterCollapse>
     </div>
     <!-- 代码查看 -->
     <div class="flex-1" v-show="activeMenu === 'code'">
       <SplitterCollapse>
-        <SplitterCollapseItem title="屏幕页面" name="page" :min="200"> </SplitterCollapseItem>
-        <SplitterCollapseItem title="页面大纲" name="hierarchy"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="屏幕页面"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="页面大纲"> </SplitterCollapseItem>
       </SplitterCollapse>
     </div>
     <!-- json预览 -->

+ 9 - 8
src/renderer/src/views/designer/workspace/stage/index.vue

@@ -121,15 +121,16 @@ let workspaceLeft = 0
 let workspaceTop = 0
 // 鼠标按下
 const handleMouseDown = (e: MouseEvent) => {
+  const target = e?.target as Element | null
   if (
-    e?.target?.closest('.edit-box') ||
-    e?.target?.closest('.component-content') ||
-    e?.target?.closest('.component-wrapper') ||
-    e?.target?.closest('.scaleplate-horizontal') ||
-    e?.target?.closest('.scaleplate-vertical') ||
-    e?.target?.closest('.refer-line-img') ||
-    e?.target?.closest('.workspace-bottom') ||
-    e?.target?.closest('.refer-line')
+    target?.closest('.edit-box') ||
+    target?.closest('.component-content') ||
+    target?.closest('.component-wrapper') ||
+    target?.closest('.scaleplate-horizontal') ||
+    target?.closest('.scaleplate-vertical') ||
+    target?.closest('.refer-line-img') ||
+    target?.closest('.workspace-bottom') ||
+    target?.closest('.refer-line')
   ) {
     return
   }