xflow流程可视化-designable高级配置
【xflow流程可视化-designable高级配置】上篇简要介绍了formilyjs以及基于其构建了表单设计器,实现了表单动态设计已经预览功能,本片将介绍表单设计器的一些高级配置,使其能更好的运用于我们的节点编辑以及连线编辑。
designable高级配置
请求及自定义数据注入
一般来说,我们页面的请求都是统一封装好的,在使用时我们如何把我们封装好的请求或者已经有的数据源注入到我们的
表单设计器中呢:
SchemaField 组件是专门用于解析JSON-Schema动态渲染表单的组件,在使用createSchemaField
时我们可以传入scope
来注入到全局作用域中链接:
import { FC, Ref, useEffect, useImperativeHandle, useState } from 'react';
import { Modal } from 'antd';
import {
FormItem,
Input,
Form,
Submit,
ArrayBase,
ArrayCards,
ArrayCollapse,
ArrayItems,
ArrayTable,
ArrayTabs,
BaseItem,
Cascader,
Checkbox,
DatePicker,
Editable,
FormButtonGroup,
FormCollapse,
FormGrid,
FormTab,
GridColumn,
NumberPicker,
Password,
PreviewText,
Radio,
Reset,
Select,
SelectTable,
Space,
Switch,
TimePicker,
Transfer,
TreeSelect,
Upload,
} from '@formily/antd';
import api from '@/api';
import { createSchemaField } from '@formily/react';
import { LgetItem } from '@/utils/storage';
import { createForm } from '@formily/core';
interface PreviewProps {
previewRef: Ref<{ setVisible: (flag: boolean) => void }>;
modalConfig: { [key: string]: any };
}const SchemaField = createSchemaField({
components: {
Input,
ArrayBase,
ArrayCards,
ArrayCollapse,
ArrayItems,
ArrayTable,
ArrayTabs,
BaseItem,
Cascader,
Checkbox,
DatePicker,
Editable,
Form,
FormButtonGroup,
FormCollapse,
FormGrid,
FormItem,
FormTab,
GridColumn,
NumberPicker,
Password,
PreviewText,
Radio,
Reset,
Select,
SelectTable,
Space,
Submit,
Switch,
TimePicker,
Transfer,
TreeSelect,
Upload,
},
scope: {
$fetch: api,
selectList: [{ label: 'aaa', value: 'aaa' }, { label: 'bbb', value: 'bbb' }]
}
});
const Preview: FC = ({ previewRef, modalConfig }) => {
const [visible, setVisible] = useState(false);
useImperativeHandle(previewRef, () => ({
setVisible,
}));
const [params, setParams] = useState({});
const normalForm = createForm({});
useEffect(() => {
if (modalConfig && visible) {
const playgroundList = LgetItem('playgroundList') || [];
const data = https://www.it610.com/article/playgroundList.find((s) => s.id === modalConfig.id);
setParams(data?.params || {});
}
}, [modalConfig, visible]);
const handleCancel = () => {
setVisible(false);
};
return (
);
};
export default Preview;
在使用表单设计器时,便可以使用注入的
scope
值,比如我们准备一个json,选择一个下拉控件,配置相应器,然后通过我们注入的请求获取这个json,展示对应的下拉值: $effect(() => {
$self.loading = true
$fetch({
url: '/getSelectList',
method: 'get',
params: {}
}).then(res => {
$self.loading = false
// 当返回值不是label和value时转化一下
$self.dataSource = res.map(s => ({ label: res.name, value: res.id }))
}).catch(() => {
$self.loading = false
})
}, [])
这里的
$fetch
就是我们注入的请求了表单配置
- form提交的key为字段标识,可自定义修改,默认为随机字符串
- 标题为form表单的label
- 支持自定义搜索的,比如select,需要在组件属性下筛选器中配置表单式,才能支持label搜索
(inputValue, option) => { return option.label.indexOf(inputValue) !== -1; }
文章图片
- 如果配置了响应器规则中和外部一样的配置,比如组件属性,那么响应器规则中的会覆盖外部的配置(外部的组件属性失效)
$self
为当前选中的表单对象$form
为form对象$deps
为依赖对象(需在上方依赖字段配置来源字段)$observable
声明一个可观察对象$effect
和react的useEffect
使用类似$values
为提交的form表单对象
- 动态枚举值,假如我们有一个select控件,这个控件的值是接口返回的
$effect(() => { $self.loading = true $fetch({ url: '/getSelectList', method: 'get', params: {} }).then(res => { $self.loading = false // 当返回值不是label和value时转化一下 $self.dataSource = res.map(s => ({ label: res.name, value: res.id })) }).catch(() => { $self.loading = false }) }, [])
- 联动变化枚举值,比如我们有两个select,第一个select是
mechanism
机构,第一个select是user
人员,我们选择一个机构后,第二个select会根据第一个select的值来从接口中获取机构下的人员列表,这是一个比较常见的联动选择功能,那么放在表单设计器里面我们该如何实现呢(实现方式不唯一,这里提供思路)。
// 第一个select,我们监听mechanism的变化,flag主要应用为跳过初次渲染(保证反显正常展示),当mechanism改版(即手动选值)后,清空user的取值。 $effect(() => { $self.loading = true $fetch({ url: '/getMechanismList', method: 'get', params: {} }).then(res => { $self.loading = false // 当返回值不是label和value时转化一下 $self.dataSource = res.map(s => ({ label: res.name, value: res.id })) }).catch(() => { $self.loading = false }) }, []) const state = $observable({ flag: false }); $effect(() => { if (state.flag) { $form.reset('user'); } state.flag = true; }, [$self.value])
当mechanism
变化时,清空user
列表,发起请求获取user
列表
$effect(() => { $self.dataSource = [] if ($deps.mechanism) { $self.loading = true $fetch({ url: '/getSelectList', method: 'get', params: { mechanism: $deps.mechanism } }).then(res => { $self.loading = false // 当返回值不是label和value时转化一下 $self.dataSource = res.map(s => ({ label: res.name, value: res.id })) }).catch(() => { $self.loading = false }) } }, [$deps.mechanism])
// mock/api.ts
export default {
'GET /api/mechanism': [
{
value: '1',
label: '机构1',
},
{
value: '2',
label: '机构2',
},
],
'GET /api/users': (req, res) => {
// 添加跨域请求头
const query: any = req.query;
const user: any = {
'1': [
{
value: '1-1',
label: '机构1-人员1',
},
{
value: '1-2',
label: '机构1-人员2',
},
],
'2': [
{
value: '2-1',
label: '机构2-人员1',
},
{
value: '2-2',
label: '机构2-人员2',
},
],
};
res.send(user[query.id]);
},
};
我们定义了两mock接口,
mechanism
和users
,前者返回一个机构列表,后者根据前者的id返回对应的列表,接着我们在上一期中的预览弹窗中注入请求,这里我们直接使用umi提供的request
。// Preview.tsx
import { request } from 'umi';
...const SchemaField = createSchemaField({
components: ...,
scope: {
$fetch: request,
},
});
最后我们在表单设计中添加请求
// mechanism
$effect(() => {
$self.loading = true
$fetch("/api/mechanism", {})
.then((res) => {
$self.loading = false
// 当返回值不是label和value时转化一下
$self.dataSource = res
})
.catch(() => {
$self.loading = false
})
}, [])// users
$effect(() => {
$self.dataSource = []
if ($deps.mechanism) {
$self.loading = true
$fetch("/api/users", {
params: {
id: $deps.mechanism,
},
})
.then((res) => {
$self.loading = false
// 当返回值不是label和value时转化一下
$self.dataSource = res
})
.catch(() => {
$self.loading = false
})
}
}, [$deps.mechanism])
文章图片
文章图片
文章图片
最后再到表单模板预览一下:
文章图片
好了,本篇介绍的功能都实现了,那么下一篇我们将把流程可是化的编辑功能和我们的表单模板进行关联起来,修改表单模板就能修改节点或连线的属性编辑,达到真正的动态属性编辑效果,尽情期待。
本文地址:链接
本文github地址:链接
github demo地址:链接
推荐阅读
- 推荐一个数据可视化大屏幕报表开源系统
- node中child_process的回调执行流程的源码分析
- 如何可视化编写和编排你的|如何可视化编写和编排你的 K8s 任务
- FDTD学习笔记|Lumerical Python API学习(七)——可视化几何
- 【Netty】七、服务端读取数据流程 - 源码解读
- win10系统VS2019配置点云库PCL1.12.1的详细流程
- hdfs的读写流程分析总结
- C++基于boost|C++基于boost asio实现sync tcp server通信流程详解
- 简单又免费的地图可视化工具终于被我发现啦!
- 8.2、SpringBoot启动流程--把spring应用跑起来(接8.1)