rev:流程引擎

This commit is contained in:
2024-04-28 14:23:03 +08:00
parent 16f05d5567
commit 5f115921b8
34 changed files with 1028 additions and 114 deletions

View File

@@ -24,4 +24,26 @@ export function edit(data) {
})
}
export default {add, edit, del}
export function getTypes(data) {
return request({
url: '/api/bmFormStruc/getTypes',
method: 'get',
data
})
}
export function getTaskTypes() {
return request({
url: '/api/flow/getTaskTypes',
method: 'get'
})
}
export function getStrategyList() {
return request({
url: '/api/flow/getStrategyList',
method: 'get'
})
}
export default {add, edit, del, getTypes, getTaskTypes, getStrategyList}

View File

@@ -26,16 +26,13 @@
<el-form-item label="模型名称" prop="name">
<el-input v-model="form.name" style="width: 370px;"/>
</el-form-item>
<el-form-item label="模型KEY">
<el-input v-model="form.model_key" style="width: 370px;"/>
</el-form-item>
<el-form-item label="模型描述">
<el-input v-model="form.description" style="width: 370px;"/>
</el-form-item>
<el-form-item label="模型注释">
<el-input v-model="form.model_comment" style="width: 370px;"/>
</el-form-item>
<el-form-item label="版本号">
<el-form-item v-if="crud.status.edit" label="版本号">
<el-input v-model="form.version" style="width: 370px;"/>
</el-form-item>
<el-form-item label="模型数据">
@@ -48,7 +45,14 @@
<el-input v-model="form.model_type" style="width: 370px;"/>
</el-form-item>
<el-form-item label="单据类型">
<el-input v-model="form.form_type" style="width: 370px;"/>
<el-select v-model="form.form_type" placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in formTypes"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="归属租户">
<el-input v-model="form.tenant_id" style="width: 370px;"/>
@@ -90,6 +94,7 @@
align="center"
>
<template slot-scope="scope">
<el-button @click="viewClick(scope.row)" type="text" icon="el-icon-thumb" size="small">预览</el-button>
<el-button @click="handleClick(scope.row)" type="text" icon="el-icon-thumb" size="small">设计</el-button>
<udOperation
:data="scope.row"
@@ -102,6 +107,7 @@
<pagination/>
</div>
<FlowDesigner ref="flowDesigner"/>
<ViewFlowDesigner ref="viewFlowDesigner"/>
</div>
</template>
@@ -113,6 +119,7 @@ import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
import FlowDesigner from '../../../flow_manage/logicflow/FlowDesigner';
import ViewFlowDesigner from '../../../flow_manage/logicflow/ViewFlowDesigner';
const defaultForm = {
id: null,
@@ -134,7 +141,7 @@ const defaultForm = {
export default {
dicts: [],
name: 'ActDeModel',
components: {pagination, crudOperation, rrOperation, udOperation, FlowDesigner},
components: {pagination, crudOperation, rrOperation, udOperation, FlowDesigner, ViewFlowDesigner},
mixins: [presenter(), header(), form(defaultForm), crud()],
cruds() {
return CRUD({
@@ -151,6 +158,7 @@ export default {
},
data() {
return {
formTypes: [],
permission: {},
rules: {
name: [
@@ -159,6 +167,9 @@ export default {
}
}
},
created() {
this.getTypes();
},
methods: {
// 钩子在获取表格数据之前执行false 则代表不获取数据
[CRUD.HOOK.beforeRefresh]() {
@@ -167,6 +178,14 @@ export default {
handleClick(row) {
//console.log(row);
this.$refs.flowDesigner.showLogicFlowDesigner(row);
},
viewClick(row) {
this.$refs.viewFlowDesigner.showLogicFlowDesigner(row);
},
getTypes() {
curdActDeModel.getTypes().then(res => {
this.formTypes = res
})
}
}
}

View File

@@ -77,7 +77,10 @@ import {
registerScriptTask,
registerSendTask,
registerFormTask,
registerGatewayTask
registerGatewayTask,
registerstorInvTask,
registerExecuteFlow,
sequence,
} from './registerNode'
//const demoData = require('./data.json')
@@ -216,6 +219,10 @@ export default {
registerSendTask(this.lf)
registerFormTask(this.lf)
registerGatewayTask(this.lf)
registerstorInvTask(this.lf)
registerExecuteFlow(this.lf)
this.lf.register(sequence)
this.lf.setDefaultEdgeType("sequenceFlow");
this.$_render(row)
},
/**

View File

@@ -107,6 +107,20 @@ export default {
background-size: cover;
}
.node-storInv-task {
background: url('../background/storInvTask.png') no-repeat;
width: 45px;
height: 40px;
background-size: cover;
}
.node-execute-flow {
background: url('../background/executeFlow.png') no-repeat;
width: 45px;
height: 45px;
background-size: cover;
}
/*.node-user {*/
/* background: url('../background/user.png') no-repeat;*/
/* background-size: cover;*/

View File

@@ -0,0 +1,123 @@
<template>
<div>
<el-form label-width="80px" :rules="rules" ref="formRef" :model="formData">
<el-form-item label="id" prop="id">
<el-input v-model="formData.id" disabled></el-input>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="任务类型" prop="task_type">
<el-select clearable v-model="formData.task_type" placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in taskTypes"
v-if="item.value === '2'"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item v-if="formData.task_type === '1' || formData.task_type === '2'" label="表达式" prop="skipExpression">
<el-input v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item v-else-if="formData.task_type === '3'" label="表达式" prop="skipExpression">
<el-input type="textarea" v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item v-else-if="formData.task_type === '4'" label="表达式" prop="skipExpression">
<el-select clearable v-model="formData.skipExpression" multiple placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in strategyList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import curdActDeModel from "../../act/model/curdActDeModel";
export default {
name: '',
props: {
nodeData: Object,
lf: Object || String,
},
mounted() {
const {properties, text} = this.$props.nodeData
if (properties) {
this.$data.formData = Object.assign({}, this.$data.formData, properties)
}
if (text && text.value) {
this.$data.formData.text = text.value
}
if (text && text.value) {
this.$data.text = text.value
}
if (!this.formData.id) {
this.formData.id = this.generateUniqueId();
}
this.getTaskTypes()
this.getStrategyList()
},
data() {
return {
text: '',
taskTypes: [],
strategyList: [],
formData: {
id: '',
name: '',
task_type: ''
},
rules: {
id: [
{required: true, message: 'ID不能为空', trigger: 'blur'}
],
name: [
{required: true, message: '名称不能为空', trigger: 'blur'}
],
}
}
},
methods: {
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
const {id} = this.$props.nodeData;
this.$props.lf.setProperties(id, {...this.formData});
this.$props.lf.updateText(id, this.formData.text);
this.$notify({
title: '保存成功',
message: '请点击上方保存数据按钮,进行持久化!',
type: 'success',
offset: 100
});
this.$emit('onClose'); // 关闭对话框或完成后续操作
}
});
},
generateUniqueId() {
return `id_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
},
getTaskTypes() {
curdActDeModel.getTaskTypes().then(res => {
this.taskTypes = res
})
},
getStrategyList() {
curdActDeModel.getStrategyList().then(res => {
this.strategyList = res
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -7,14 +7,42 @@
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="节点描述" prop="documentation">
<el-input v-model="formData.documentation"></el-input>
<el-form-item label="任务类型" prop="task_type">
<el-select clearable v-model="formData.task_type" placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in taskTypes"
v-if="item.value !== '4'"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="表单Id" prop="formId">
<el-input v-model="formData.formId"></el-input>
<el-form-item v-if="formData.task_type === '1' || formData.task_type === '2'" label="表达式" prop="skipExpression">
<el-input v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item label="任务类型" prop="taskType">
<el-input v-model="formData.taskType"></el-input>
<el-form-item v-else-if="formData.task_type === '3'" label="表达式" prop="skipExpression">
<el-input type="textarea" v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item v-else-if="formData.task_type === '4'" label="表达式" prop="skipExpression">
<el-select clearable v-model="formData.skipExpression" multiple placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in strategyList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="单据类型" prop="form_type">
<el-select clearable v-model="formData.form_type" placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in formTypes"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
@@ -23,6 +51,8 @@
</div>
</template>
<script>
import curdActDeModel from "../../act/model/curdActDeModel";
export default {
name: '',
props: {
@@ -43,17 +73,22 @@ export default {
if (!this.formData.id) {
this.formData.id = this.generateUniqueId();
}
this.getTypes()
this.getTaskTypes()
this.getStrategyList()
},
data() {
return {
text: '',
formTypes: [],
taskTypes: [],
strategyList: [],
formData: {
id: '',
name: '',
documentation: '',
listener: '',
formId: '',
taskType: ''
task_type: '',
skipExpression: '',
form_type: ''
},
rules: {
id: [
@@ -71,7 +106,7 @@ export default {
if (valid) {
const {id} = this.$props.nodeData;
this.$props.lf.setProperties(id, {...this.formData});
this.$props.lf.updateText(id, this.formData.text);
this.$props.lf.updateText(id, this.formData.name);
this.$notify({
title: '保存成功',
message: '请点击上方保存数据按钮,进行持久化!',
@@ -84,6 +119,21 @@ export default {
},
generateUniqueId() {
return `id_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
},
getTypes() {
curdActDeModel.getTypes().then(res => {
this.formTypes = res
})
},
getTaskTypes() {
curdActDeModel.getTaskTypes().then(res => {
this.taskTypes = res
})
},
getStrategyList() {
curdActDeModel.getStrategyList().then(res => {
this.strategyList = res
})
}
}
}

View File

@@ -19,7 +19,6 @@
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
<el-button @click="testMethod">点击我测试</el-button>
</el-form-item>
</el-form>
</div>

View File

@@ -10,6 +10,21 @@
:nodeData="nodeData"
:lf="lf"
@onClose="handleClose"/>
<SequenceFlowProperties
v-if="nodeData.type === 'sequenceFlow'"
:nodeData="nodeData"
:lf="lf"
@onClose="handleClose"/>
<StorInvTaskProperties
v-if="nodeData.type === 'storInvTask'"
:nodeData="nodeData"
:lf="lf"
@onClose="handleClose"/>
<ExecuteFlowProperties
v-if="nodeData.type === 'executeFlow'"
:nodeData="nodeData"
:lf="lf"
@onClose="handleClose"/>
<ServerTaskProperties
v-if="nodeData.type === 'serverTask'"
:nodeData="nodeData"
@@ -56,6 +71,9 @@ import SendTaskProperties from './SendTaskProperties'
import GatewayTaskProperties from './GatewayTaskProperties'
import FormTaskProperties from './FormTaskProperties'
import PolylineProperties from './PolylineProperties'
import SequenceFlowProperties from './SequenceFlowProperties'
import StorInvTaskProperties from './StorInvTaskProperties'
import ExecuteFlowProperties from './ExecuteFlowProperties'
import CommonProperty from './CommonProperty'
import User from './User.vue'
@@ -71,6 +89,9 @@ export default {
FormTaskProperties,
PolylineProperties,
CommonProperty,
SequenceFlowProperties,
StorInvTaskProperties,
ExecuteFlowProperties,
User
},
props: {

View File

@@ -1,25 +1,17 @@
<template>
<div>
<el-form label-width="80px" :model="formData">
<el-form-item label="文案">
<el-input v-model="formData.text"></el-input>
<el-form-item label="id" prop="id">
<el-input v-model="formData.id" disabled></el-input>
</el-form-item>
<el-form-item label="名称">
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="活动区域">
<el-input v-model="formData.region"></el-input>
<el-form-item label="表达式" prop="skipExpression">
<el-input type="textarea" v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item label="活动形式">
<el-input v-model="formData.type"></el-input>
</el-form-item>
<el-form-item label="A">
<el-input v-model="formData.a.a1"></el-input>
<el-input v-model="formData.a.a2"></el-input>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
<el-button @click="testMethod">点击我测试</el-button>
</el-form-item>
</el-form>
</div>
@@ -32,7 +24,7 @@ export default {
lf: Object || String,
},
mounted() {
const { properties, text } = this.$props.nodeData
const {properties, text} = this.$props.nodeData
if (properties) {
this.$data.formData = Object.assign({}, this.$data.formData, properties)
}
@@ -42,25 +34,23 @@ export default {
if (text && text.value) {
this.$data.text = text.value
}
if (!this.formData.id) {
this.formData.id = this.generateUniqueId();
}
},
data () {
data() {
return {
text: '',
formData: {
text: '',
name: '',
region: '',
type: '',
a: {
a1: '',
a2: ''
}
}
id: '',
name: '',
skipExpression: ''
}
}
},
methods: {
onSubmit() {
const { id } = this.$props.nodeData
const {id} = this.$props.nodeData
this.$props.lf.setProperties(id, {
...this.$data.formData
});
@@ -74,8 +64,8 @@ export default {
});
this.$emit('onClose')
},
testMethod(){
console.log(222222)
generateUniqueId() {
return `id_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
}
}

View File

@@ -0,0 +1,74 @@
<template>
<div>
<el-form label-width="80px" :model="formData">
<el-form-item label="id">
<el-input v-model="formData.id" disabled></el-input>
</el-form-item>
<el-form-item label="名称">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="表达式">
<el-input v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: '',
props: {
nodeData: Object,
lf: Object || String,
},
mounted() {
const {properties, text} = this.$props.nodeData
if (properties) {
this.$data.formData = Object.assign({}, this.$data.formData, properties)
}
if (text && text.value) {
this.$data.formData.text = text.value
}
if (text && text.value) {
this.$data.text = text.value
}
if (!this.formData.id) {
this.formData.id = this.generateUniqueId();
}
},
data() {
return {
text: '',
formData: {
id: '',
name: '',
skipExpression: ''
}
}
},
methods: {
onSubmit() {
const {id} = this.$props.nodeData
this.$props.lf.setProperties(id, {
...this.$data.formData
});
console.log(6666, this.$data.formData);
this.$props.lf.updateText(id, this.$data.formData.name);
this.$notify({
title: '保存成功',
message: '请点击上方保存数据按钮,进行持久化!',
type: 'success',
offset: 100
});
this.$emit('onClose')
},
generateUniqueId() {
return `id_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
}
}
</script>
<style scoped>
</style>

View File

@@ -7,14 +7,32 @@
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="节点描述" prop="documentation">
<el-input v-model="formData.documentation"></el-input>
<el-form-item label="任务类型" prop="task_type">
<el-select clearable v-model="formData.task_type" placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in taskTypes"
v-if="item.value !== '3'"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="表单Id" prop="formId">
<el-input v-model="formData.formId"></el-input>
<el-form-item v-if="formData.task_type === '1' || formData.task_type === '2'" label="表达式" prop="skipExpression">
<el-input v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item label="任务类型" prop="taskType">
<el-input v-model="formData.taskType"></el-input>
<el-form-item v-else-if="formData.task_type === '3'" label="表达式" prop="skipExpression">
<el-input type="textarea" v-model="formData.skipExpression"></el-input>
</el-form-item>
<el-form-item v-else-if="formData.task_type === '4'" label="表达式" prop="skipExpression">
<el-select clearable v-model="formData.skipExpression" multiple placeholder="请选择" style="width: 370px;">
<el-option
v-for="item in strategyList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
@@ -23,6 +41,8 @@
</div>
</template>
<script>
import curdActDeModel from "../../act/model/curdActDeModel";
export default {
name: '',
props: {
@@ -43,17 +63,18 @@ export default {
if (!this.formData.id) {
this.formData.id = this.generateUniqueId();
}
this.getTaskTypes()
this.getStrategyList()
},
data() {
return {
text: '',
taskTypes: [],
strategyList: [],
formData: {
id: '',
name: '',
documentation: '',
listener: '',
formId: '',
taskType: ''
task_type: ''
},
rules: {
id: [
@@ -84,6 +105,16 @@ export default {
},
generateUniqueId() {
return `id_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
},
getTaskTypes() {
curdActDeModel.getTaskTypes().then(res => {
this.taskTypes = res
})
},
getStrategyList() {
curdActDeModel.getStrategyList().then(res => {
this.strategyList = res
})
}
}
}

View File

@@ -0,0 +1,96 @@
<template>
<div>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="活动名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动区域">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
</el-col>
</el-form-item>
<el-form-item label="即时配送">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="活动性质">
<el-checkbox-group v-model="form.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊资源">
<el-radio-group v-model="form.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动形式">
<el-input type="textarea" v-model="form.desc"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: '',
props: {
nodeData: Object,
lf: Object || String,
},
mounted() {
const { properties } = this.$props.nodeData
if (properties) {
this.$data.form = Object.assign({}, this.$data.form, properties)
}
},
data() {
return {
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
}
}
},
methods: {
onSubmit() {
console.log('submit!');
// const { id } = this.$props.nodeData
// this.$props.lf.setProperties(id, this.$data.form);
const nodeData = this.$props.nodeData
nodeData.properties = this.$data.form
console.log(nodeData);
this.$props.lf.setNodeData(nodeData);
this.$notify({
title: '保存成功',
message: '请点击上方保存数据按钮,进行持久化!',
type: 'success',
offset: 100
});
this.$emit('onClose')
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,192 @@
<template>
<el-dialog
:visible.sync="logicFlowVisible"
append-to-body
destroy-on-close
:height="'100%'"
title="流程预览"
:width="'100%'"
:before-close="handleClose">
<div class="logic-flow-view">
<!-- 画布 -->
<div id="LF-view2" style="width: 100%; height: 100%;"></div>
</div>
</el-dialog>
</template>
<script>
import LogicFlow from '@logicflow/core'
import '@logicflow/core/dist/style/index.css'
import '@logicflow/extension/lib/style/index.css'
import {
registerStart,
registerEnd,
registerConnect,
registerServerTask,
registerScriptTask,
registerSendTask,
registerFormTask,
registerGatewayTask,
registerstorInvTask,
registerExecuteFlow,
sequence,
} from './registerNode'
//const demoData = require('./data.json')
export default {
components: {},
data() {
return {
logicFlowVisible: false, // 控制流程设计器对话框的可见性
lf: null, // LogicFlow实例
showAddPanel: false,
addPanelStyle: {
top: 0,
left: 0
},
id: null,
initNodes: {"nodes": [], "edges": []},
nodeData: null,
addClickNode: null,
clickNode: null,
dialogVisible: false,
graphData: null,
dataVisible: false,
config: {
background: {
color: '#f7f9ff'
},
grid: {
size: 10,
visible: false
},
keyboard: {
enabled: true
},
style: {
rect: {
radius: 6,
},
edgeText: { // 边文本样式
background: {
fill: '#fff'
}
},
},
edgeTextDraggable: true,
guards: {
beforeClone(data) {
console.log('beforeClone', data)
return true
},
beforeDelete(data) {
// 可以根据data数据判断是否允许删除允许返回true,不允许返回false
// 文档: http://logic-flow.org/guide/basic/keyboard.html#%E5%A6%82%E4%BD%95%E9%98%BB%E6%AD%A2%E5%88%A0%E9%99%A4%E6%88%96%E8%80%85%E6%8B%B7%E8%B4%9D%E8%A1%8C%E4%B8%BA
console.log('beforeDelete', data)
// _this.$message('不允许删除', 'error')
return true
}
}
},
moveData: {},
};
},
methods: {
// 初始化并显示流程设计
showLogicFlowDesigner(row) {
this.logicFlowVisible = true;
this.$nextTick(() => {
this.$_initLf(row)
});
},
$_initLf(row) {
// LogicFlow.use(Menu)
// LogicFlow.use(Snapshot)
const lf = new LogicFlow({container: document.querySelector('#LF-view2'), editable: false,})
this.lf = lf
// 设置主题
lf.setTheme({
circle: {
r: 20,
stroke: '#000000',
outlineColor: '#88f',
strokeWidth: 1
},
rect: {
outlineColor: '#88f',
strokeWidth: 1
},
polygon: {
strokeWidth: 1
},
polyline: {
stroke: '#000000',
hoverStroke: '#000000',
selectedStroke: '#000000',
outlineColor: '#88f',
strokeWidth: 1
},
nodeText: {
color: '#000000'
},
edgeText: {
color: '#000000',
background: {
fill: '#f7f9ff'
}
}
})
this.$_registerNode(row)
},
// 自定义
$_registerNode(row) {
registerStart(this.lf)
registerEnd(this.lf)
registerConnect(this.lf)
registerServerTask(this.lf)
registerScriptTask(this.lf)
registerSendTask(this.lf)
registerFormTask(this.lf)
registerGatewayTask(this.lf)
registerstorInvTask(this.lf)
registerExecuteFlow(this.lf)
this.lf.register(sequence)
this.lf.setDefaultEdgeType("sequenceFlow");
this.$_render(row)
},
/**
*这个是加载中间面板数据
* 其中 demoData中的nodes是节点信息
* edges是连接线信息
*/
$_render(row) {
this.id = row.id
if (!row.model_editor_json) {
this.lf.render(this.initNodes)
} else {
this.lf.render(JSON.parse(row.model_editor_json))
}
},
closeDialog() {
this.$data.dialogVisible = false
},
handleClose() {
this.logicFlowVisible = false;
},
},
};
</script>
<style scoped>
.logic-flow-view {
height: 100vh;
position: relative;
}
#LF-view2 {
outline: none;
margin-left: 1px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -34,6 +34,16 @@ export const nodeList = [
type: 'gatewayTask',
class: 'node-gateway-task'
},
{
text: 'storInvTask',
type: 'storInvTask',
class: 'node-storInv-task'
},
{
text: 'executeFlow',
type: 'executeFlow',
class: 'node-execute-flow'
},
// {
// type: 'user',
// text: '用户',

View File

@@ -14,6 +14,9 @@ import registerScriptTask from './registerScriptTask'
import registerSendTask from './registerSendTask'
import registerFormTask from './registerFormTask'
import registerGatewayTask from './registerGatewayTask'
import registerstorInvTask from './registerstorInvTask'
import sequence from './sequence'
import registerExecuteFlow from './registerExecuteFlow'
export {
registerStart,
@@ -21,12 +24,15 @@ export {
registerEnd,
//registerPush,
//registerDownload,
//registerPolyline,
// registerTask,
///registerPolyline,
// registerTask,
registerConnect,
registerServerTask,
registerScriptTask,
registerSendTask,
registerFormTask,
registerGatewayTask
registerGatewayTask,
registerstorInvTask,
registerExecuteFlow,
sequence
}

View File

@@ -0,0 +1,106 @@
export default function registerExecuteFlow(lf) {
lf.register('executeFlow', ({RectNode, RectNodeModel, h}) => {
class ExecuteFlowNode extends RectNode {
getIconShape() {
const attributes = this.getAttributes();
const {stroke} = attributes;
const iconWidth = 80; // 图标宽度
const iconHeight = 80; // 图标高度
const iconX = attributes.x - iconWidth / 2 + 5; // 调整图标位置的X坐标
const iconY = attributes.y - iconHeight / 2; // 调整图标位置的Y坐标
return h(
'svg',
{
x: iconX,
y: iconY,
width: iconWidth,
height: iconHeight,
viewBox: '0 0 1126 1024'
},
h(
'path',
{
fill: stroke,
d: 'M196.56 0c-212.096 0-212.096 1024 0 1024 160.896 0 789.952-343.744 789.952-512S350.16 0 196.56 0zM818.32 555.904c-109.696 109.696-373.056 256-533.952 321.856a54.144 54.144 0 0 1-73.152-43.904 1589.12 1589.12 0 0 1 0-643.648 58.752 58.752 0 0 1 73.152-43.904A2253.184 2253.184 0 0 1 818.32 468.16a54.848 54.848 0 0 1 0 87.744z',
}
)
);
}
getShape() {
const attributes = this.getAttributes();
const {width, height, x, y, radius} = attributes;
const points = [
[x - width / 2, y],
[x + width / 2, y],
[x, y - height / 2],
[x, y - height / 2]
];
const pointsPath = points.map(point => point.join(',')).join('');
return h(
'g',
{
// transform
},
[
h('rect', {
x: x - width / 2,
y: y - height / 2,
rx: 5 ,
ry: 5,
width,
height,
fill: 'none', // 填充颜色
stroke: 'black', // 边框颜色
strokeWidth: 1, // 边框宽度
strokeOpacity: 1, // 边框透明度
fillOpacity: 0.5, // 填充透明度
points: pointsPath,
}),
this.getIconShape(),
]
);
}
}
class ExecuteFlowModel extends RectNodeModel {
constructor(data, graphModel) {
data.text = {
value: (data.text && data.text.value) || '',
x: data.x,
y: data.y + 50
};
super(data, graphModel);
this.menu = [
{
className: 'lf-menu-delete',
text: 'delete',
callback(node) {
lf.deleteNode(node.id);
},
},
{
text: 'edit',
className: 'lf-menu-item',
callback(node) {
lf.editNodeText(node.id);
},
},
{
text: 'copy',
className: 'lf-menu-item',
callback(node) {
lf.cloneNode(node.id);
},
},
];
}
}
return {
type: 'executeFlow',
view: ExecuteFlowNode,
model: ExecuteFlowModel,
};
});
}

View File

@@ -0,0 +1,106 @@
export default function registerUser(lf) {
lf.register('storInvTask', ({RectNode, RectNodeModel, h}) => {
class Node extends RectNode {
getIconShape() {
const attributes = this.getAttributes();
const {stroke} = attributes;
const iconWidth = 80; // 图标宽度
const iconHeight = 80; // 图标高度
const iconX = attributes.x - iconWidth / 2 ; // 调整图标位置的X坐标
const iconY = attributes.y - iconHeight / 2; // 调整图标位置的Y坐标
return h(
'svg',
{
x: iconX,
y: iconY,
width: iconWidth,
height: iconHeight,
viewBox: '0 0 1126 1024'
},
h(
'path',
{
fill: stroke,
d: 'M913.660512 443.297039L474.753353 70.480459 35.846194 443.297039l-35.549944-40.397665L474.753353-0.026932l474.457104 403.007101zM190.515386 551.481984H136.193993v-258.545053h54.321393v258.545053z m633.13913 0h-54.321393v-258.545053h54.321393v258.545053zM507.313871 962.083846h-149.821472v-53.297985h149.821472v53.297985z m309.44611 0h-133.904792v-53.297985h79.583399V570.549682H84.835095v338.236179h91.945085v53.297985h-146.239546V517.224765h786.219347v444.859081z m-546.71506 61.943086a121.354584 121.354584 0 1 1 123.616854-121.192994 122.620378 122.620378 0 0 1-123.643785 121.112198z m0-189.330388A68.029667 68.029667 0 1 0 339.340382 902.537689a68.729893 68.729893 0 0 0-69.322392-67.92194z m324.096997 189.330388a121.354584 121.354584 0 1 1 123.616853-121.192994 122.620378 122.620378 0 0 1-123.643785 121.112198z m0-189.330388a68.029667 68.029667 0 1 0 69.29546 67.841145 68.729893 68.729893 0 0 0-69.322392-67.92194z m416.688443 189.330388a121.354584 121.354584 0 1 1 123.616854-121.192994 122.620378 122.620378 0 0 1-123.643785 121.112198z m0-189.330388a68.029667 68.029667 0 1 0 69.295461 67.841145 68.729893 68.729893 0 0 0-69.322392-67.92194z m254.828468 96.631214h-135.816948v-53.405713h81.468623v-106.622902h-108.615854V584.742728h-325.874493v-53.324917H1156.989112v186.583346h108.642785v213.218874z m-380.222818 0h-108.642786v-53.405713h108.642786v53.297986z m-172.040188-469.340067h-54.321392v-156.042712h54.321392v156.042712z m-88.309294 1.346589h-130.349798V304.652254h130.349798v158.73589z m-76.001473-53.297985h21.707012v-52.112987h-21.733944v52.112987z m-93.668718 51.978328h-54.348325v-156.069644h54.321393v156.042712z m-88.309295 1.346589H236.703382V304.652254h130.349798v158.73589z m-76.028404-53.297985h21.707011v-52.139919h-21.760875v52.112987z',
}
)
);
}
getShape() {
const attributes = this.getAttributes();
const {width, height, x, y, radius} = attributes;
const points = [
[x - width / 2, y],
[x + width / 2, y],
[x, y - height / 2],
[x, y - height / 2]
];
const pointsPath = points.map(point => point.join(',')).join('');
return h(
'g',
{
// transform
},
[
h('rect', {
x: x - width / 2,
y: y - height / 2,
rx: 5 ,
ry: 5,
width,
height,
fill: 'none', // 填充颜色
stroke: 'black', // 边框颜色
strokeWidth: 1, // 边框宽度
strokeOpacity: 1, // 边框透明度
fillOpacity: 0.5, // 填充透明度
points: pointsPath,
}),
this.getIconShape(),
]
);
}
}
class Model extends RectNodeModel {
constructor(data, graphModel) {
data.text = {
value: (data.text && data.text.value) || '',
x: data.x,
y: data.y + 50
};
super(data, graphModel);
this.menu = [
{
className: 'lf-menu-delete',
text: 'delete',
callback(node) {
lf.deleteNode(node.id);
},
},
{
text: 'edit',
className: 'lf-menu-item',
callback(node) {
lf.editNodeText(node.id);
},
},
{
text: 'copy',
className: 'lf-menu-item',
callback(node) {
lf.cloneNode(node.id);
},
},
];
}
}
return {
type: 'storInvTask',
view: Node,
model: Model,
};
});
}

View File

@@ -0,0 +1,40 @@
import { PolylineEdge, PolylineEdgeModel } from "@logicflow/core";
class SequenceModel extends PolylineEdgeModel {
setAttributes() {
this.offset = 20;
}
getAnimation() {
const animation = super.getAnimation();
animation.stroke = "blue";
return animation;
}
getEdgeStyle() {
const style = super.getEdgeStyle();
const { properties } = this;
if (properties.isActived) {
style.strokeDasharray = "4 4";
}
style.stroke = "orange";
return style;
}
getTextStyle() {
const style = super.getTextStyle();
style.color = "#3451F1";
style.fontSize = 30;
style.background.fill = "#F2F131";
return style;
}
getOutlineStyle() {
const style = super.getOutlineStyle();
style.stroke = "red";
style.hover.stroke = "red";
return style;
}
}
export default {
type: "sequenceFlow",
view: PolylineEdge,
model: SequenceModel
};