Просмотр исходного кода

feat: 动态计算下拉框弹窗、滚动条样式

jiaxing.liao 2 дней назад
Родитель
Сommit
a9a8eab24a

+ 70 - 15
src/renderer/src/lvgl-widgets/dropdown/Dropdown.vue

@@ -1,34 +1,45 @@
 <template>
   <div :style="styleMap?.mainStyle" class="box-border relative">
-    <div class="w-full flex items-center justify-between overflow-hidden relative">
-      <span>{{ options?.[0] }}</span>
-      <EpArrowDownBold
+    <div class="relative w-full overflow-hidden" :class="direction === 'left' ? 'text-right' : ''">
+      {{ options?.[0] }}
+      <div
         v-if="showArrow"
-        size="14px"
-        class="absolute right-0 top-1/2 transform -translate-y-1/2"
-      />
+        class="absolute right-0 top-0"
+        :class="direction === 'left' ? 'left-0 right-auto' : ''"
+      >
+        <EpArrowDownBold v-if="direction === 'down'" size="14px" />
+        <EpArrowUpBold v-if="direction === 'up'" size="14px" />
+        <EpArrowLeftBold v-if="direction === 'left'" size="14px" />
+        <EpArrowRightBold v-if="direction === 'right'" size="14px" />
+      </div>
     </div>
     <div
-      v-show="showList"
-      class="absolute mt-10px left-0 top-full bg-white"
-      :style="styleMap?.mainStyle"
+      v-if="showList"
+      :style="{ ...styleMap?.mainStyle, ...popStyle }"
       style="padding: 0; width: 100%; height: auto"
+      class="absolute bg-white max-h-[120px] overflow-y-auto dropdown-pop"
     >
       <div
-        class="truncate h-24px leading-24px"
+        class="truncate h-24px leading-24px px-10px box-border"
         v-for="(item, index) in options"
         :key="item"
         :style="index === 0 ? styleMap?.selectedStyle : ''"
       >
         {{ item }}
       </div>
+      <div class="absolute" :style="{ ...(styleMap?.scrollbarStyle || {}), ...scrollbarStyle }" />
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { computed } from 'vue'
-import { EpArrowDownBold } from 'vue-icons-plus/ep'
+import { computed, CSSProperties } from 'vue'
+import {
+  EpArrowDownBold,
+  EpArrowUpBold,
+  EpArrowLeftBold,
+  EpArrowRightBold
+} from 'vue-icons-plus/ep'
 import { useWidgetStyle } from '../hooks/useWidgetStyle'
 
 const props = defineProps<{
@@ -39,14 +50,58 @@ const props = defineProps<{
   part?: string
   showArrow?: boolean
   options: string[]
+  direction?: 'up' | 'down' | 'left' | 'right'
 }>()
 
-const showList = computed(() => props.part === 'selected')
-
 const styleMap = useWidgetStyle({
   widget: 'lv_dropdown',
   props
 })
+
+const showList = computed(() => props.part !== 'main')
+
+const popStyle = computed((): CSSProperties => {
+  const border = (styleMap.value?.mainStyle?.borderWidth as string)?.replace('px', '')
+
+  return props.direction === 'left'
+    ? {
+        top: `-${Number(border || 0)}px`,
+        left: `calc(-100% - ${Number(border || 0) * 3}px)`
+      }
+    : props.direction === 'right'
+      ? {
+          right: `calc(-100% - ${Number(border || 0) * 3}px)`,
+          top: `-${Number(border || 0)}px`
+        }
+      : props.direction === 'up'
+        ? {
+            top: 'auto',
+            bottom: `calc(100% + ${Number(border || 0)}px)`,
+            left: `-${Number(border || 0)}px`
+          }
+        : {
+            bottom: 'auto',
+            top: `calc(100% + ${Number(border || 0)}px)`,
+            left: `-${Number(border || 0)}px`
+          }
+})
+// 滚动条样式
+const scrollbarStyle = computed(() => {
+  const border = styleMap.value?.mainStyle?.borderWidth as string
+
+  return {
+    right: border || 0,
+    top: border || 0,
+    width: '3px',
+    height: '40%'
+  }
+})
 </script>
 
-<style scoped></style>
+<style lang="less" scoped>
+.dropdown-pop {
+  &::-webkit-scrollbar {
+    display: none;
+  }
+}
+</style>

+ 17 - 3
src/renderer/src/lvgl-widgets/dropdown/index.tsx

@@ -38,7 +38,8 @@ export default {
       addFlags: [],
       removeFlags: [],
       showArrow: false,
-      options: ['option1', 'option2', 'option3']
+      options: ['option1', 'option2', 'option3'],
+      direction: 'down'
     },
     styles: [
       {
@@ -166,7 +167,7 @@ export default {
       {
         label: '添加标识',
         field: 'props.addFlags',
-        valueType: 'select',
+        valueType: 'checkbox',
         componentProps: {
           options: flagOptions,
           defaultCollapsed: true
@@ -175,7 +176,7 @@ export default {
       {
         label: '删除标识',
         field: 'props.removeFlags',
-        valueType: 'select',
+        valueType: 'checkbox',
         componentProps: {
           options: flagOptions,
           defaultCollapsed: true
@@ -188,6 +189,19 @@ export default {
         field: 'props.showArrow',
         valueType: 'switch'
       },
+      {
+        label: '方向',
+        field: 'props.direction',
+        valueType: 'select',
+        componentProps: {
+          options: [
+            { label: '下', value: 'down' },
+            { label: '上', value: 'up' },
+            { label: '左', value: 'left' },
+            { label: '右', value: 'right' }
+          ]
+        }
+      },
       {
         label: '属性',
         field: 'props.options',

+ 2 - 0
src/renderer/src/views/designer/config/property/index.vue

@@ -16,6 +16,7 @@
         />
       </el-row>
     </el-form>
+    <!-- 核心属性 -->
     <el-collapse v-model="activeKeys">
       <el-collapse-item name="props" v-if="formConfig?.coreProps">
         <template #title>
@@ -40,6 +41,7 @@
           </el-row>
         </el-form>
       </el-collapse-item>
+      <!-- 样式设置 -->
       <el-collapse-item name="style">
         <template #title>
           <div class="flex items-center">