|
|
@@ -7,7 +7,7 @@
|
|
|
:class="titleMode === 'bottom_fixed' ? 'flex-col-reverse' : 'flex-col'"
|
|
|
>
|
|
|
<div
|
|
|
- class="w-full px-18px relative whitespace-pre! flex items-center box-border"
|
|
|
+ class="menu-header w-full px-18px relative whitespace-pre! flex items-center box-border"
|
|
|
:style="styleMap?.menuTitleStyle"
|
|
|
>
|
|
|
<LuChevronLeft size="14px" />
|
|
|
@@ -26,7 +26,7 @@
|
|
|
>
|
|
|
<ImageBg :src="styleMap?.mainStyle?.imageSrc" :imageStyle="styleMap?.mainStyle?.imageStyle" />
|
|
|
<!-- 菜单标题 -->
|
|
|
- <div class="relative whitespace-pre!" :style="styleMap?.menuTitleStyle">
|
|
|
+ <div class="menu-header relative whitespace-pre!" :style="styleMap?.menuTitleStyle">
|
|
|
<ImageBg
|
|
|
:src="styleMap?.menuTitleStyle?.imageSrc"
|
|
|
:imageStyle="styleMap?.menuTitleStyle?.imageStyle"
|
|
|
@@ -35,66 +35,74 @@
|
|
|
</div>
|
|
|
<!-- 侧边栏 -->
|
|
|
<div
|
|
|
+ ref="sidebarRef"
|
|
|
:style="styleMap?.sidebarStyle"
|
|
|
:class="titleMode === 'bottom_fixed' ? 'flex-1' : ''"
|
|
|
- class="relative box-border overflow-hidden"
|
|
|
+ class="menu-sidebar relative box-border overflow-hidden"
|
|
|
>
|
|
|
<ImageBg
|
|
|
:src="styleMap?.sidebarStyle?.imageSrc"
|
|
|
:imageStyle="styleMap?.siderbaStyle?.imageStyle"
|
|
|
/>
|
|
|
<!-- 菜单片段 -->
|
|
|
- <template v-for="(section, sectionIndex) in children || []" :key="sectionIndex">
|
|
|
- <div v-show="openSection" class="z-2 min-h-30px flex items-center">
|
|
|
- <div class="w-full px-10px py-2px" :style="styleMap?.sectionTitleStyle">
|
|
|
- {{ section.name }}
|
|
|
+ <div ref="contentRef" class="z-2">
|
|
|
+ <template v-for="(section, sectionIndex) in children || []" :key="sectionIndex">
|
|
|
+ <div v-show="openSection" class="z-2 min-h-30px flex items-center">
|
|
|
+ <div class="w-full px-10px py-2px" :style="styleMap?.sectionTitleStyle">
|
|
|
+ {{ section.name }}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div :style="styleMap?.sectionStyle" class="z-2 overflow-hidden">
|
|
|
- <div
|
|
|
- v-for="({ titleIcon, name }, index) in section.children || []"
|
|
|
- :key="index"
|
|
|
- :style="
|
|
|
- activeIndex === `[${sectionIndex}].children.[${index}]`
|
|
|
- ? activeStyle
|
|
|
- : styleMap?.itemsStyle
|
|
|
- "
|
|
|
- class="relative min-h-30px flex items-center gap-4px overflow-hidden px-10px py-2px"
|
|
|
- >
|
|
|
- <ImageBg
|
|
|
- :src="styleMap?.itemsStyle?.imageSrc"
|
|
|
- :imageStyle="styleMap?.itemsStyle?.imageStyle"
|
|
|
- />
|
|
|
- <div class="z-2 w-full min-w-80px flex items-center gap-4px mr-10px">
|
|
|
- <span v-if="titleIcon?.type === 'symbol'">
|
|
|
- <i class="lvgl-icon not-italic" v-html="getSymbol(titleIcon.img_symbol)"></i>
|
|
|
- </span>
|
|
|
- <div
|
|
|
- v-if="titleIcon?.type === 'img'"
|
|
|
- :id="titleIcon.img_id"
|
|
|
- :style="{
|
|
|
- width: titleIcon.img_width + 'px',
|
|
|
- height: titleIcon.img_height + 'px',
|
|
|
- position: 'relative'
|
|
|
- }"
|
|
|
- >
|
|
|
- <ImageBg
|
|
|
+ <div :style="styleMap?.sectionStyle" class="z-2 overflow-hidden">
|
|
|
+ <div
|
|
|
+ v-for="({ titleIcon, name }, index) in section.children || []"
|
|
|
+ :key="index"
|
|
|
+ :style="
|
|
|
+ activeIndex === `[${sectionIndex}].children.[${index}]`
|
|
|
+ ? activeStyle
|
|
|
+ : styleMap?.itemsStyle
|
|
|
+ "
|
|
|
+ class="relative min-h-30px flex items-center gap-4px overflow-hidden px-10px py-2px"
|
|
|
+ >
|
|
|
+ <ImageBg
|
|
|
+ :src="styleMap?.itemsStyle?.imageSrc"
|
|
|
+ :imageStyle="styleMap?.itemsStyle?.imageStyle"
|
|
|
+ />
|
|
|
+ <div class="z-2 w-full min-w-80px flex items-center gap-4px mr-10px">
|
|
|
+ <span v-if="titleIcon?.type === 'symbol'">
|
|
|
+ <i class="lvgl-icon not-italic" v-html="getSymbol(titleIcon.img_symbol)"></i>
|
|
|
+ </span>
|
|
|
+ <div
|
|
|
+ v-if="titleIcon?.type === 'img'"
|
|
|
:id="titleIcon.img_id"
|
|
|
- :image-style="{
|
|
|
- backgroundColor: titleIcon.img_recolor,
|
|
|
- opacity: titleIcon.img_alpha / 255
|
|
|
- }"
|
|
|
- :image-props="{
|
|
|
+ :style="{
|
|
|
width: titleIcon.img_width + 'px',
|
|
|
- height: titleIcon.img_height + 'px'
|
|
|
+ height: titleIcon.img_height + 'px',
|
|
|
+ position: 'relative'
|
|
|
}"
|
|
|
- />
|
|
|
+ >
|
|
|
+ <ImageBg
|
|
|
+ :id="titleIcon.img_id"
|
|
|
+ :image-style="{
|
|
|
+ backgroundColor: titleIcon.img_recolor,
|
|
|
+ opacity: titleIcon.img_alpha / 255
|
|
|
+ }"
|
|
|
+ :image-props="{
|
|
|
+ width: titleIcon.img_width + 'px',
|
|
|
+ height: titleIcon.img_height + 'px'
|
|
|
+ }"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <span class="flex-1 whitespace-pre!">{{ name }}</span>
|
|
|
</div>
|
|
|
- <span class="flex-1 whitespace-pre!">{{ name }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ <!-- 滚动条 -->
|
|
|
+ <div
|
|
|
+ v-if="showVScroll"
|
|
|
+ class="v-scrollbar absolute right-6px top-6px w-4px h-20% bg-#d7d7d7"
|
|
|
+ ></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div v-if="sider" class="basis-2/3"></div>
|
|
|
@@ -102,11 +110,12 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { computed, type CSSProperties } from 'vue'
|
|
|
+import { computed, ref, type CSSProperties } from 'vue'
|
|
|
import { useWidgetStyle, getStyle } from '../hooks/useWidgetStyle'
|
|
|
import { useProjectStore } from '@/store/modules/project'
|
|
|
import { assign, get } from 'lodash-es'
|
|
|
import { getSymbol } from '@/utils'
|
|
|
+import { useResizeObserver } from 'vue-hooks-plus'
|
|
|
|
|
|
import { LuChevronLeft } from 'vue-icons-plus/lu'
|
|
|
import ImageBg from '../ImageBg.vue'
|
|
|
@@ -136,6 +145,17 @@ const styleMap = useWidgetStyle({
|
|
|
props
|
|
|
})
|
|
|
|
|
|
+const sidebarRef = ref<HTMLDivElement>()
|
|
|
+const contentRef = ref<HTMLDivElement>()
|
|
|
+const showVScroll = ref(false)
|
|
|
+
|
|
|
+useResizeObserver(contentRef, (entries) => {
|
|
|
+ const entry = entries[0]
|
|
|
+ const { height: _h } = entry.contentRect
|
|
|
+ const boxHeight = sidebarRef.value?.offsetHeight
|
|
|
+ showVScroll.value = !!boxHeight && _h > boxHeight
|
|
|
+})
|
|
|
+
|
|
|
const projectStore = useProjectStore()
|
|
|
|
|
|
// 激活样式
|