V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhuizhuidea
V2EX  ›  前端开发

一个低代码拖拉拽的表单编辑器,开源咯!

  •  1
     
  •   zhuizhuidea · 2023-04-25 13:49:04 +08:00 · 1193 次点击
    这是一个创建于 579 天前的主题,其中的信息可能已经有所发展或是发生改变。

    编辑器介绍

    先来个图,有个初步的认识

    抱歉,原谅图有点模糊哈

    github: https://github.com/Liberty-liu/Everright-formEditor

    demo: https://everright.site/zh-cn/module/formEditor/introduction.html

    Everright-formEditor是一个基于 vue3 的可视化编辑器,依赖于element-plusvant进行开发。内部提供了适配器进行参数转码。

    1. 灵活的拖放功能(通过拖拽便可决定一个字段插入行还是列,无需布局容器)
    2. 提供多种字段(单行文本、邮箱、身份证号、手机号、网址、多行文本、数字、单选框、多选框、时间、日期、评分、开关、滑块、Html 编辑器、级联、上传文件、签名、省市区)
    3. 布局字段(栅格布局、表格布局、标签页、折叠面板、分割线)
    4. 内置了国际化(中文和英文)
    5. 内置两种模式:字段与布局不分离、字段与布局分离
    6. 编辑器、预览器和配置面板都可以单独使用,可以根据实际需求选择性单独使用配置面板,满足不同场景下的需求

    多图预警!!!多图预警!!!多图预警!!!多图预警!!!多图预警!!!多图预警!!!

    编辑器界面

    预览器 pc 界面

    预览器 mobile 界面

    属性面板界面

    内部实现原理

    Field

    Field作为元素之一

    在一个 form 编辑器里边,主要操作的是一个元素,布局容器(也是元素之一)则是作为Field的承载。用下图表示一个FieldField自身会有很多的属性。

    注意右上角的的白色图案,表示这个Field内部属性由两个管道的输入来共同决定。

    1. 来自canvas 面板canvas 面板下面的选区(Selection)
    2. 来自属性面板配置属性

    Field经过用户的 click 或者拖拉拽的方式塞入Canvas 画板

    Canvas

    用下图表示一个Canvas 画板

    Canvas 画板内部的数据用一个二维数组表示Array[r][c],设 r 为行,c 为列,是不是有了一点 table 的味道了,事实上如 table 一样的,内部可以无限嵌套的(布局容器是可以嵌套)。

    当一个元素被插入Canvas 画板元素会自动被 选区(Selection) 包裹。

    选区(Selection)

    用下图表示一个选区(Selection)

    图中白色区域表示slot,元素被放置在这个地方。

    选区(Selection) 提供是否可以被拖拽、删除、复制、调整大小、选中父级的功能。

    当选中元素时,会在Canvas 面板上被高亮显示。

    Config 面板

    用下图表示一个Config 面板

    用于配置字段属性。

    当选中元素时,Config 面板会显示被选中元素的自身的全部属性

    数据流动图

    结合以上示意图,将用户的行为用下图示意

    • 实线箭头代表用户的操作
    • 带圆点的实线箭头代表自动发生的事件
    • 虚线箭头表示数据流动

    再加一段文字描述方便理解

    1. 当用户通过 click 或者拖拉拽的方式将一个元素拖入到画板当中,编辑器会自动为该元素包裹一个选区(Selection)
    2. 当用户选中选区的时候,Config 面板会显示被选中元素的自身的全部属性
    3. 用户通过Config 面板或者选区(Selection) 修改元素属性的时候,数据会同步到Canvas 画板,实现所见即所得

    适配器(Adapter)

    用下图表示一个适配器(Adapter)

    由于 pc 依赖 element-plus ,mobile 依赖 vant ,它们之间交集部分的功能参数有些是不一样的,适配器(Adapter) 就是做这个体力活的。

    举个栗子

    Rate 评分这个组件想设置一下星星⭐️的数量,在element-plus 参数是 max,而在vant是 count 。

    下面插入一点点代码示意一下适配器所做的事情

    if (!isPc) {
      result.count = options.max
    } else {
      result.max = options.max
    }
    

    编辑器的两种模式

    再回顾一下在编辑器内部流动的主要数据是元素元素分为字段布局容器

    编辑器内部的真实数据是一个tree

    默认情况下,编辑器是采用布局字段不分离的模式,当然,也支持布局和字段分离的模式。

    • layoutType1 布局和字段不分离

      在 PC 端设计表单,会自适应 mobile 端。

    • layoutType2 布局和字段分离

      在 PC 端设计表单时,例如将一个字段为 email 的字段放入到 tabs 容器中,切换到 mobile 端,不会同步 tabs 容器的,此时如果在 mobile 新建一个 Collapse 容器,将 email 字段放入其中,切换到 pc 端,是不会同步 Collapse 容器的,对于在一端新增的字段,切换到另一端,会进行两个集合运算,新增的字段会 push 到画板底部,删除的字段会在布局结构体中删除掉。字段自身的所有属性是同步的。

    以上无论哪种模式,导出的数据都会把Field抽离出来的,与后端而言,他们更关心的是字段而非是一个 tree 。

    拖拽逻辑

    依赖sortablejs来实现的,但是用sortablejs想做到插入行或者列是不支持的。插入行的时候再包裹一个 inline 容器(元素插入一行会自动包裹一个 inline 虚拟容器),当行内唯一元素被移动走,又得删除 inline 容器,简而言之就是当拖拽一个元素,如果插入行就会包裹一个 inline 容器,如果插入列就插入到 inline 容器下边。 因此写了一个 sortablejs 的插件拦截了 dragOver 和 drop 事件来实现的。

    当拖拽的时候会一直触发 dragOver 事件,根据当前鼠标的 x/y 判断在 target 元素的四个方向决定是插入行还是列,判断四个方向是根据斜率计算的,贴一张图比较容易理解。挡 drop 的时候记录最后一次 dragOver 的元素和实例来实现的。

    开发环境下有一个 node 的服务

    在开发环境下内置了一个后端服务,基于 node 写的,数据库是 SQLite (只需要生成一个数据库文件就好,无需常规数据库搭环境那么复杂,微信 App 的聊天记录就是用这个数据库存储的) ,一个编辑器最终是要提交到数据库中的,所以有一个 crud 方便开发。

    现有功能缺陷

    1. 历史记录
    2. 将 tree 结构界面体现出来(内部的数据有了)
    3. GUI 方式控制字段显示与隐藏以及逻辑校验

    以上功能接下来开发完成

    低代码说白了就是一个堆功能的东西,全部都有了也就才能实现低代码

    4 条回复    2024-05-04 15:06:34 +08:00
    coolair
        1
    coolair  
       2023-04-25 13:57:53 +08:00
    没有动态行的子表单吗?
    zhuizhuidea
        2
    zhuizhuidea  
    OP
       2023-04-25 13:59:15 +08:00
    @coolair 目前没有做了,现在再做一个可视化控制字段校验和显隐,开发完这个会去开发子表单吧
    yuxu952
        3
    yuxu952  
       204 天前
    可以实现根据响应的字段,进行映射在页面自动展示列表吗
    yuxu952
        4
    yuxu952  
       204 天前
    逻辑控制那块,好多 bug 啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   908 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 22:06 · PVG 06:06 · LAX 14:06 · JFK 17:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.