企业级⾃定义表单引擎解决⽅案(⼆)--架构及核⼼模块设计
先总体介绍⼀下⼤概的架构和核⼼模块设计。先上⼀张整体设计图
概念还是有点多,有⼀些概念可能⽐较新,如果熟悉K2⾃定义表单,可能⽐较好理解⼀些。代码地址:gitee/kuangqifu/sprite,或者QQ交流:523477776 对核⼼的⼀些功能模块进⾏总体介绍如下(
⽤ core实现,其他语⾔整体设计思路相差不⼤)
基础设施:
⾃定义表单主要涉及到数据存储,包括表单定义信息和真实的业务表存储管理,可⽀持不同的数据库存储,Redis主要⽤在缓存更新通知上,Redis不存储表单定义缓存
基础组件:
表单基础框架, core实现,⽤Dapper做ORM存储,封装了UnitOfWork,另外还包括了模块管理、租户/应⽤管理等基础功能,不包括权限相关功能。
表单定义本地缓存:
表单定义信息对于⾃定义表单来说,访问特别的频繁,真实业务变更极少,需要不少的过滤查询,如果存储到Redis,涉及到频繁的访问以及数据过滤,对整体性能影响也⽐较⼤,所以这⾥考虑把表单定义信息存储到每⼀个应⽤程序内存中,直接从内存中访问表单定义信息,表单定义信息改变时,通知所有应⽤表单定义对应的数据已经更新,应⽤程序读取数据时,会从数据库读取最新的数据存储到内存中。表单定义信息还会存储到浏览器Indexdb中,⼀条总的原则就是访问⾃定义表单定义信息⼀定要快,就近获取。
基础数据本地缓存:
数据字典(⽤户信息)也可以存储到本地缓存,管理⽅式同表单定义本地缓存,数据字典变更极少,访问⼤;业务表往往只存储⽤户Id,展⽰需要⽤户名称,所以也存储到本地缓存中。
缓存变更通知:
修改了表单定义信息或者数据字典等,通过Redis通知所有应⽤程序清空本地缓存,再次读取数据时,应⽤程序从数据库或者接⼝读取数据再填充到内存中。如果检测到Redis断开连接,则直接从数据库或者接⼝读取数据,待Redis恢复,再从内存读取数据。Redis可由其他有发布订阅中间件服务替换。
CurrentUser:
只提供接⼝定义,对接具体的框架实现具体的逻辑,⽐如框架使⽤Abp框架,则从Abp的ICurrentUser读取⽤户当前⽤户信息。
微服务调⽤组件:
暂时未迁移,见作者其他博客描述。
租户/应⽤配置管理:
对⾃定义表单数据在租户和应⽤级别进⾏隔离,以⽀持Saas服务。
Sprite Comon:
⾃定义表单公共组件/模块
动态Sql:
⾃定义表单⽐较核⼼的内容之⼀,所有对业务表的常规CRUD,都是通过动态拼接Sql语句完成以及动态参数,这⾥⾯涉及到⼤量的JObject操作,也就是开发者⽤得⽐较多的Newtonsoft.Json组件部分内容。
动态查询条件:
对Sql的参数查询,查询条件定义为⼀棵查询树,然后根据树完成Sql查询条件Where⼦句的字符串拼接。表单设计器怎么做
动态表达式:
也是⼀棵树,每⼀个节点为⼀种函数或者取值,⽐如逻辑表达式、⽇期转换函数、从⽅法获取值、固定值等,根据根节点类型返回对应动态值
表单规则:
⾃定义表单灵魂所在,有了表单规则定义,才能称之为表单引擎,可定义视图或者表单规则;
表单规则事件:
⽐如⽤户列表视图新增按钮点击事件,部门树⽤户列表表单部门树视图树节点选中节点变化事件,⽤户列表视图弹出对话框保存事件等,可以是视图/表单本⾝或者控件触发,也可以是⼦表单/⼦视图本⾝或者控件触发
表单规则执⾏:
当某⼀个规则定义的事件被触发,可定义执⾏⼀系列执⾏动作,⽐如"⽤户列表视图新增按钮点击事件"触发时,定义执⾏设置⽤户列表选中部门参数、获取⽤户列表查询参数定义、执⾏后端获取⽤户分页数据⽅法、将执⾏结果传递给⽤户列表等⼀系列动作。再⽐如"⽤户列表视图弹出对话框保存事件"事件触发,验证⽤户Item视图、验证通过
定义时和运⾏时验证:
⾃定义表单不需要写代码,则验证就显得⾮常的重要了,定义时各个模型之前数据是否正确,规则定义是否正确,运⾏时参数等是否正确等
序列化:
表单定义存储往往是结构化的数据,很多定义信息可能以字符串的⽅式存储,但JS前端往往需要Json数据,则需要进⾏序列化与反序列化操作。
Sprite Object:
⾃定义表单对象管理,包括对象、属性、⽅法
Object管理:
Object管理与业务表需要完全同步,添加Object时,需要动态⽣成业务表的创建Sql语句,并在业务库中创建具体业务表,业务表名称与Object的Name字段对应,动态Sql是根据Object定义信息拼接Sql语句并在真实业务库中执⾏Sql语句。
Property管理:
Object定义表,Property定义字段,⾃定义表单定义⼀些审计相关的字段并进⾏维护,包括Creator,CreationTime,IsDeleted等
Method管理:
定义⽅法,可以是执⾏Sql语句、调⽤微服务、反射调⽤,并包括⽅法能够成功执⾏的附加信息定义,并对执⾏参数进⾏验证,对业务表常规的操作已经定义到了⾃定义表单中,⽐如Create,Update,Get,List,PageList,TreeList等,不需要格外定义⽅法
业务表管理:
对Object和Property的管理,同步更新业务表表结构,他们之间需要完全的对应。
Sprite View and Form:
视图管理:
⾃定义表单最⼩功能单元定义,⽐如⽤户Item,⽤户列表视图,部门树视图等,抽离出Item视图、列表视图、树视图等各个单元视图。
表单管理:
⾃定义表单视图容器,表单不处理任何具体业务,只是将各种视图聚合起来统⼀管理,可以对视图进⾏布局,可以定义规则在视图与视图之间传递数据等。
视图/表单控件:
统⼀定义不同视图/表单固定区域的控件,⽐如列表视图查询区域控件,列表功能控件,新增,刷新,批量删除等,或者列表⾏控件等,再或者表单流程相关控制按钮
视图/表单Wrap管理:
视图或者表单只定义⾃⾝需要的功能,但⽤到哪些地⽅⾃⾝是不知道的,⽐如⽤户Item视图放⼊⽤户列表弹出框中,部门树表单⽤Card布局等
视图/表单⾏列管理:
按照Grid布局,定义常规的⾏列布局管理
⼦视图/⼦表单:
表单列或者视图列的内容可以是⼦表单或者⼦视图,运⾏时当发现是⼦视图或者⼦表单,则动态再加载配置的视图或者表单。
视图/表单版本管理:
视图或者表单本⾝或者任何关联数据改变,都会重新⽣成版本号,并通知所有应⽤对应缓存变更并删除
应⽤本地缓存,浏览器每请求⼀个页⾯,发现视图或者表单版本号改变了也会更新浏览器本地存储数据。
视图/表单规则管理:
视图和表单都可以定义⾃⾝规则,规则见上⽂描述。
宿主框架:
计划将⾃定义表单宿主到Abp Vnext框架中,Abp框架负责登录认证,⽤户⾓⾊管理,菜单操作权限管理等,⾃定义表单公开Api供使⽤端调⽤,当然,使⽤其他框架做为宿主也是⼀样的。另外,⼯作流引擎这块,之前是⽤WWF研发的⼀套产品,但是微软没有计划将其迁移到 core,基本就宣告了死刑,所以之前的⽂章也就停⽌了;流程引擎这块后续是会重新编写,流程引擎+表单引擎,这块⾃定义表单最终的形态,不过不都是后话了,⾃定义表单完全可以独⽴存在。
前端(个⼈是做后端的,前端⽔平有限):
前端的复杂程度不亚于后端,很多东西是需要配合后端⼀起定义的,前端+后端,才能形成⼀个整体。
前端可以是不同的架构,不同的应⽤,可以是浏览器,winform等,都是调⽤Api,这⾥选择的是浏览器,技术选择的是vue,框架选择的是and design for vue Ant Design for Vue:
使⽤此框架,可替换其他框架,但各个控件需要做相应的修改。
视图:
定义视图Layout、Item、列表、Tree等视图。
表单:
定义普通表单、Div表单等
Wrap管理:
对视图或表单进⾏包装,包括Div、对话框、Card布局等各种包装。
视图/表单控件:
对前端各种控件进⾏⼆次封装,注⼊规则,允许触发事件和执⾏规则。
浏览器数据缓存:
⽐较核⼼的内容,⾃定义表单内容设计变更,需要即使的通知前端,同是⾃定义表单定义信息访问⼜必
须快速,不能有明显的性能损失。IndexedDb存储视图/表单定义等信息,每次打开⼀个页⾯时,遍历所有关联的视图和表单Id和版本信息,与后端缓存数据进⾏⽐较,不同则更新本地缓存。
表单规则注册与执⾏:
前端灵魂所在,视图、表单、控件在创建的时候,都会注⼊规则,⽤户进⾏某个操作时,如果有对应的事件定义,则到规则定义,进⽽到⼀系列视图/表单/空间执⾏⼀系列规定。
动态表达式:
为⼀棵树,同后端动态表达式⽐较类似。
⾃定义功能:
⾃定义表单也不可能抽象出所有的数据模型,特殊的业务可编写代码,完全⾃定义功能实现。后端⼀些报表或者某些业务模块,开发⼈员⾃⼰写业务逻辑,通过微服务或者反射配置⽅法,执⾏具体的⾃定义功能。前端则可编写不同的⾃定义控件,并注册到Vue框架中,⾃定义表单在某个功能上配置⾃定义控件名称即可。
前端技术选型不要选择angular,angular的动态控件⽐较死板,动态控件不能动态添加指令,还有其他很多限制,基本上断了⾃定义表单的路了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论