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

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 = infothis.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 existvar 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 htmlvar 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 htmlvar 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 imagesvar images_build_url = Config.root + '/server/custom/build/' + type + '/' + type + '/images';fsExtra.removeSync(images_build_url);fsExtra.copySync(imagesUploadDir,images_build_url);//copy default imagesvar images_default_url = Config.root + '/server/custom/template/' + type + '/images';fsExtra.copySync(images_default_url,images_build_url);//copy all to customvar all_build_url = Config.root + '/server/custom/build/';fsExtra.copySync(all_build_url + type , output);//clear poolfsExtra.removeSync(imagesUploadDir);res.json({success:true,code:1});});};

源码地址: JZ_Activity

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

使用vue+elementUI编写运营活动生成工具相关推荐

  1. springboot+vue+elementui大学生社团活动报名系统平台

    学生社团活动平台的主要实现功能包括:管理员:学生管理.社团申请信息管理.校园社团管理.社团活动管理.会员管理.活动参与管理.会员申请管理.系统管理,会员:社团申请信息管理.校园社团管理.社团活动管理. ...

  2. vue进阶04-vue文档生成工具vuepress2

    介绍 VuePress 是一个以 Markdown 为中心的静态网站生成器.你可以使用 Markdown 来书写内容(如文档.博客等),然后 VuePress 会帮助你生成一个静态网站来展示它们. V ...

  3. 参考企业微信日程 通过vue+elementUi编写一个按月统计会议的日程计划组件

    这个组件的话 需要三个第三方依赖 npm install --save chinese-lunar-calendar sass sass-loader element-ui sass因为我这里 还是习 ...

  4. Vue+Element-Ui简单实现动态生成的表格

    顾名思义 就是根据后端传回来的数据 前端来生产不同表头的表格来表现数据: 前端代码如下: <el-table:data="tableData":height="ta ...

  5. Vue + ElementUI 动态生成面包屑导航教程

    在Web应用程序中,面包屑导航是一种常用的导航方式,它可以帮助用户更好地理解当前页面的位置和层次关系.在Vue项目中,结合ElementUI组件库,我们可以很容易地实现一个动态生成面包屑导航的功能.本 ...

  6. 记表格设计规范整理与页面可视化生成工具开发

    前言 公司有一个项目在维护,大概有300左右,其中表单与表格的页面占比大概百分之五六十,为了节省开发时间,避免多人协作时,出现多套冗余代码,我们尝试写了一下表单和表格的生成工具,从梳理到规范学习再到总 ...

  7. Vue+element-ui上传logo图片到后端生成二维码展示到页面

    Vue+element-ui上传logo图片生成二维码展示到页面 该文章将介绍如何通过前端上传二维码logo图片在后台生成二维码,并将生成的二维码转换成Base64编码返回给前端在页面展示,用户扫码二 ...

  8. vue可视化拖拽生成工具_vdesjs: 基于vue的可视化拖拽,代码生成工具。提升前端开发效率,或者集成至项目作为在线拖拽工具。(持续迭代升级中)...

    vdesjs 介绍 vdesjs是一款基于vue技术栈,可视化拖拽,代码生成工具.我们提供详细的文档来帮助您理解我们工具的实现原理,并且您可以方便的基于vdesjs来扩展您自己的代码生成组件. 技术选 ...

  9. nodejs+Vue+elementui农家乐管理系统系统-住宿-美食-活动报名系统vue

     语言 node.js 框架:Express 前端:Vue.js 数据库:mysql  数据库工具:Navicat 开发软件:VScode 目  录 管理员在还可以进行首页.个人中心.农家乐管理.美食 ...

最新文章

  1. 静态常量放在什么包里面_在沙雕游戏里面用表情包打架,是一种什么体验
  2. 鸢尾花分类_机器学习:鸢尾花数据集--贝叶斯分类
  3. WPF 3D 学习 - 3D材质初步
  4. Python简明教程
  5. SAP UI5 应用开发教程之十八 - SAP UI5 数据绑定语法里的特殊符号,以及绝对绑定和相对绑定概念详解
  6. K210 / Openmv实现 大津法/Otsu最大类间方差法 自适应二值化
  7. [20170310]关于在线日志与归档3.txt
  8. 国内maven仓库地址资源汇总
  9. 分享一个dapper简单封装
  10. mapreduce中文乱码,已解决
  11. 如何测量C#代码的运行时间
  12. 07堆排序 python
  13. element ui 选项卡切换_Vue.js + element-ui 扫盲(服务端对大前端的扫盲)
  14. 周立功专访:周立功和他的团队已经找到了属于自己的道路
  15. 预训练模型在金融 NLP场景下的应用
  16. python scatter参数详解_Python中scatter函数参数及用法详解
  17. 大一计算机虚拟机,虚拟机对电脑伤害大吗
  18. 数据模型:概念数据模型,逻辑数据模型,物理数据模型
  19. Oracle 数据库中 同义词的意思
  20. Java中的线程-1

热门文章

  1. 学平面设计要掌握哪些小知识?
  2. 什么是平面设计?平面设计发展现状如何?
  3. SpringBoot集成cas-client 客户端配置拦截过滤,绝对最简单有效,亲测
  4. 树莓派小车教程(二)之——基于Tornado框架的网页控制小车(按键+鼠标点击)
  5. spring-boot-2.0.3不一样系列之源码篇 - springboot源码一,绝对有值得你看的地方
  6. Unity制作自定义字体的两种方法
  7. FFmpeg从入门到牛掰(二):转封装(remux)讲解
  8. python-opencv提取复杂背景下的文字
  9. jetson AGX Opencv 编译记录
  10. 腾讯QQ无力?推出新武器“TIM”