mirror of
https://github.com/Powerful-517/yys-editor.git
synced 2025-07-08 13:21:53 +00:00
支持组件缩放
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue';
|
import {ref, watch} from 'vue';
|
||||||
import { Handle, useVueFlow } from '@vue-flow/core';
|
import {Handle, useVueFlow} from '@vue-flow/core';
|
||||||
import { NodeResizer } from '@vue-flow/node-resizer';
|
import {NodeResizer} from '@vue-flow/node-resizer';
|
||||||
import '@vue-flow/node-resizer/dist/style.css';
|
import '@vue-flow/node-resizer/dist/style.css';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -17,18 +17,19 @@ const nodeHeight = ref(120);
|
|||||||
watch(() => props.data, (newData) => {
|
watch(() => props.data, (newData) => {
|
||||||
if (newData && newData.width) nodeWidth.value = newData.width;
|
if (newData && newData.width) nodeWidth.value = newData.width;
|
||||||
if (newData && newData.height) nodeHeight.value = newData.height;
|
if (newData && newData.height) nodeHeight.value = newData.height;
|
||||||
}, { immediate: true });
|
}, {immediate: true});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="image-node" :style="{ width: `${nodeWidth}px`, height: `${nodeHeight}px` }">
|
<NodeResizer v-if="selected" :min-width="60" :min-height="60" :max-width="400" :max-height="400"/>
|
||||||
<NodeResizer v-if="selected" :min-width="60" :min-height="60" :max-width="400" :max-height="400" />
|
<div class="image-node">
|
||||||
<Handle type="target" position="left" :id="`${id}-target`" />
|
<Handle type="target" position="left" :id="`${id}-target`"/>
|
||||||
<div class="image-content">
|
<div class="image-content">
|
||||||
<img v-if="props.data && props.data.url" :src="props.data.url" alt="图片节点" style="width:100%;height:100%;object-fit:contain;" />
|
<img v-if="props.data && props.data.url" :src="props.data.url" alt="图片节点"
|
||||||
|
style="width:100%;height:100%;object-fit:contain;"/>
|
||||||
<div v-else class="image-placeholder">未上传图片</div>
|
<div v-else class="image-placeholder">未上传图片</div>
|
||||||
</div>
|
</div>
|
||||||
<Handle type="source" position="right" :id="`${id}-source`" />
|
<Handle type="source" position="right" :id="`${id}-source`"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@ -41,14 +42,22 @@ watch(() => props.data, (newData) => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 180px;
|
||||||
|
min-height: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-content {
|
.image-content {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-placeholder {
|
.image-placeholder {
|
||||||
color: #bbb;
|
color: #bbb;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -205,15 +205,14 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="property-node" :class="[currentProperty.priority ? `priority-${currentProperty.priority}` : '']" :style="{ width: `${nodeWidth}px`, height: `${nodeHeight}px` }">
|
<NodeResizer
|
||||||
<NodeResizer
|
|
||||||
v-if="selected"
|
v-if="selected"
|
||||||
:min-width="150"
|
:min-width="150"
|
||||||
:min-height="150"
|
:min-height="150"
|
||||||
:max-width="300"
|
:max-width="300"
|
||||||
:max-height="300"
|
:max-height="300"
|
||||||
/>
|
/>
|
||||||
|
<div class="property-node" :class="[currentProperty.priority ? `priority-${currentProperty.priority}` : '']" >
|
||||||
<!-- 输入连接点 -->
|
<!-- 输入连接点 -->
|
||||||
<Handle type="target" position="left" :id="`${id}-target`" />
|
<Handle type="target" position="left" :id="`${id}-target`" />
|
||||||
|
|
||||||
@ -252,12 +251,28 @@ defineExpose({
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.property-node {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 180px;
|
||||||
|
min-height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
.node-content {
|
.node-content {
|
||||||
|
position: relative;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: 1px solid #dcdfe6;
|
border: 1px solid #dcdfe6;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
min-width: 180px;
|
||||||
|
min-height: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.vue-flow__node-resizer) {
|
:deep(.vue-flow__node-resizer) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
import {ref, onMounted, onUnmounted, watch} from 'vue';
|
||||||
import { Handle, Position, useVueFlow } from '@vue-flow/core';
|
import {Handle, Position, useVueFlow} from '@vue-flow/core';
|
||||||
import { NodeResizer } from '@vue-flow/node-resizer'
|
import {NodeResizer} from '@vue-flow/node-resizer'
|
||||||
import '@vue-flow/node-resizer/dist/style.css';
|
import '@vue-flow/node-resizer/dist/style.css';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -11,10 +11,10 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取Vue Flow的实例和节点更新方法
|
// 获取Vue Flow的实例和节点更新方法
|
||||||
const { findNode, updateNode } = useVueFlow();
|
const {findNode, updateNode} = useVueFlow();
|
||||||
|
|
||||||
// 御魂信息保存在节点数据中
|
// 御魂信息保存在节点数据中
|
||||||
const currentYuhun = ref({ name: '未选择御魂', avatar: '', type: '' });
|
const currentYuhun = ref({name: '未选择御魂', avatar: '', type: ''});
|
||||||
|
|
||||||
// 节点尺寸
|
// 节点尺寸
|
||||||
const nodeWidth = ref(180);
|
const nodeWidth = ref(180);
|
||||||
@ -25,7 +25,7 @@ watch(() => props.data, (newData) => {
|
|||||||
if (newData && newData.yuhun) {
|
if (newData && newData.yuhun) {
|
||||||
currentYuhun.value = newData.yuhun;
|
currentYuhun.value = newData.yuhun;
|
||||||
}
|
}
|
||||||
}, { immediate: true });
|
}, {immediate: true});
|
||||||
|
|
||||||
// 更新御魂信息的方法(将由App.vue调用)
|
// 更新御魂信息的方法(将由App.vue调用)
|
||||||
const updateNodeYuhun = (yuhun) => {
|
const updateNodeYuhun = (yuhun) => {
|
||||||
@ -34,18 +34,18 @@ const updateNodeYuhun = (yuhun) => {
|
|||||||
|
|
||||||
// 备用方案:通过全局事件总线监听更新
|
// 备用方案:通过全局事件总线监听更新
|
||||||
const handleYuhunUpdate = (event) => {
|
const handleYuhunUpdate = (event) => {
|
||||||
const { nodeId, yuhun } = event.detail;
|
const {nodeId, yuhun} = event.detail;
|
||||||
if (nodeId === props.id) {
|
if (nodeId === props.id) {
|
||||||
updateNodeYuhun(yuhun);
|
updateNodeYuhun(yuhun);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理调整大小
|
// 处理调整大小
|
||||||
const handleResize = (event, { width, height }) => {
|
const handleResize = (event, {width, height}) => {
|
||||||
// 更新本地状态
|
// 更新本地状态
|
||||||
nodeWidth.value = width;
|
nodeWidth.value = width;
|
||||||
nodeHeight.value = height;
|
nodeHeight.value = height;
|
||||||
|
|
||||||
// 更新Vue Flow中的节点
|
// 更新Vue Flow中的节点
|
||||||
const node = findNode(props.id);
|
const node = findNode(props.id);
|
||||||
if (node) {
|
if (node) {
|
||||||
@ -65,7 +65,7 @@ onMounted(() => {
|
|||||||
console.log('YuhunSelectNode mounted:', props.id);
|
console.log('YuhunSelectNode mounted:', props.id);
|
||||||
// 添加全局事件监听
|
// 添加全局事件监听
|
||||||
window.addEventListener('update-yuhun', handleYuhunUpdate);
|
window.addEventListener('update-yuhun', handleYuhunUpdate);
|
||||||
|
|
||||||
// 初始化时检查是否有数据
|
// 初始化时检查是否有数据
|
||||||
if (props.data && props.data.yuhun) {
|
if (props.data && props.data.yuhun) {
|
||||||
currentYuhun.value = props.data.yuhun;
|
currentYuhun.value = props.data.yuhun;
|
||||||
@ -84,26 +84,25 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="yuhun-node" :style="{ width: `${nodeWidth}px`, height: `${nodeHeight}px` }">
|
<NodeResizer
|
||||||
<NodeResizer
|
|
||||||
v-if="selected"
|
v-if="selected"
|
||||||
:min-width="150"
|
:min-width="150"
|
||||||
:min-height="150"
|
:min-height="150"
|
||||||
:max-width="300"
|
:max-width="300"
|
||||||
:max-height="300"
|
:max-height="300"
|
||||||
/>
|
/>
|
||||||
|
<div class="yuhun-node" >
|
||||||
<!-- 输入连接点 -->
|
<!-- 输入连接点 -->
|
||||||
<Handle type="target" position="left" :id="`${id}-target`" />
|
<Handle type="target" position="left" :id="`${id}-target`"/>
|
||||||
|
|
||||||
<div class="node-content">
|
<div class="node-content">
|
||||||
<div class="node-header">
|
<div class="node-header">
|
||||||
<div class="node-title">御魂选择</div>
|
<div class="node-title">御魂选择</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="node-body">
|
<div class="node-body">
|
||||||
<div v-if="currentYuhun.avatar" class="yuhun-avatar">
|
<div v-if="currentYuhun.avatar" class="yuhun-avatar">
|
||||||
<img :src="currentYuhun.avatar" alt="御魂图片" />
|
<img :src="currentYuhun.avatar" alt="御魂图片"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="yuhun-placeholder">
|
<div v-else class="yuhun-placeholder">
|
||||||
点击选择御魂
|
点击选择御魂
|
||||||
@ -112,19 +111,35 @@ defineExpose({
|
|||||||
<div v-if="currentYuhun.type" class="yuhun-type">{{ currentYuhun.type }}</div>
|
<div v-if="currentYuhun.type" class="yuhun-type">{{ currentYuhun.type }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 输出连接点 -->
|
<!-- 输出连接点 -->
|
||||||
<Handle type="source" position="right" :id="`${id}-source`" />
|
<Handle type="source" position="right" :id="`${id}-source`"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.yuhun-node {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 180px;
|
||||||
|
min-height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
.node-content {
|
.node-content {
|
||||||
|
position: relative;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: 1px solid #dcdfe6;
|
border: 1px solid #dcdfe6;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
min-width: 180px;
|
||||||
|
min-height: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.vue-flow__node-resizer) {
|
:deep(.vue-flow__node-resizer) {
|
||||||
|
Reference in New Issue
Block a user