如何设计一款营销低代码可视化海报平台

5,772 阅读11分钟

本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

写在开头

近两年来,低代码的概念频繁的出现在互联网领域,可谓是遍地开花。有人说它是一把利刃,极大了提升了产研效能;有人说它是行业的毒瘤,是在反复炒冷饭。

每个人对于低代码都有自己的看法,无论是好是坏,存在即合理。

背景

我是从去年来到新公司后才第一次近距离的接触到低代码的概念,部门负责的是营销业务,每天都有很多的营销活动,随之而来的就是大量的H5海报页面。而这些H5页面都是由许多张图片拼接而成,在之前这些图片都是全部由UED切图完成的,这样就给他们带来了大量的重复工作。

面对这样一个困境,我们也在思考:能否通过技术手段去解放UED同学的劳动力呢?通常的海报需求都是由运营同学提供给UED的,而且大部分海报组成相对都比较简单:图片、文字、按钮。在这种情况下,我们完全可以做一个营销海报合成平台,运营同学可以直接通过简单的拖拽方式就是快速的制作需要的图片素材,完全可以称得上是天马行空,而且UED同学几乎不用参与。

这样的海报搭建平台其实社区也蛮多,我们是自己从0到1、从前到后的实现了一套完整的内部海报搭建平台。出发点有两个:

1、完全自主开发,不受限于平台,后期扩展维护方便

2、形成公司内部的一套系统,可推广到其他部门,缩减类似场景的人力成本

经过了三个月左右的开发和打磨,这个海报搭建平台顺利上线了:

image.png

image.png

上线后差不多节省了UED90%以上的工作量。

上面短短的几句话概括了乔巴乐高诞生的背景和最终的成果,这中间的过程其实并没有那么一帆风顺。虽然相较颗粒度在组件维度的常规低代码平台,乔巴乐高的复杂度低了很多,但无论是脚手架、编辑器、组件库、持续集成,他都应有尽有。

这其实也是蛮符合写这个专栏我的初衷的:从零带大家深入了解大厂真实的低代码平台。更多的去关注整个构建流程(这个项目从前端到服务端包括运维相关,全部是由我们前端自己完成的),而不是局限在某个具体的业务细节的实现上。换而言之,站在更高的视角去看一个完整的项目。

项目架构

首先,我们梳理下需求,站在产品角度,整体的看下用户(这里主要是运营或产品同学)使用编辑器创建活动的流程:

低代码06.png

从上面的使用流程图上,我们提取几个关键词:组件模板可视化搭建系统发布

通过以上几个关键词,我们把关注点放在:

  • 一共需要多少个子项目
  • 数据流转关系

模块设计

首先肯定需要一个可视化编辑器,编辑器主要是以活动为单位进行流转:包括活动的创建、编辑、预览、审核、下线、发布。当然上面流程中的预设模板和组件肯定也要考虑在内。

然后活动搭建完,运营需要去投放,投放侧肯定是H5了,那么对应就要有一个项目来负责对已搭建活动的渲染。渲染端是对客端,也就是投放出去的海报页面,用户可以直接看到的。这部分主要是负责对页面的渲染和对应的组件加载、调度。

到这里其实已经可以满足我们最基础的需求了。但这里还有一个不得不提的:组件库。

上面两个比较好理解,那为什么需要组件库呢?组件库核心作用在于复用,我们知道上图中间的画布区域、预览区域以及最终渲染端其实展示都是一样的,这种场景下怎样实现最大程度的复用呢?这个时候就要依附于组件库的能力了。

组件库侧会积累编辑器中经常用到的一些基础组件,像我们这里主要就是文字、图片和素材了,文字和图片比较好理解。素材以形状为主。

聊到这里,我们已经确定了打底的三个项目:

  1. 编辑器
  2. 渲染端
  3. 组件库

细化一下需求:编辑器需要一个前端(choba-lego)和服务端(choba-lego-server);渲染端直接用服务端渲染就行,所以只需要一个项目:choba-h5;组件库其实除了自身外(choba-lego-components)还需要一个对应的组件平台(choba-component-platform),用于快速的创建和发布组件。

数据结构及其流转关系

接下来就是要来聊一下数据的流转关系了,在我看来这也是一个系统设计底层很重要的支撑。

我们先来用一张图来了解下上面提到的几个项目的大致关系吧:

image.png

从图中也不难看出,主流程为:创建作品 > 保存作品 > 发布作品 > 浏览作品。那么归根到底数据的流转关系的核心在于作品本身的数据结构该如何设计。

我们结合编辑器来看下:

image.png

古有“数据驱动视图”,今天我们就结合编辑器视图页面来反推数据。这里思考几个问题:

  • 组件Schema应该怎么设计?
  • 组件的数据如何去维护?

每个组件都是单一的个体,画布区域又是由很多个组件组合而成的,很容易想到要维护一个组件数组:

componentData:[]

然后当组件被选中时,右侧的属性面板应该展示选中组件的对应属性,这个时候就要维护一个当前编辑的组件数据字段了:

curComponent: {}

画布区域可以对组件进行添加、删除、编辑操作,就要有对应的方法与之匹配:

// 添加组件到componentData 
addComponentData(){}, 
// 编辑组件,更新componentData及curComponent 
editComponentData(){}, 
// 删除组件 
delComponentData(){}

对于可视化编辑器这种大型前端项目,须有一个全局状态管理机制去做数据的存储和分发。这样对于数据状态的共享和同步也是很有帮助的。所以以上这些均需要维护在全局的store中:

state:{ 
// 所有添加到画布中的组件数据 
componentData:[], 
// 当前编辑的组件数据 
curComponent: {} 
} 

reducers:{ 
// 添加组件到componentData 
addComponentData(){}, 
// 编辑组件,更新componentData及curComponent 
editComponentData(){}, 
// 删除组件 
delComponentData(){} }

大的数据流转关系弄清楚了,接下来就是来设计下每个组件的Schema,由于组件都是直接来自于组件库,所以要有一些通用的属性:

{
    name: "", // 业务组件库名称 c-text c-image
    id: "",
    props: {
        // 组件独有属性
    }
}

这里的props更多是和组件本身相关联的属性,主要是一些样式属性,像宽度(width)、高度(height)、外边距(margin)、内边距(padding)、透明度(opacity)、边框(border)、位置(position)、透明度(opacity)等。

除了这些每个组件都具有的基本属性外,像文字组件还具有字体相关的fontSize、fontFamily、fontStyle、color等属性;图片组件还具有图片链接imageSrc属性;素材(形状)组件还具有背景色(background)属性。

组件的Schema看完,我们回到全局,也就是活动维度,看下单个活动的Schema:

page_config: {
    id: 1,
    title: "",
    desc: "",
    creator: "",
    status: "unpiblish",
    props: {},
    components: [],
    isTemplate: false,
}

除了组件属性外,还需要具备页面id、标题、描述、创建者、状态、是否为模板、属性props(主要包含了页面的宽度、高度、背景色等)

了解了整体大概的数据结构设计后,我们再来整理下数据流转关系:

  • 创建作品:用户创建作品,实为初始化了一个json数据
  • 保存作品:保存作品其实就是对json初始化的json就行了修改
  • 发布作品:作品的发布就是修改了作品的状态(上面page_config中的status
  • 浏览作品:作品的浏览就是在C端,choba-h5侧根据pageid拉取对应页面和组件配置,然后渲染
  • 下线作品:有些活动存在有效期,超过有效期后如果运营想下线活动可以直接下线,其实也只是status的修改,同样在C端也要添加对应逻辑

技术选型

技术方案的选择在大型项目开始前是必不可少的一步。

视图&组件框架

首先是编辑器的前端,这部分是操作较为繁琐,前端交互众多的,框架方面主要就从Vue和React中二选其一。

React和Vue都是很优秀的框架,它们之间的相似之处多过不同之处,并且大部分的优秀功能是相通的:

  • 用虚拟DOM实现快速渲染
  • 轻量级
  • 响应式组件
  • 服务端渲染
  • 集成路由工具,打包工具,状态管理工具的难度低
  • 优秀的支持和社区

然而低代码编辑平台是非常重交互的,在这一点上,Vue的双向绑定无疑是如虎添翼,能帮助我们减去不少冗余代码,另外其数据依赖收集模式使其默认的数据响应和渲染效率都要比 React 高一些。

编辑器的画布区域是需要动态加载组件的,如果你经常使用Vue,那我想你对Vue中的动态组件肯定不陌生:

<!-- 当 currentView 改变时组件就改变 -->
<component :is="currentView"></component>

市面上的大部分编辑器也都是利用了这个特性。

结合以上这些,视图层框架选择Vue。

组件库

既然组件使用方(编辑器)都已经使用了Vue,组件产出方肯定也是要用Vue的,只不过组件库和普通项目不一样,是要抽成npm包的,这里采用Rollup作为打包工具,相比Webpack,它更适合用于类库的打包。 关于Rollp的使用可参考我之前的一文带你快速上手Rollup

服务端

服务端的技术选型囊括的的东西会多一些,主要是以下几个方面:

  • NodeJS框架
  • 数据库
  • 线上服务及运维

关于框架的选型,社区有这么一个共识,也可以说是决定因素:

  • 场景,是做api还是管理后台,还是h5,不同的应用场景会有不一样的选择
  • 团队能力,如果团队Node.js经验非常丰富就无所谓,如果不是特别熟,那就至少要有一个人能cover住,如果都没有,那就挑选最成熟的最保守的做吧
  • 趋势,如果leader大局观不错,综合上面2点,再辅以趋势的话,就非常好,毕竟现在技术革新太快,别你刚学会,别人都不用了,也是比较痛苦的。

首先我们这里的场景是rest api,其次在团队能力上,大家对koa2express都比较熟悉。

koa2 仍然是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。借助 cogenerator,很好地解决了异步流程控制和异常捕获问题。其次,koa 把 Express 中内置的 router、view 等功能都移除了,使得框架本身更轻量。

综合上述因素,最终NodeJS框架选择的是koa2

数据库的选择方面,像基础的作品信息(不包含作品内容)比较适合用表格形式存储,对应的也就是mysql。而作品内容一般都是JSON,这种更适合使用mongodb存储。真正的线上环境肯定会存在高并发的场景,这个时候缓存就很有必要了,这里使用的是redis作为缓存方案。

最后的线上服务和运维部分,主要是pm2(进程守护、多进程、日志记录)和nginx(静态服务、反向代理和access log)的使用。

总结

本篇作为《如何设计实现营销搭建系统》专栏的第一篇文章,主要从需求的背景、项目架构、技术选型三方面娓娓道来。在接下来的几篇文章中,我会分别分享编辑器、脚手架、组件库以及CI/CD的细节。最终是希望通过这一个专栏带大家深入了解营销低代码平台的架构及设计实现细节,也希望大家能保持关注😊