使用vue+elementUI编写运营活动生成工具

来源:互联网 发布:淘宝助理宝贝描述红叉 编辑:程序博客网 时间:2024/06/05 06:36

前端切图的对象,很大一部分是公司营销活动类和纯展示类的页面,这一类页面通常有以下特点:


1.页面:切片(cuts的添加和删除)、功能区域(map、area或absolute操作对象)、模块(include的固定代码)、组件(components的调用和配置);

2:组件: 一份代码 + 一份数据,可复用组装。

3.有规则的数据监控和上线配置;

4.实时预览及快速发布上线。



以下为采用vue+elementUI制作运营活动工具的实践。

源码地址: JZ_Activity


活动上线流程:


1.新建活动页面,配置信息(页面标题,生成URL,分享图标及描述)






2.上传切好的各个切片(暂存于临时目录,活动生成后自动删除)



3.进入编辑页后选择组件(如:链接,功能性按钮,表单等等,可以根据需求自行开发),框选组件位置和尺寸



4.生成代码 =>

1)一键上传到服务器(需配置好对应上传目录及权限)

2)下载代码,编写无法用编辑器实现的特定需求后上传(活动代码压缩包);


组件开发流程:


1.新建vue组件.

2.进入活动编辑页

3.添加 - 选择组件 , 框选组件位置和尺寸


