|
@@ -2,8 +2,8 @@
|
|
|
<Moveable
|
|
<Moveable
|
|
|
v-if="pageId && pageId === projectStore.activePageId"
|
|
v-if="pageId && pageId === projectStore.activePageId"
|
|
|
:target="moveableTarget"
|
|
:target="moveableTarget"
|
|
|
- :draggable="true"
|
|
|
|
|
- :resizable="true"
|
|
|
|
|
|
|
+ :draggable="canTransformSelection"
|
|
|
|
|
+ :resizable="canTransformSelection"
|
|
|
:groupable="isGroupSelection"
|
|
:groupable="isGroupSelection"
|
|
|
:rotatable="false"
|
|
:rotatable="false"
|
|
|
:padding="2"
|
|
:padding="2"
|
|
@@ -79,6 +79,12 @@ const projectStore = useProjectStore()
|
|
|
const appStore = useAppStore()
|
|
const appStore = useAppStore()
|
|
|
const isGroupSelection = computed(() => elements.value.length > 1)
|
|
const isGroupSelection = computed(() => elements.value.length > 1)
|
|
|
const isIndividualGroupable = computed(() => elements.value.length === 1)
|
|
const isIndividualGroupable = computed(() => elements.value.length === 1)
|
|
|
|
|
+const canTransformSelection = computed(() => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ projectStore.activeWidgets.length > 0 &&
|
|
|
|
|
+ projectStore.activeWidgets.every((item) => !hasLockedWidgetTree(item))
|
|
|
|
|
+ )
|
|
|
|
|
+})
|
|
|
const moveableTarget = computed<HTMLElement | HTMLElement[] | null>(() => {
|
|
const moveableTarget = computed<HTMLElement | HTMLElement[] | null>(() => {
|
|
|
if (isGroupSelection.value) {
|
|
if (isGroupSelection.value) {
|
|
|
return elements.value
|
|
return elements.value
|
|
@@ -157,6 +163,11 @@ useMutationObserver(
|
|
|
const zIndex = ref()
|
|
const zIndex = ref()
|
|
|
|
|
|
|
|
const individualGroupableProps = (element: HTMLElement | SVGElement | null | undefined) => {
|
|
const individualGroupableProps = (element: HTMLElement | SVGElement | null | undefined) => {
|
|
|
|
|
+ const widgetId = element?.getAttribute('widget-id') || ''
|
|
|
|
|
+ if (widgetId && hasLockedWidgetTree(projectStore.activeWidgetMap[widgetId])) {
|
|
|
|
|
+ return { draggable: false, resizable: false, rotatable: false }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
const widgetType = element?.getAttribute('widget-type') || ''
|
|
const widgetType = element?.getAttribute('widget-type') || ''
|
|
|
if (['lv_checkbox', 'qrcode'].includes(widgetType)) {
|
|
if (['lv_checkbox', 'qrcode'].includes(widgetType)) {
|
|
|
return { resizable: false }
|
|
return { resizable: false }
|
|
@@ -190,14 +201,25 @@ const getScale = (widget: Page | BaseWidget) => {
|
|
|
return (widget.props?.scale ?? 256) / 256
|
|
return (widget.props?.scale ?? 256) / 256
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const hasLockedWidgetTree = (widget?: BaseWidget | Page): boolean => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ !!widget &&
|
|
|
|
|
+ (!!widget.locked || !!widget.children?.some((child) => hasLockedWidgetTree(child)))
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 拖拽开始
|
|
// 拖拽开始
|
|
|
const onDragStart = (e) => {
|
|
const onDragStart = (e) => {
|
|
|
|
|
+ const id = e.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return false
|
|
|
zIndex.value = e.target.style.zIndex
|
|
zIndex.value = e.target.style.zIndex
|
|
|
e.target.style.zIndex = 999
|
|
e.target.style.zIndex = 999
|
|
|
appStore.draging = true
|
|
appStore.draging = true
|
|
|
}
|
|
}
|
|
|
// 渲染节点拖拽
|
|
// 渲染节点拖拽
|
|
|
const onDrag = (e) => {
|
|
const onDrag = (e) => {
|
|
|
|
|
+ const id = e.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
// 当前选中节点整体移动
|
|
// 当前选中节点整体移动
|
|
|
e.target.style.transform = e.transform
|
|
e.target.style.transform = e.transform
|
|
|
}
|
|
}
|
|
@@ -205,6 +227,10 @@ const onDrag = (e) => {
|
|
|
const onDragEnd = (e) => {
|
|
const onDragEnd = (e) => {
|
|
|
e.target.style.zIndex = zIndex.value
|
|
e.target.style.zIndex = zIndex.value
|
|
|
const id = e.target.attributes['widget-id']?.value
|
|
const id = e.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) {
|
|
|
|
|
+ appStore.draging = false
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
if (id && projectStore.activeWidgetMap[id] && e?.lastEvent?.translate) {
|
|
if (id && projectStore.activeWidgetMap[id] && e?.lastEvent?.translate) {
|
|
|
projectStore.activeWidgetMap[id].props.x = Math.round(e.lastEvent.translate[0])
|
|
projectStore.activeWidgetMap[id].props.x = Math.round(e.lastEvent.translate[0])
|
|
|
projectStore.activeWidgetMap[id].props.y = Math.round(e.lastEvent.translate[1])
|
|
projectStore.activeWidgetMap[id].props.y = Math.round(e.lastEvent.translate[1])
|
|
@@ -213,6 +239,8 @@ const onDragEnd = (e) => {
|
|
|
}
|
|
}
|
|
|
// 渲染节点缩放
|
|
// 渲染节点缩放
|
|
|
const onResize = (e) => {
|
|
const onResize = (e) => {
|
|
|
|
|
+ const id = e.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
e.target.style.width = `${e.width}px`
|
|
e.target.style.width = `${e.width}px`
|
|
|
e.target.style.height = `${e.height}px`
|
|
e.target.style.height = `${e.height}px`
|
|
|
e.target.style.transform = e.drag.transform
|
|
e.target.style.transform = e.drag.transform
|
|
@@ -220,6 +248,7 @@ const onResize = (e) => {
|
|
|
// 节点缩放完成
|
|
// 节点缩放完成
|
|
|
const onResizeEnd = (e) => {
|
|
const onResizeEnd = (e) => {
|
|
|
const id = e.target.attributes['widget-id']?.value
|
|
const id = e.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
if (e.lastEvent && id && projectStore.activeWidgetMap[id]) {
|
|
if (e.lastEvent && id && projectStore.activeWidgetMap[id]) {
|
|
|
const scale = getScale(projectStore.activeWidgetMap[id])
|
|
const scale = getScale(projectStore.activeWidgetMap[id])
|
|
|
let width = Math.round(e.lastEvent.width / scale)
|
|
let width = Math.round(e.lastEvent.width / scale)
|
|
@@ -269,12 +298,16 @@ const onRender = (e) => {
|
|
|
// 节点组拖拽
|
|
// 节点组拖拽
|
|
|
const onDragGroup = ({ events }) => {
|
|
const onDragGroup = ({ events }) => {
|
|
|
events.forEach((ev) => {
|
|
events.forEach((ev) => {
|
|
|
|
|
+ const id = ev.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
ev.target.style.transform = ev.transform
|
|
ev.target.style.transform = ev.transform
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
// 节点组缩放
|
|
// 节点组缩放
|
|
|
const onResizeGroup = ({ events }) => {
|
|
const onResizeGroup = ({ events }) => {
|
|
|
events.forEach((ev) => {
|
|
events.forEach((ev) => {
|
|
|
|
|
+ const id = ev.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
ev.target.style.width = `${ev.width}px`
|
|
ev.target.style.width = `${ev.width}px`
|
|
|
ev.target.style.height = `${ev.height}px`
|
|
ev.target.style.height = `${ev.height}px`
|
|
|
ev.target.style.transform = ev.drag.transform
|
|
ev.target.style.transform = ev.drag.transform
|
|
@@ -284,6 +317,7 @@ const onResizeGroup = ({ events }) => {
|
|
|
const onDragGroupEnd = ({ events }) => {
|
|
const onDragGroupEnd = ({ events }) => {
|
|
|
events.forEach((ev) => {
|
|
events.forEach((ev) => {
|
|
|
const id = ev.target.attributes['widget-id']?.value
|
|
const id = ev.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
if (id && projectStore.activeWidgetMap[id] && ev?.lastEvent?.translate) {
|
|
if (id && projectStore.activeWidgetMap[id] && ev?.lastEvent?.translate) {
|
|
|
projectStore.activeWidgetMap[id].props.x = Math.round(ev.lastEvent.translate[0])
|
|
projectStore.activeWidgetMap[id].props.x = Math.round(ev.lastEvent.translate[0])
|
|
|
projectStore.activeWidgetMap[id].props.y = Math.round(ev.lastEvent.translate[1])
|
|
projectStore.activeWidgetMap[id].props.y = Math.round(ev.lastEvent.translate[1])
|
|
@@ -294,6 +328,7 @@ const onDragGroupEnd = ({ events }) => {
|
|
|
const onResizeGroupEnd = ({ events }) => {
|
|
const onResizeGroupEnd = ({ events }) => {
|
|
|
events.forEach((ev) => {
|
|
events.forEach((ev) => {
|
|
|
const id = ev.target.attributes['widget-id']?.value
|
|
const id = ev.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
if (ev.lastEvent && id && projectStore.activeWidgetMap[id]) {
|
|
if (ev.lastEvent && id && projectStore.activeWidgetMap[id]) {
|
|
|
const scale = getScale(projectStore.activeWidgetMap[id])
|
|
const scale = getScale(projectStore.activeWidgetMap[id])
|
|
|
let width = Math.round(ev.lastEvent.width / scale)
|
|
let width = Math.round(ev.lastEvent.width / scale)
|
|
@@ -341,6 +376,7 @@ const onResizeGroupEnd = ({ events }) => {
|
|
|
// 旋转结束
|
|
// 旋转结束
|
|
|
const onRotateEnd = (e) => {
|
|
const onRotateEnd = (e) => {
|
|
|
const id = e.target.attributes['widget-id']?.value
|
|
const id = e.target.attributes['widget-id']?.value
|
|
|
|
|
+ if (id && hasLockedWidgetTree(projectStore.activeWidgetMap[id])) return
|
|
|
if (e.lastEvent && id && projectStore.activeWidgetMap[id]) {
|
|
if (e.lastEvent && id && projectStore.activeWidgetMap[id]) {
|
|
|
// 设置位置
|
|
// 设置位置
|
|
|
projectStore.activeWidgetMap[id].props.rotation = Math.round(e.lastEvent.rotate)
|
|
projectStore.activeWidgetMap[id].props.rotation = Math.round(e.lastEvent.rotate)
|