This commit is contained in:
zhang zhuo 2025-12-12 15:33:06 +08:00
parent 1121cb1664
commit 15e259b28f
6 changed files with 128 additions and 37 deletions

View File

@ -2,7 +2,7 @@
<el-container class="flow-editor">
<left-panel v-if="lf" :lf="lf"></left-panel>
<div ref="containerRef" class="flow-container"></div>
<div class="right-panel" v-if="activeNode"></div>
<right-panel v-if="lf" :lf="lf" :node="activeNode"></right-panel>
<menu-panel v-if="lf" :lf="lf" class="menu-panel"/>
</el-container>
</template>
@ -16,6 +16,7 @@ import "@logicflow/core/lib/style/index.css"
import "@logicflow/extension/lib/style/index.css"
import leftPanel from "./left.vue"
import menuPanel from "./menu.vue"
import rightPanel from "./right.vue"
import {StartNodeModel, StartNodeView, START_NODE_TYPES} from "./model/StartNode"
import {EventNodeModel, EventNodeView, EVENT_NODE_TYPES} from "./model/EventNode"
import {GatewayNodeModel, GatewayNodeView, GATEWAY_NODE_TYPES} from "./model/GatewayNode"
@ -180,27 +181,27 @@ function updateNodeProps() {
//
const handleKeydown = (event) => {
if (event.key === "Delete" || event.key === "Backspace") {
if (Object.keys(activeNode.value).length !== 0) {
ElMessageBox.confirm(
activeNode.value.type === 'line' ? t('flow.deleteLine') : t('flow.deleteNode'),
t('system.warning'),
{
confirmButtonText: t('system.ok'),
cancelButtonText: t('system.cancel'),
type: 'warning',
}
).then(() => {
if (activeNode.value.type === 'line') {
lf.value.deleteEdge(activeNode.value.id);
} else {
lf.value.deleteNode(activeNode.value.id);
}
}).catch(() => {
})
}
return
}
// if (event.key === "Delete" || event.key === "Backspace") {
// if (Object.keys(activeNode.value).length !== 0) {
// ElMessageBox.confirm(
// activeNode.value.type === 'line' ? t('flow.deleteLine') : t('flow.deleteNode'),
// t('system.warning'),
// {
// confirmButtonText: t('system.ok'),
// cancelButtonText: t('system.cancel'),
// type: 'warning',
// }
// ).then(() => {
// if (activeNode.value.type === 'line') {
// lf.value.deleteEdge(activeNode.value.id);
// } else {
// lf.value.deleteNode(activeNode.value.id);
// }
// }).catch(() => {
// })
// }
// return
// }
const directionKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
if (directionKeys.includes(event.key)) {
@ -257,13 +258,6 @@ const handleKeydown = (event) => {
height: calc(100% - 3px);
}
.right-panel {
width: 320px;
background: #fff;
border-left: 1px solid var(--el-border-color-light);
padding: 10px;
}
:deep(.lf-mini-map) {
background: #FFF;
border: 1px solid #eee;

View File

@ -0,0 +1,84 @@
<template>
<el-aside class="panel">
<el-scrollbar>
<el-tabs v-model="activeName" stretch>
<el-tab-pane v-if="activeName==='line'" label="连线属性" name="line">
<el-form :model="form" label-width="90px">
<el-form-item label="连线ID" prop="id">
<el-input v-model="form.id" disabled></el-input>
</el-form-item>
<el-form-item label="连线名称" prop="text">
<el-input v-model="form.text" @input="onInput"/>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane v-else-if="activeName==='node'" label="节点属性" name="node">
<el-form :model="form" label-width="90px">
<el-form-item label="节点ID" prop="id">
<el-input v-model="form.id" disabled></el-input>
</el-form-item>
<el-form-item label="节点名称" prop="text">
<el-input v-model="form.text" @input="onInput"/>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane v-else label="流程设置" name="flow">
</el-tab-pane>
</el-tabs>
</el-scrollbar>
</el-aside>
</template>
<script setup>
import {ref, watch} from "vue"
import LogicFlow from "@logicflow/core";
const props = defineProps({
node: {type: Object, default: {}},
lf: {type: LogicFlow}
})
const activeName = ref('node')
const form = ref({
id: null,
text: null
})
watch(() => props.node, () => {
changeActive()
form.value.id = props.node.id
form.value.text = props.node?.text?.value
}, {deep: true})
const onInput = () => {
updateEdgeLabel(form.value.id, form.value.text)
}
function changeActive() {
if (Object.keys(props.node).length === 0) {
activeName.value = 'flow'
}else if (props.node.type === 'line') {
activeName.value = 'line'
}else {
activeName.value = 'node'
}
}
function updateEdgeLabel(edgeId, newLabel) {
let edge = props.lf?.graphModel?.getEdgeModelById(edgeId);
if (!edge) {
edge = props.lf?.graphModel?.getNodeModelById(edgeId);
}
if (!edge) return;
edge.updateText(newLabel);
}
</script>
<style scoped>
.panel {
width: 320px;
background: #fff;
border-left: 1px solid var(--el-border-color-light);
padding: 10px;
user-select: none;
}
</style>

View File

@ -80,7 +80,6 @@ async function copyCode() {
fields: props.data.fields,
config: props.data.config
})
console.log(res.data['form.vue'])
navigator.clipboard.writeText(res.data['form.vue'])
proxy.$message.success("复制成功")
}
@ -90,7 +89,17 @@ async function downFile() {
fields: props.data.fields,
config: props.data.config
})
console.log(res)
await saveFile(res.data['form.vue'])
}
async function saveFile(content, filename = 'form.vue') {
const blob = new Blob([content], {type: 'text/plain;charset=utf-8'})
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = filename
link.click()
URL.revokeObjectURL(url)
}
</script>

