update code

main
haha 2024-07-09 00:40:30 +08:00
parent 4bcf5f9fef
commit 7ddabba1e0
7 changed files with 246 additions and 78 deletions

View File

@ -1,12 +1,8 @@
<template> <template>
<el-config-provider :locale="locale" :size="size"> <el-config-provider :locale="locale" :size="size">
<!-- 开启水印 --> <!-- 开启水印 -->
<el-watermark <el-watermark v-if="watermarkEnabled" :font="{ color: fontColor }" :content="defaultSettings.watermarkContent"
v-if="watermarkEnabled" class="wh-full">
:font="{ color: fontColor }"
:content="defaultSettings.watermarkContent"
class="wh-full"
>
<router-view /> <router-view />
</el-watermark> </el-watermark>
<!-- 关闭水印 --> <!-- 关闭水印 -->
@ -39,15 +35,28 @@ const fontColor = computed(() => {
background-color: #EEF3FB; background-color: #EEF3FB;
border-right: solid 3px var(--el-color-primary); border-right: solid 3px var(--el-color-primary);
} }
.table-container .el-form-item--default { .table-container .el-form-item--default {
margin-bottom: 0px !important; margin-bottom: 0px !important;
} }
.el-table__header { .el-table__header {
th { th {
background-color: #edebeb6e !important; background-color: #edebeb6e !important;
} }
} }
.el-pagination { .el-pagination {
justify-content: end; justify-content: end;
} }
.scroll::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.scroll::-webkit-scrollbar-thumb {
background-color: rgb(1, 169, 255);
border-radius: 4px;
}
</style> </style>

View File

@ -1,27 +1,34 @@
import { RectNode, RectNodeModel, h } from "@logicflow/core" import { RectNode, RectNodeModel, h } from "@logicflow/core";
import { getBytesLength } from '../util' import { getBytesLength } from "../util";
class RedNodeModel extends RectNodeModel { class RedNodeModel extends RectNodeModel {
/** /**
* 初始化 * 初始化
*/ */
initNodeData(data) { initNodeData(data) {
super.initNodeData(data) super.initNodeData(data);
this.width = 200; this.width = 200;
this.height = 30; this.height = 30;
this.radius = 5; this.radius = 5;
this.text.x = this.x + 10; this.text.x = this.x + 10;
this.defaultFill = data.fill||'rgb(253, 208, 162)' this.defaultFill = data.fill || "rgb(253, 208, 162)";
const startOnlyAsTarget={
message:"开始结点只能连接结束节点",
validate: (sourceNode, targetNode, sourceAnchor, targetAnchor) => {
return sourceAnchor.type !== targetAnchor.type;
},
};
this.sourceRules.push(startOnlyAsTarget);
} }
getData() { getData() {
const data = super.getData() const data = super.getData();
data.properties.ui = 'node-ai' data.properties.ui = "node-ai";
return data return data;
} }
updateText(val) { updateText(val) {
super.updateText(val) super.updateText(val);
this.setAttributes(); this.setAttributes();
} }
/** /**
@ -32,10 +39,10 @@ class RedNodeModel extends RectNodeModel {
const dataStyle = this.properties.style || {}; const dataStyle = this.properties.style || {};
if (this.isSelected) { if (this.isSelected) {
style.strokeWidth = Number(dataStyle.borderWidth) || 2; style.strokeWidth = Number(dataStyle.borderWidth) || 2;
style.stroke = dataStyle.borderColor || '#ff7f0e'; style.stroke = dataStyle.borderColor || "#ff7f0e";
} else { } else {
style.strokeWidth = Number(dataStyle.borderWidth) || 1; style.strokeWidth = Number(dataStyle.borderWidth) || 1;
style.stroke = dataStyle.borderColor || '#999'; style.stroke = dataStyle.borderColor || "#999";
} }
style.fill = dataStyle.backgroundColor || this.defaultFill; style.fill = dataStyle.backgroundColor || this.defaultFill;
return style; return style;
@ -48,16 +55,18 @@ class RedNodeModel extends RectNodeModel {
const anchors = [ const anchors = [
{ {
x: x, x: x,
y: y+ height / 2, y: y - height / 2,
id: `${id}_right`, id: `${id}_right`,
type: "right" type: "start",
className: "anchors-start",
}, },
{ {
x: x, x: x,
y: y- height / 2, y: y + height / 2,
id: `${id}_left`, id: `${id}_left`,
type: "left" type: "end",
} className: "anchors-end",
},
]; ];
return anchors; return anchors;
} }
@ -66,63 +75,64 @@ class RedNodeModel extends RectNodeModel {
*/ */
getOutlineStyle() { getOutlineStyle() {
const style = super.getOutlineStyle(); const style = super.getOutlineStyle();
style.stroke = 'transparent'; style.stroke = "transparent";
style.hover.stroke = 'transparent'; style.hover.stroke = "transparent";
return style; return style;
} }
handleContextMenu(ev) { handleContextMenu(ev) {
debugger debugger;
} }
} }
class RedNode extends RectNode { class RedNode extends RectNode {
/** /**
* 1.1.7版本后支持在view中重写锚点形状 * 1.1.7版本后支持在view中重写锚点形状
* 重写锚点新增 * 重写锚点新增
*/ */
getAnchorShape(anchorData) { getAnchorShape(anchorData) {
const { x, y, type } = anchorData; const { x, y, type, className } = anchorData;
if(type=="start"){
return h( "circle", {
cx: x - 0,
cy: y - 5,
r:6,
className: "custom-anchor " + className,
title:'开始'
});
}
return h( "rect", { return h( "rect", {
x: x - 5, x: x - 5,
y: y - 5, y: y - 5,
width: 10, width: 10,
height: 10, height: 10,
className: 'custom-anchor' className: "custom-anchor " + className,
title:'结束'
}); });
} }
getShape() { getShape() {
const { const { text, x, y, width, height, radius } = this.props.model;
text, const style = this.props.model.getNodeStyle();
x,
y,
width,
height,
radius
} = this.props.model;
const style = this.props.model.getNodeStyle()
return h( return h(
'g', "g",
{ {
className: 'lf-ai-node' className: "lf-ai-node",
}, },
[ [
h('rect', { h("rect", {
...style, ...style,
x: x - width / 2, x: x - width / 2,
y: y - height / 2, y: y - height / 2,
width, width,
height, height,
rx: radius, rx: radius,
ry: radius ry: radius,
}) }),
] ]
) );
} }
} }
export default { export default {
type: 'ai-node', type: "ai-node",
model: RedNodeModel, model: RedNodeModel,
view: RedNode view: RedNode,
} };