实现编辑页功能:

    import Vue from 'vue'export default {  components: {},  data () {    return {      defaults:{        width:0,height:0,left:0,top:0,        memorySize : true,//记住上一次尺寸        currentCutName:''      },      pageUrl:null,//生成地址      info:{},//活动信息      fileList : [],//切片列表      currentMoveArea : null,//补充未快速响应的移动事件      currentChangeArea : null,//补充未快速响应的移动事件      areaTypeList :[        {          name:'组件库',          type:2,          data:[            { key : 'slider-zhucai' , icon : 'menu' , text : '主材轮播',width:300,height:200},            { key : 'slider-fangan' , icon : 'menu' , text : '整装方案轮播',width:300,height:200},            { key : 'slider-ybj' , icon : 'menu' , text : '样板间轮播',width:300,height:200}          ]        },        {          name:'热区元素',          type:3,          data:[            { key : 'open-form' , icon : 'view' , text : '弹出表单',width:100,height:50},            { key : 'open-link' , icon : 'view' , text : '超链接',width:200,height:50}          ]        },        {          name:'表单录入',          type:3,          data:[            { key : 'input-name' , icon : 'edit' , text : '姓名',width:200,height:50},            { key : 'input-telephone' , icon : 'edit' , text : '电话',width:200,height:50},            { key : 'input-mianji' , icon : 'edit' , text : '面积',width:200,height:50},            { key : 'input-text' , icon : 'edit' , text : '文本',width:200,height:50},            { key : 'input-submit' , icon : 'check' , text : '提交',width:200,height:50}          ]        }      ]    }  },  filters: {    imgUrl (name) {      return Vue.globalOptions.root + '/static/server/custom/images/' + name;    }  },   methods: {    init (info,fileList){      this.info = info      this.fileList = fileList    },    add (item,type){      var width,height,left,top;      if(this.defaults.memorySize && this.defaults.left != 0 && item.name == this.defaults.currentCutName){          width = this.defaults.width;          height = this.defaults.height;          left = this.defaults.left;          this.defaults.top += this.defaults.height + 10;//跟上一个area加点间距          top = this.defaults.top      }else{          width = this.defaults.width = type.width;          height = this.defaults.height = type.height;          left = this.defaults.left = 100;          top = this.defaults.top = 20;      }      this.defaults.currentCutName = item.name;      item.areaList.push({        type:type,        drag:{          move_flag:false,          change_flag:false,          mousePosition:{x:0,y:0},          areaPosition:{x:0,y:0},          areaSize:{width:0,height:0}        },        left:left,        top:top,        width:width,        height:height      });    },    clear (item){      item.areaList = [];      this.defaults.width = 0;      this.defaults.height = 0;      this.defaults.left = 0;      this.defaults.top = 0;    },    move_down (event,area){      if(!area.drag.move_flag){        this.currentMoveArea = area;        area.drag.move_flag = true;        area.drag.mousePosition = {x:event.clientX,y:event.clientY};        area.drag.areaPosition = {x:area.left,y:area.top};      }    },    move_move (event,area){      if(area.drag.move_flag){        let left = area.drag.areaPosition.x + event.clientX - area.drag.mousePosition.x;        let top  = area.drag.areaPosition.y + event.clientY - area.drag.mousePosition.y;        area.left = left > 0 ? left : 0;        area.top = top > 0 ? top : 0;        if(this.defaults.memorySize){          this.defaults.left = left;          this.defaults.top = top;          this.defaults.width = area.width;          this.defaults.height = area.height;        }      }    },    move_up (event,area){      if(area.drag.move_flag){        area.drag.move_flag = false;      }    },    remove (event,area,item){      removeObjWithArr(item.areaList,area);      //设置最后一个area为默认尺寸      if(item.areaList.length>0){        let lastArea = item.areaList[item.areaList.length-1];        this.defaults.width = lastArea.width;        this.defaults.height = lastArea.height;        this.defaults.left = lastArea.left;        this.defaults.top = lastArea.top;      }else{        this.defaults.width = 0;        this.defaults.height = 0;        this.defaults.left = 0;        this.defaults.top = 0;      }    },    change_down (event,area){      event.cancelBubble = true;      if(!area.drag.change_flag){        this.currentChangeArea = area;        area.drag.change_flag = true;        area.drag.mousePosition = {x:event.clientX,y:event.clientY};        area.drag.areaSize = {width:area.width,height:area.height};      }    },    change_move (event,area){      if(area.drag.change_flag){        var width = area.drag.areaSize.width + event.clientX - area.drag.mousePosition.x;        var height = area.drag.areaSize.height + event.clientY - area.drag.mousePosition.y;        area.width = width > 50 ? width : 50;        area.height = height > 30 ? height : 30;        if(this.defaults.memorySize){          this.defaults.width = width;          this.defaults.height = height;          this.defaults.left = area.left;          this.defaults.top = area.top;        }      }    },    change_up (event,area){      if(area.drag.change_flag){        this.currentMoveArea = null;        area.drag.change_flag = false;      }    },    cut_move (event){//补充未快速响应的移动事件      if(this.currentMoveArea != null){        this.move_move(event,this.currentMoveArea);      }else if(this.currentChangeArea != null){        this.change_move(event,this.currentChangeArea);//补充未快速响应的移动事件      }    },    cut_up (event){//结束未快速响应的移动事件      if(this.currentMoveArea != null){        this.currentMoveArea.drag.move_flag = false;        this.currentMoveArea = null;      }else if(this.currentChangeArea != null){        this.currentChangeArea.drag.change_flag = false;        this.currentChangeArea = null;      }    },    save (){      var form = {          info:this.info,          cutList:this.fileList        };        var container = this.$refs.container;        var width;        if (window.getComputedStyle) {            width = window.getComputedStyle(container, null).width;        } else {             width = container.currentStyle.width;        }        form.ratio = (parseFloat(width)/1920).toFixed(2);        this.$post('activity/build', form, { emulateJSON: false }).then(function(data){          data = JSON.parse(data.bodyText);          if(data.code == 0 ){            this.$message({              message: '已存在的页面地址(请确认活动路径和页面名称是否重复)!',              type: 'warning'            });          }else{            this.pageUrl = "//localhost:8999/preview/" + this.info.url + '/' + (this.info.type=="1"?"pc":"mobile");          }          //this.$emit('close');          //this.$emit('reload');        })    }  }}


生成数据结构:

代码生成:

点击生成活动时:提交到本地nodejs server,实现以下步骤:

1.新建活动代码目录build;

2.匹配活动模板,拼接HTML字符串,生成至build目录

3.拷贝默认携带的js,images等资源至build目录

4.生成build压缩包或上线代码

5.清空暂存目录


  module.exports.build = function(req,res,next){    var info = req.body.info;    var cutList = req.body.cutList;    var ratio = req.body.ratio;    var type = info.type == "1"? "pc":"mobile";    var formIndex = 1;    var calculate = function(value){        if(type=="pc"){            return (value/ratio).toFixed(2) + 'px';        }else{            return (value/ratio/1920*100/10).toFixed(2) + 'rem';        }    };              //check dir exist    var output = Config.root + '/server/custom/output/' + info.url;    if(!fsExtra.pathExistsSync(output)){        fsExtra.ensureDirSync(output);    }    if(fsExtra.pathExistsSync(output + '/' + type )){        res.json({success:true,code:0});        return;    }else{        fsExtra.ensureDirSync(output);    }    //make html    var html_content = '';    for(let c = 0 ; c < cutList.length ; c++){        let cut = cutList[c];        let initForm = false;        if(cut.areaList.length == 0)            html_content += '<img src="<%= images(\'' + cut.name + '\') %>" alt="家装季" />\n';        else{            html_content += '<div class="activity-module">\n';            html_content += '<img src="<%= images(\'' + cut.name + '\') %>"  alt="家装季" />\n';            for(let a = 0 ; a < cut.areaList.length ; a++){                let area = cut.areaList[a];                let styles = 'top:' + calculate(area.top) + ';left:' + calculate(area.left) + ';width:' + calculate(area.width) + ';height:' + calculate(area.height) + ';';                switch(area.type.key){                    case 'open-form':                        html_content += '<button class="activity-button" style="'+ styles +'"></button>\n';                        break;                    case 'input-name':                        if(!initForm){                            initForm = true;                            html_content += '<div id="j_form' + formIndex++ + '" form-baoming="' + c + '" >\n';                        }                        html_content += '<input type="text" class="c1" data-placeholder="请输入您的姓名" style="'+ styles +'" />\n';                        break;                    case 'input-telephone':                        if(!initForm){                            initForm = true;                            html_content += '<div id="j_form' + formIndex++ + '" form-baoming="" >\n';                        }                        html_content += '<input type="tel" class="c2" data-placeholder="请输入您的联系方式" maxlength="11" style="'+ styles +'" />\n';                        break;                    case 'input-mianji':                        if(!initForm){                            initForm = true;                            html_content += '<div id="j_form' + formIndex++ + '" form-baoming="" >\n';                        }                        html_content += '<input type="tel" class="c3" data-placeholder="请输入您的房屋面积" maxlength="11" style="'+ styles +'" />\n';                        html_content = html_content.replace(new RegExp('form-baoming=\"' + c + '\"'),'form-baoming="baojia"');                        break;                    case 'input-text':                        if(!initForm){                            initForm = true;                            html_content += '<div id="j_form' + formIndex++ + '" form-baoming="" >\n';                        }                        html_content += '<input type="text" data-placeholder="请输入您的房屋面积" maxlength="11" style="'+ styles +'" />\n';                        break;                    case 'input-submit':                        if(!initForm){                            initForm = true;                            html_content += '<div id="j_form' + formIndex++ + '" form-baoming="" >\n';                        }                        html_content += '<button class="btn_submit" style="'+ styles +'"></button>\n';                        break;                          }            }            if(initForm) html_content += '</div>\n';            html_content += '</div>\n';                              }    }    //build html    var html_template_url = Config.root + '/server/custom/template/' + type + '.html';    var html_build_url = Config.root + '/server/custom/build/' + type + '/' + type + '.html';    var html = fs.readFileSync(html_template_url,"utf-8");    html = html.replace(/\[node-build-activity-title\]/g,info.title);    html = html.replace(/\[node-build-activity-modules-placeholder\]/g,html_content);    fs.writeFile(html_build_url,html,function(err){        if (err) throw err;                          //build js                  //build images        var images_build_url = Config.root + '/server/custom/build/' + type + '/' + type + '/images';        fsExtra.removeSync(images_build_url);        fsExtra.copySync(imagesUploadDir,images_build_url);                  //copy default images        var images_default_url = Config.root + '/server/custom/template/' + type + '/images';        fsExtra.copySync(images_default_url,images_build_url);                          //copy all to custom        var all_build_url = Config.root + '/server/custom/build/';        fsExtra.copySync(all_build_url + type , output);                          //clear pool        fsExtra.removeSync(imagesUploadDir);        res.json({success:true,code:1});    });                    };


源码地址: JZ_Activity


原文链接:http://www.tliangl.com/article67.aspx