堆糖后台的可视化编辑器

这两周的实习除了老东西一些迁移到angular的项目以外(话说我已经写了4000+行angular了现在闭上眼睛都是满天$scope),还在做一个很有意思的东西:一个给运营人员用的可视化编辑器。据堆糖内部从阿里某宝跑出来的架构师说这东西他们之前就有一个?

开发背景

如果你手机上有堆糖的APP的话,在“发现”那个栏目里有一个“精品团”的二级分类。点进去之后大概是这样:

此处输入图片的描述

这就是堆糖近期正式商业化后的第一个项目(似乎还挺成功的,提前半个月达成目标,明天要去庆功宴0w0),每天会在这里更新一些有意思的小商品。

既然要达到每天更新的频率,那么就基本不可能让苦逼的前端每天“画”一张(要知道堆糖的前端加上我也只有4个人),所以需要想一个办法让不懂代码是个啥的运营人员自己弄。

最开始我们想到的方法就是喜闻乐见的模板引擎,只要运营人员写一大段商品信息的JSON,然后我们就可以优雅地把这段JSON用模板引擎渲染出来(之前用的是handlebars)。

此处输入图片的描述

但是这样的话不就意味着运营人员也要懂写JSON吗?(掀桌)虽然在堆糖这样一个码农会做产品设计,运营会写代码的地方不是什么奇怪的事情,但终究还是会有些不优雅的地方(比如有些地方少一个逗号括号啥的)。

更大的问题在于,这种方式依然给前端带来了很大的压力,因为:

  1. 每一张页面都需要我们去写一个模板,以及范例JSON,里面还可能会带有一些js的组件比如倒计时、评论这些不能用模板引擎的东西。

  2. 当页面层次结构变得复杂的时候,对应储存数据的JSON的结构也会变得复杂,让JSON的编写、维护成本越来越大,到最后出现了类似}]}}}]]}}这样的嵌套地狱。

所以这个时候就提出了一个很酷的想法:我们要做一个可视化编辑器!没错就是要比strikingly还屌的那种!(逃


所以怎么做呢?

1、HTML编辑器
最开始我们的想法很简单,不是要编辑器吗?那就模仿着现在烂大街(不)的微信平台编辑器来弄个轻量级的呗。

后来发现这样是有问题的,因为我们最后需要生成的页面中不只是有HTML,还有一些js的小组件(比如倒计时的插件),这些插件是很难用HTML编辑器这种东西来编辑的。比如倒计时的效果,编辑者实际上需要编辑“目标时间”,然后代码不断地自动刷新计时器,而这个“目标时间”是不会直接在页面上显示的,是一种“隐含”的信息。这种隐含的信息用类似HTML编辑器的东西去编辑是很难做的。

2、strkingly这样的建站工具
然后我们就自然而然的想到了类似strikingly这样的大型建站工具,后来发现也不适合,因为这种做法过于臃肿了,它的逻辑实际上是这样子的:

当生成网页的时候,我们做两件事情:

1、编辑器的源数据 -> HTML/JS/CSS
2、保存源数据,以便将来修改这个页面

修改网页的时候,我们需要:

1、从服务器读取保存的源数据
2、将数据渲染到编辑器内

这种做法很酷,功能和可扩展性都很好,但是需要服务器端提供支持。现在我们需要的只是一把轻巧的剪刀,可是它却是一台功能齐全但是笨重庞大的全自动收割机。


最终的实现方法

既要组件化、可视化编辑,又不需要像建站工具那样大而全。所以我们最后选用了一种很巧妙(并不)的方法。

首先我们构建了一套语义化的标签,类似这样:

<i class="dt-cms dt-cms-copy">+</i> //复制这个标签所在的块
<i class="dt-cms dt-cms-delete">x</i> //删除这个标签所在的块
...

然后我们会在页面中写入这些标签,当然,这些标签不会出现在实际的页面上,因为实际的页面中声明了CSS:

.dt-cms{
    display:none
}

当我们需要编辑这些页面时,会用一个AJAX请求到这个页面的HTML代码,然后在HTML代码中插入几行scriptlink标签,然后写入一个iframe中:

...
<script type="text/javascript" src="pageEdit.js"></script>
<link rel="stylesheet" href="pageEdit.css">
...

pageEdit.css中大概是这样:

...
.dt-cms{
    display:block !important; //让语义化标签显示出来
}

p:hover,span:hover,h1:hover,strong:hover,h2:hover,img:hover,em:hover {
    box-shadow: 0px 0px 3px red; 
    //让鼠标悬停在可编辑的标签上时,显示一个红色的轮廓
}
...

pageEdit.js主要需要实现三个东西:

1.<p><img><span><a>……等标签直接点击即可弹出一个编辑框编辑一些信息

2.dt-cms-deletedt-cms-copy……这样的语义化标签的功能实现

3.一些组件的实现

pageEdit.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
$(window).click(function(e){
var className = $(e.target).attr('class');
var tagName = $(e.target).attr('tagName');
if(className === 'dt-cms-copy'){
//复制操作
}
if(className === 'dt-cms-delete'){
//删除操作
}
...
if(tagName === 'P'){
//弹出一个编辑框,可以编辑这个P标签
}
if(tagName === 'IMG'){
//弹出一个编辑框,可以编辑这个IMG标签的链接地址
}
...
if($(e.target).attr('dt-cms-expiretime')){
//如果有dt-cms-expiretime这样的属性,那么就是倒计时组件,弹出特殊的编辑框
}
...
})
...

现在是上线了0.1版本(只有内部能访问),只能编辑几张风格固定的页面,将来会考虑模块化以及交互体验。。。

以及迟早有一天会开源的!!!