View File

@ -109,7 +109,7 @@
</div> </div>
</template> </template>
<script lang='ts' setup> <script setup>
import detailFlow from './detailFlow.vue'; import detailFlow from './detailFlow.vue';
import ConnApi from '@/api/connection' import ConnApi from '@/api/connection'
const router = useRouter(); const router = useRouter();

View File

@ -77,16 +77,29 @@
</div> </div>
<div class="row"> <div class="row">
<span class="sp-label">输入参数:</span> <span class="sp-label">输入参数:</span>
<span class="sp-text"> <span class="sp-text sp-paramter scroll" @click="doEdit(selNode.info,'输入参数','i')">
<el-input v-model="selNode.info.inputParams" type="textarea" style="width:100%;" <span v-for="(it,idx) in objToArr(selNode.info.inputParams) " :key="idx" class="param-item">
:rows="4" @input="doFlowInput" /> <span>{{ it.key }}:</span>
<span>{{ it.value }}</span>
</span>
</span> </span>
</div> </div>
<div class="row" style="margin-top:4px;"> <div class="row" style="margin-top:4px;">
<span class="sp-label">输出参数:</span> <span class="sp-label">输出参数:</span>
<span class="sp-text"> <span class="sp-text sp-paramter scroll" @click="doEdit(selNode.info,'输出参数','o')">
<el-input v-model="selNode.info.outputParams" type="textarea" style="width:100%;" <span v-for="(it,idx) in objToArr(selNode.info.outputParams) " :key="idx" class="param-item">
:rows="4" @input="doFlowInput" /> <span>{{ it.key }}:</span>
<span>{{ it.value }}</span>
</span>
</span>
</div>
<div class="row" style="margin-top:4px;">
<span class="sp-label">处理参数:</span>
<span class="sp-text sp-paramter scroll" @click="doEdit(selNode.info,'处理参数','p')">
<span v-for="(it,idx) in objToArr(selNode.info.process) " :key="idx" class="param-item">
<span>{{ it.key }}:</span>
<span>{{ it.value }}</span>
</span>
</span> </span>
</div> </div>
</div> </div>
@ -97,6 +110,7 @@
<el-button type="primary" @click="doSave"></el-button> <el-button type="primary" @click="doSave"></el-button>
<el-button @click="doCancel"></el-button> <el-button @click="doCancel"></el-button>
</el-card> </el-card>
<EditParamDlg ref="editDlg" @success="doEditSuccess"/>
</div> </div>
</template> </template>
@ -104,6 +118,7 @@
import nodePanel from './nodePanel.vue' import nodePanel from './nodePanel.vue'
import editFlow from './editFlow.vue' import editFlow from './editFlow.vue'
import ConnApi from '@/api/connection' import ConnApi from '@/api/connection'
import EditParamDlg from './editParamDlg.vue'
const router = useRouter(); const router = useRouter();
const uploadForm = ref(ElForm) const uploadForm = ref(ElForm)
const route = useRoute() const route = useRoute()
@ -114,9 +129,11 @@ const upForm = reactive({
connection_label: '', connection_label: '',
connection_desc: '' connection_desc: ''
}); });
const editDlg=ref()
const info = reactive({ const info = reactive({
connInfo: null, connInfo: null,
nodes: [], nodes: [],
editObj:null,
}) })
const selNode = reactive({ const selNode = reactive({
info: null info: null
@ -131,8 +148,48 @@ const doFlowInput = () => {
} else { } else {
tmps[0].inputParams = selNode.info.inputParams; tmps[0].inputParams = selNode.info.inputParams;
tmps[0].outputParams = selNode.info.outputParams; tmps[0].outputParams = selNode.info.outputParams;
tmps[0].process = selNode.info.process;
} }
} }
const doEditSuccess=(obj)=>{
let t=info.editObj.type;
if(t=='i'){
selNode.info.inputParams=obj;
}
if(t=='o'){
selNode.info.outputParams=obj;
}
if(t=='p'){
selNode.info.process=obj;
}
let tmps = info.nodes.filter(d => d.id == selNode.info.id);
if (tmps.length == 0) {
info.nodes.push(selNode.info)
} else {
tmps[0].inputParams = selNode.info.inputParams;
tmps[0].outputParams = selNode.info.outputParams;
tmps[0].process = selNode.info.process;
}
};
const doEdit=(obj,title,t)=>{
info.editObj={
obj:obj,
title:title,
type:t
}
editDlg.value.showDialog({
obj:t=='i'?obj.inputParams:t=='o'?obj.outputParams:obj.process,
title:title
});
}
const objToArr=(obj,t)=>{
let arr=[];
for(let k in obj){
arr.push({key:k,value:obj[k]})
}
return arr;
}
const doUpdateNode = (data) => { const doUpdateNode = (data) => {
if (ndPanel && ndPanel.value) { if (ndPanel && ndPanel.value) {
ndPanel.value.updateNode(data) ndPanel.value.updateNode(data)
@ -147,6 +204,7 @@ const doNodeClick = (node) => {
} else { } else {
selNode.info.inputParams = tmps[0].inputParams; selNode.info.inputParams = tmps[0].inputParams;
selNode.info.outputParams = tmps[0].outputParams; selNode.info.outputParams = tmps[0].outputParams;
selNode.info.process = tmps[0].process;
} }
} }
else { else {
@ -185,6 +243,22 @@ onMounted(() => {
align-items: center; align-items: center;
font-weight: bold; font-weight: bold;
} }
:deep(.anchors-end){
fill:red;
}
:deep(.anchors-start){
fill:green;
}
.sp-paramter{
height: 60px;
border:solid 1px #409EFF;
overflow-y: auto;
padding:4px;
cursor: pointer;
.param-item{
display:block;
}
}
} }
.card-footer { .card-footer {

View File

@ -4,7 +4,7 @@
</div> </div>
</template> </template>
<script lang='ts' setup> <script setup>
import LogicFlow from '@logicflow/core'; import LogicFlow from '@logicflow/core';
// //
import '@logicflow/core/dist/style/index.css'; import '@logicflow/core/dist/style/index.css';
@ -71,6 +71,9 @@ const initEvent=(lf)=>{
nodePropKey.value++ nodePropKey.value++
doUpdateState() doUpdateState()
}); });
lf.on("connection:not-allowed",(a,b,c)=>{
ElMessage.error("开始节点只能连接结束节点!");
});
lf.on("node:delete",data=>{ lf.on("node:delete",data=>{
if(data.data.text.value=="目标绘图"){ if(data.data.text.value=="目标绘图"){
ElMessage.error("目标绘图节点不能删除"); ElMessage.error("目标绘图节点不能删除");
@ -81,7 +84,7 @@ const initEvent=(lf)=>{
} }
doUpdateState() doUpdateState()
}); });
lf.on("node:contextmenu",(d,e,p)=>{ lf.on("node:contextmenu",(d)=>{
if(d.data.text.value=="目标绘图"){ if(d.data.text.value=="目标绘图"){
setTimeout(()=>{ setTimeout(()=>{
document.querySelector(".lf-menu").style.display="none"; document.querySelector(".lf-menu").style.display="none";

View File

@ -0,0 +1,67 @@
<template>
<el-dialog v-model="dialog.show" :title="dialog.title"
:close-on-press-escape="false"
:close-on-click-modal="false" align-center append-to-body width="600px"
>
<div class="scroll " style="max-height: 400px;overflow-y: auto;overflow-x: hidden;">
<el-row v-for="(it,idx) in dialog.attrs" :key="idx" style="margin-bottom:4px;" gutter="2">
<el-col :span="8">
<el-input v-model="it.key" @input="inputKey"/>
</el-col>
<el-col :span="16">
<el-input v-model="it.value"/>
</el-col>
</el-row>
</div>
<template #footer>
<div style="text-align: center">
<el-button type="primary" @click="doOk"></el-button>
<el-button @click="doCancel"></el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
const emit=defineEmits("success");
const dialog = reactive({
show: false,
title: '',
editObj: null,
attrs: []
})
const doOk = () => {
let obj={};
dialog.attrs.forEach(d=>{
if(d.key && d.value){
obj[d.key]=d.value;
}
});
emit("success",obj);
dialog.show=false;
}
const doCancel=()=>{
dialog.show=false;
}
const showDialog = (opt) => {
dialog.show = true;
dialog.editObj = opt.obj;
dialog.title = opt.title;
dialog.attrs = [];
for (let k in opt.obj) {
dialog.attrs.push({ key: k, value: opt.obj[k] });
}
dialog.attrs.push({key:'',value:''});
}
const inputKey=(a,b)=>{
if(dialog.attrs[dialog.attrs.length-1].key){
dialog.attrs.push({key:'',value:''});
}
};
defineExpose({
showDialog
})
</script>
<style scoped lang='less'></style>

View File

@ -84,12 +84,12 @@ const list2 = reactive([
const updateNode = (nodes) => { const updateNode = (nodes) => {
let nds = nodes.nodes.map(d => d.properties.node); let nds = nodes.nodes.map(d => d.properties.node);
list2.forEach(d => { if(info.all){
info.all.forEach(d => {
d.show = nds.indexOf(d.id) == -1 d.show = nds.indexOf(d.id) == -1
}) });
list1.forEach(d => { }
d.show = nds.indexOf(d.id) == -1
})
} }
const doEdit=(nd)=>{ const doEdit=(nd)=>{
@ -98,6 +98,7 @@ const doEdit=(nd)=>{
if(tmps.length>0){ if(tmps.length>0){
tmps[0].inputParams=nd.inputParams; tmps[0].inputParams=nd.inputParams;
tmps[0].outputParams=nd.inputParams; tmps[0].outputParams=nd.inputParams;
tmps[0].process=nd.process;
} }
} }
defineExpose({ defineExpose({
@ -111,8 +112,12 @@ const initData = () => {
it.show = true; it.show = true;
it.text = it.operator_name; it.text = it.operator_name;
it.id = it.operator_id it.id = it.operator_id
it.inputParams=""; it.inputParams={
it.outputParams=""; a:10,b:20,c:30,d:40,e:50,
a2:10,b2:20,c2:30,d2:40,e2:50,
};
it.outputParams={};
it.process={};
return it; return it;
}); });
info.all=tmps; info.all=tmps;