This commit is contained in:
lzp
2026-03-02 13:51:14 +08:00
parent d49c00376d
commit 13e3e5dcc5
8 changed files with 62 additions and 19 deletions

View File

@@ -107,6 +107,7 @@
const componentRef = ref(null) const componentRef = ref(null)
const onGenerateClick = () => { const onGenerateClick = () => {
const data = { ...componentRef.value.data } const data = { ...componentRef.value.data }
if (attrs.node.data) attrs.node.data.data = data
nodeManager.createResultNode({ nodeManager.createResultNode({
data: { data: {
tier: currentComponent.value.tier, tier: currentComponent.value.tier,

View File

@@ -10,6 +10,10 @@
<span class="icon"><svg-icon name="export" size="11" /></span> <span class="icon"><svg-icon name="export" size="11" /></span>
<span class="text">Export</span> <span class="text">Export</span>
</button> </button>
<button class="import" @click="emit('import')">
<span class="icon"><svg-icon name="import" size="11" /></span>
<span class="text">Import</span>
</button>
</div> </div>
</template> </template>
@@ -19,7 +23,7 @@
zoom: { default: 1, type: Number }, zoom: { default: 1, type: Number },
step: { default: 0.1, type: Number } step: { default: 0.1, type: Number }
}) })
const emit = defineEmits(['mouse', 'hand', 't', 'undo', 'redo', 'export']) const emit = defineEmits(['mouse', 'hand', 't', 'undo', 'redo', 'export', 'import'])
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@@ -60,7 +64,7 @@
background-color: #dfdfdf; background-color: #dfdfdf;
} }
} }
> .export { > button {
width: 10rem; width: 10rem;
height: 3rem; height: 3rem;
border-radius: 0.4rem; border-radius: 0.4rem;

View File

@@ -18,13 +18,22 @@
import { reactive, computed } from 'vue' import { reactive, computed } from 'vue'
const emit = defineEmits(['update:modelValue', 'change']) const emit = defineEmits(['update:modelValue', 'change'])
const props = defineProps({ const props = defineProps({
modelValue: { type: [File, null] }, modelValue: { type: [File, Object, String, null] },
tip: { type: String, default: 'Upload your files' } tip: { type: String, default: 'Upload your files' }
}) })
const data = reactive({ const data = reactive({
file: null file: null
}) })
const url = computed(() => (props.modelValue ? URL.createObjectURL(props.modelValue) : '')) const url = computed(() => {
const type = props.modelValue?.constructor
var str = ''
if (type === File) {
str = URL.createObjectURL(props.modelValue as File)
} else if (type === String) {
str = props.modelValue as string
}
return str
})
const onChange = (v) => { const onChange = (v) => {
emit('update:modelValue', v) emit('update:modelValue', v)
emit('change', v) emit('change', v)

View File

@@ -14,7 +14,7 @@
<template v-for="v in nodeTypes" :key="v" #[`node-${v}`]="nodeProps"> <template v-for="v in nodeTypes" :key="v" #[`node-${v}`]="nodeProps">
<node :type="v" :stateManager="stateManager" :node="nodeProps"> <node :type="v" :stateManager="stateManager" :node="nodeProps">
<component <component
:is="nodeProps.data.component" :is="components[nodeProps.data.component]"
:node="nodeProps" :node="nodeProps"
:data="nodeProps.data.data" :data="nodeProps.data.data"
v-bind="nodeProps.data" v-bind="nodeProps.data"
@@ -23,7 +23,7 @@
</template> </template>
</VueFlow> </VueFlow>
</div> </div>
<header-tools @export="exportFlow" /> <header-tools @export="exportFlow" @import="importFlow" />
<zoom <zoom
:zoom="stateManager.zoom.value" :zoom="stateManager.zoom.value"
:step="0.1" :step="0.1"
@@ -34,13 +34,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { VueFlow, useVueFlow } from '@vue-flow/core' import { VueFlow, useVueFlow } from '@vue-flow/core'
import { computed, ref, markRaw, onMounted, reactive, nextTick, provide } from 'vue'
import { useLayout } from '@/utils/treeDiagram' import { useLayout } from '@/utils/treeDiagram'
import { NODE_TYPE } from './tools/index.d' import { NODE_TYPE, NODE_COMPONENT } from './tools/index.d'
// 组件 // 组件
import headerTools from './components/header-tools.vue' import headerTools from './components/header-tools.vue'
import zoom from '../components/zoom.vue' import zoom from '../components/zoom.vue'
// 节点
import node from './components/node.vue' import node from './components/node.vue'
import { computed, ref, markRaw, onMounted, reactive, nextTick, provide } from 'vue' import resultImage from './components/result/result-image.vue'
import card from './components/cards/index.vue'
const components = {
[NODE_COMPONENT.RESULT_IMAGE]: resultImage,
[NODE_COMPONENT.CARD]: card
}
// 管理器 // 管理器
import { StateManager } from './manager/StateManager' import { StateManager } from './manager/StateManager'
@@ -83,7 +90,7 @@
const { layout } = useLayout() const { layout } = useLayout()
const index = ref(0) const index = ref(0)
async function layoutGraph(direction) { async function layoutGraph(direction) {
if (index.value > 0) return // if (index.value > 0) return
index.value++ index.value++
setTimeout(() => { setTimeout(() => {
stateManager.nodes.value = layout( stateManager.nodes.value = layout(
@@ -99,8 +106,24 @@
const exportFlow = () => { const exportFlow = () => {
// flowManager.exportFlow() // flowManager.exportFlow()
const json = JSON.parse(JSON.stringify(stateManager.nodes.value)) const str = JSON.stringify(stateManager.nodes.value)
console.log(json) const json = JSON.parse(str)
localStorage.setItem('flow_json', str)
}
const importFlow = async () => {
try {
stateManager.nodes.value = []
await nextTick()
const json = JSON.parse(localStorage.getItem('flow_json') || '[]')
stateManager.nodes.value = json
setTimeout(() => {
nextTick(() => {
fitView({ maxZoom: 1 })
})
}, 0)
} catch (error) {
console.log(error)
}
} }
onMounted(() => { onMounted(() => {

View File

@@ -1,7 +1,5 @@
import { createId } from '../../tools/tools' import { createId } from '../../tools/tools'
import card from '../components/cards/index.vue' import { NODE_DATATYPE, NODE_COMPONENT } from '../tools/index.d'
import resultImage from '../components/result/result-image.vue'
import { NODE_DATATYPE } from '../tools/index.d'
interface NodeOptions { interface NodeOptions {
id?: string id?: string
position?: { x: number, y: number } position?: { x: number, y: number }
@@ -51,7 +49,7 @@ export class NodeManager {
createResultNode(options?: NodeOptions) { createResultNode(options?: NodeOptions) {
const options_ = { const options_ = {
...(options ? options : {}), ...(options ? options : {}),
component: resultImage, component: NODE_COMPONENT.RESULT_IMAGE,
data: { data: {
tier: 0, tier: 0,
type: NODE_DATATYPE.RESULT_IMAGE, type: NODE_DATATYPE.RESULT_IMAGE,
@@ -65,7 +63,7 @@ export class NodeManager {
createCardsSelect(options?: NodeOptions) { createCardsSelect(options?: NodeOptions) {
const options_ = { const options_ = {
...(options ? options : {}), ...(options ? options : {}),
component: card, component: NODE_COMPONENT.CARD,
positionY: 50, positionY: 50,
data: { data: {
tier: 1, tier: 1,
@@ -79,7 +77,7 @@ export class NodeManager {
createCardNode(options?: NodeOptions) { createCardNode(options?: NodeOptions) {
const options_ = { const options_ = {
...(options ? options : {}), ...(options ? options : {}),
component: card, component: NODE_COMPONENT.CARD,
} }
return this.createNode(options_) return this.createNode(options_)
} }

View File

@@ -56,7 +56,7 @@ export class StateManager {
id: `el-${id}-${target}`, id: `el-${id}-${target}`,
source: id, source: id,
target: target, target: target,
type: 'output' type: 'default'
}) })
} }
}) })

View File

@@ -1,3 +1,11 @@
/**
* 组件
*/
export const NODE_COMPONENT = {
RESULT_IMAGE: 'result-image',
CARD: 'card',
}
/** /**
* 节点类型 * 节点类型
*/ */

View File

@@ -1,6 +1,6 @@
// 定义要忽略的警告关键词列表 // 定义要忽略的警告关键词列表
const ignoredWarnings = [ const ignoredWarnings = [
'`markRaw` or using `shallowRef` instead of `ref`', // '`markRaw` or using `shallowRef` instead of `ref`',
] ]
/** 忽略组件响应式警告 */ /** 忽略组件响应式警告 */