|
@@ -5,6 +5,7 @@
|
|
|
:class="schema.type === 'page' ? '' : 'ignore-click widget-node'"
|
|
:class="schema.type === 'page' ? '' : 'ignore-click widget-node'"
|
|
|
:widget-id="schema.id"
|
|
:widget-id="schema.id"
|
|
|
@click.stop="handleSelect"
|
|
@click.stop="handleSelect"
|
|
|
|
|
+ @contextmenu.stop="handleContextmenu"
|
|
|
v-if="!schema.hidden"
|
|
v-if="!schema.hidden"
|
|
|
>
|
|
>
|
|
|
<!-- 控件 -->
|
|
<!-- 控件 -->
|
|
@@ -12,8 +13,9 @@
|
|
|
<!-- 子节点 -->
|
|
<!-- 子节点 -->
|
|
|
<NodeItem
|
|
<NodeItem
|
|
|
v-if="schema.children"
|
|
v-if="schema.children"
|
|
|
- v-for="child in schema.children"
|
|
|
|
|
|
|
+ v-for="(child, index) in schema.children"
|
|
|
:key="child.id"
|
|
:key="child.id"
|
|
|
|
|
+ :zIndex="schema.children.length - index"
|
|
|
:schema="child"
|
|
:schema="child"
|
|
|
:rootContainer="nodeRef!"
|
|
:rootContainer="nodeRef!"
|
|
|
/>
|
|
/>
|
|
@@ -29,6 +31,8 @@
|
|
|
:snappable="true"
|
|
:snappable="true"
|
|
|
:useMutationObserver="true"
|
|
:useMutationObserver="true"
|
|
|
:useResizeObserver="true"
|
|
:useResizeObserver="true"
|
|
|
|
|
+ :throttleDrag="1"
|
|
|
|
|
+ :throttleResize="1"
|
|
|
:snapDirections="{
|
|
:snapDirections="{
|
|
|
top: true,
|
|
top: true,
|
|
|
left: true,
|
|
left: true,
|
|
@@ -55,14 +59,17 @@
|
|
|
@resize="onResize"
|
|
@resize="onResize"
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <!-- 右键菜单 -->
|
|
|
|
|
+ <ContentMenu ref="contentMenuRef" :virtualRef="triggerRef" />
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import type { BaseWidget } from '@/types/baseWidget'
|
|
import type { BaseWidget } from '@/types/baseWidget'
|
|
|
import type { Page } from '@/types/page'
|
|
import type { Page } from '@/types/page'
|
|
|
import type { StageState } from './type'
|
|
import type { StageState } from './type'
|
|
|
|
|
+import type { CSSProperties } from 'vue'
|
|
|
|
|
|
|
|
-import { computed, type CSSProperties, ref, inject } from 'vue'
|
|
|
|
|
|
|
+import { computed, ref, inject } from 'vue'
|
|
|
import { useDrop } from 'vue-hooks-plus'
|
|
import { useDrop } from 'vue-hooks-plus'
|
|
|
import { createWidget } from '@/model'
|
|
import { createWidget } from '@/model'
|
|
|
import LvglWidgets from '@/lvgl-widgets'
|
|
import LvglWidgets from '@/lvgl-widgets'
|
|
@@ -70,6 +77,7 @@ import { useProjectStore } from '@/store/modules/project'
|
|
|
import { useMutationObserver } from '@vueuse/core'
|
|
import { useMutationObserver } from '@vueuse/core'
|
|
|
|
|
|
|
|
import Moveable from 'vue3-moveable'
|
|
import Moveable from 'vue3-moveable'
|
|
|
|
|
+import ContentMenu from './ContentMenu.vue'
|
|
|
import { getAddWidgetIndex } from '@/utils'
|
|
import { getAddWidgetIndex } from '@/utils'
|
|
|
|
|
|
|
|
defineOptions({
|
|
defineOptions({
|
|
@@ -87,6 +95,8 @@ const props = defineProps<{
|
|
|
schema: BaseWidget | Page
|
|
schema: BaseWidget | Page
|
|
|
// 传入样式 如页面样式
|
|
// 传入样式 如页面样式
|
|
|
style?: CSSProperties
|
|
style?: CSSProperties
|
|
|
|
|
+ // 层级
|
|
|
|
|
+ zIndex?: number
|
|
|
}>()
|
|
}>()
|
|
|
|
|
|
|
|
const projectStore = useProjectStore()
|
|
const projectStore = useProjectStore()
|
|
@@ -101,7 +111,7 @@ const selected = computed(() =>
|
|
|
|
|
|
|
|
// 组件样式
|
|
// 组件样式
|
|
|
const getStyle = computed((): CSSProperties => {
|
|
const getStyle = computed((): CSSProperties => {
|
|
|
- const { style = {}, schema } = props
|
|
|
|
|
|
|
+ const { style = {}, schema, zIndex } = props
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
|
position: 'absolute',
|
|
position: 'absolute',
|
|
@@ -110,6 +120,7 @@ const getStyle = computed((): CSSProperties => {
|
|
|
transform: `translate(${schema.props.x}px, ${schema.props.y}px)`,
|
|
transform: `translate(${schema.props.x}px, ${schema.props.y}px)`,
|
|
|
width: schema.props.width + 'px',
|
|
width: schema.props.width + 'px',
|
|
|
height: schema.props.height + 'px',
|
|
height: schema.props.height + 'px',
|
|
|
|
|
+ zIndex: zIndex,
|
|
|
...style
|
|
...style
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
@@ -168,7 +179,8 @@ useDrop(nodeRef, {
|
|
|
const newWidget = createWidget(content, index)
|
|
const newWidget = createWidget(content, index)
|
|
|
newWidget.props.x = offsetX
|
|
newWidget.props.x = offsetX
|
|
|
newWidget.props.y = offsetY
|
|
newWidget.props.y = offsetY
|
|
|
- props.schema.children?.push(newWidget)
|
|
|
|
|
|
|
+ // 添加到前面
|
|
|
|
|
+ props.schema.children?.unshift(newWidget)
|
|
|
projectStore.setSelectWidgets([newWidget])
|
|
projectStore.setSelectWidgets([newWidget])
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
@@ -183,6 +195,8 @@ const handleSelect = (e) => {
|
|
|
projectStore.setSelectWidgets([props.schema as BaseWidget])
|
|
projectStore.setSelectWidgets([props.schema as BaseWidget])
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ // 关闭右键菜单
|
|
|
|
|
+ contentMenuRef.value?.handleClose()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 渲染节点拖拽
|
|
// 渲染节点拖拽
|
|
@@ -209,4 +223,41 @@ const onResize = (e) => {
|
|
|
const onRender = (e) => {
|
|
const onRender = (e) => {
|
|
|
e.target.style.cssText += e.cssText
|
|
e.target.style.cssText += e.cssText
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/******************************右键菜单*********************************/
|
|
|
|
|
+const position = ref({
|
|
|
|
|
+ top: 0,
|
|
|
|
|
+ left: 0,
|
|
|
|
|
+ bottom: 0,
|
|
|
|
|
+ right: 0
|
|
|
|
|
+} as DOMRect)
|
|
|
|
|
+
|
|
|
|
|
+const contentMenuRef = ref<InstanceType<typeof ContentMenu>>()
|
|
|
|
|
+
|
|
|
|
|
+const triggerRef = ref({
|
|
|
|
|
+ getBoundingClientRect: () => position.value
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const handleContextmenu = (event: MouseEvent) => {
|
|
|
|
|
+ const { clientX, clientY } = event
|
|
|
|
|
+ position.value = DOMRect.fromRect({
|
|
|
|
|
+ x: clientX,
|
|
|
|
|
+ y: clientY
|
|
|
|
|
+ })
|
|
|
|
|
+ event.preventDefault()
|
|
|
|
|
+ contentMenuRef.value?.handleOpen()
|
|
|
|
|
+ // todo 关闭其他菜单
|
|
|
|
|
+
|
|
|
|
|
+ // 没选中当前节点时 右键选中节点
|
|
|
|
|
+ if (!projectStore.activeWidgets.map((item) => item.id).includes(props.schema.id)) {
|
|
|
|
|
+ if (props.schema.type !== 'page') {
|
|
|
|
|
+ // 判断当前是否按住ctrl
|
|
|
|
|
+ if (event.ctrlKey) {
|
|
|
|
|
+ projectStore.activeWidgets.push(props.schema as BaseWidget)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ projectStore.setSelectWidgets([props.schema as BaseWidget])
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|