View File

@ -1,6 +1,6 @@
<template>
<el-container class="pi-panel">
<left-panel :data="formData"></left-panel>
<left-panel :data="formData" :field="field"></left-panel>
<center-panel ref="centerRef" :data="formData" :field="field"></center-panel>
<right-panel :data="formData" :field="field"></right-panel>
</el-container>

View File

@ -80,7 +80,8 @@ import FormBuild from "./formBuild"
import {inputComps, choiceComps, layoutComps} from "./config"
const props = defineProps({
data: {type: FormBuild, default: {}}
data: {type: FormBuild, default: {}},
field: {type: Object, default: {}}
})
const group = {name: 'base', pull: 'clone', put: false}
@ -95,7 +96,7 @@ function cloneField(e) {
function handleClick(e) {
let field = cloneField(e)
props.data.fields.push(field)
props.data.setActiveField(field)
props.field.element = field
}
</script>
@ -103,6 +104,7 @@ function handleClick(e) {
.panel {
width: 260px;
padding: 10px;
user-select: none;
.title {
margin-bottom: 10px;

View File

@ -74,12 +74,13 @@
</template>
</pi-draggable>
</template>
<template v-if="form.name !== 'button' && form.name !== 'layout'">
<template v-if="form.name !== 'button' && form.name !== 'layout' && form.rules !== undefined">
<el-divider>正则校验</el-divider>
<pi-draggable v-model="form.rules" item-key="regex" :template="{regex:'',message:''}">
<pi-draggable v-model="form.rules" item-key="regex"
:template="{pattern:'',message:'', trigger: 'blur'}">
<template #default="scope">
<el-form-item label="表达式">
<el-input v-model="scope.element.regex"/>
<el-input v-model="scope.element.pattern"/>
</el-form-item>
<el-form-item label="错误提示">
<el-input v-model="scope.element.message"/>
@ -149,6 +150,7 @@ let form = computed(() => {
.panel {
width: 350px;
padding: 10px;
user-select: none;
border-left: 1px solid var(--el-border-color-light);
}