前言
两年前的时候就想做一个类似的功能,当时思路大家都讨论好了,诸多原因最终还是夭折了。没想到两年多后再这有重新提出要写一个绘制表单的功能。对此也是有点小激动呢?总共用时8.5天的时间基本功能也就实现了,当然再者中间也借用了网上的一些资料,公司前端也没有帮忙处理,所以样式和部分功能还没有更好地得到处理,github上出的code只有前端脚本,至于后端的处理,会在博客中体现出来。
1.工作前准备
1.1.实现的思路
思路一:
(1)ueditor添加自定义按钮
(2)绘制表单(控件会触发的脚步【暂时考虑范围】)【每个控件均需添加控件名称和创建名称】
(3)保存表单时建立数据库表(无需存储表信息),并保存html字符串
(4)修改表单需同时修改数据库
(5)表单发起获取数据封装成json,进行后台保存。
思路二:
(1)jquery 拖动自定义标签,在指定区域进行绘制
(2)表单属性设置相应的表单属性和表单基本布局
(3)设置每个控件的属性值
(4)把表单信息和控件以json的形式传入后台进行保存
(5)从后台获取数据json对象用jquery 绘制表单页面
(6)创建一张表(F-F200)把表单数据存入表单中。
最终选择的是【思路二】,原因是富文本编辑器绘制起来有很多自动生成的标签,让人感觉很是不爽。当然可以对ueditor进行处理(这个也是两年前的思路)。
1.2.实现过程的确定
整个的过程从借鉴开始网上有些类似的功能,从中得到很多帮助在这就不一一鸣谢了。然后就是没羞没臊的3天脚本修改工作【现在基本完成不过还在持续中】。后台数据的处理完全没有什么可说的,中间用的了一些缓存问题,本来说是用redis呢,结果商量一些说不用难部署(难部署???好吧一脸懵逼),就用了c#的CacheHelper。
2.具体实现
绘制表单预览与保存
2.1.脚本
以上是表单创建的js脚本。
就是上边那个图片的实现。
html重要分左中右三部分。左边是页面上所用到的标签区域,中间是展示区域,右边是表单和控件属性的设置区域。htnl 脚本如下:
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="keywords" content="kmonkey,王延领,在线表单,自定义表单,表单设计器">
<meta name="description" content="表单设计器,支持文本、图片、地图、单选、多选,下拉等多种输入类型,我是准备把它做成一个超级通用的一个插件。让不懂编程的人也能很轻松的设计出想要的表单。继续加油code吧">
<meta name="renderer" content="webkit">
<title>表单设计title>
<link type="text/css" rel="stylesheet" href="~/Content/FormDesign/css/common.css?v=20160929" />
<link type="text/css" rel="stylesheet" href="~/Content/FormDesign/css/jquery-ui-1.9.2.custom.css" />
<link type="text/css" rel="stylesheet" href="~/Content/FormDesign/css/widgets.css?v=20160929" />
<link type="text/css" rel="stylesheet" href="~/Content/FormDesign/css/jquery.mCustomScrollbar.min.css?v=20160929" />
<link type="text/css" rel="stylesheet" href="~/Content/FormDesign/css/formbuild.css?v=20160929" />
head>
<body>
<div id="container">
<div id="left">
<div id="addFields" class="overhide">
<h3 class="fields-group">通用字段h3>
<ul id="col1">
<li id="drag_text" ftype="text"><a id="sl" class="btn-field" title="适用于填写简短的文字内容,身份证号、银行卡号、工号等请使用此类型。" href="#"><i class="iconfont">i>单行文本a>li>
<li id="drag_textarea" ftype="textarea"><a id="pt" class="btn-field" title="适用于填写大段文本,如“备注”、“留言”" href="#"><i class="iconfont">i>多行文本a>li>
<li id="drag_radio" ftype="radio"><a id="mc" class="btn-field" title="适用于在少量选项里选一个,如“男/女”" href="#"><i class="iconfont">i>单选框a>li>
<li ftype="date"><a id="dt" class="btn-field" title="适用于选择特定的日期" href="#"><i class="iconfont">i>日期a>li>
<li ftype="dropdown2"><a id="dd2" class="btn-field" title="适用于展示多级联动,如第一级是饮料,第二级只能选择绿茶、红茶等" href="#"><i class="iconfont">i>多级下拉框a>li>
<li ftype="file"><a id="fu" class="btn-field" title="适用于收集文件,如简历、照片" href="#"><i class="iconfont">i>文件上传a>li>
<li id="drag_radio" ftype="section"><a id="sb" class="btn-field" title="用于将字段分组显示,更清晰" href="#"><i class="iconfont">i>分隔符a>li>
ul>
<ul id="col2">
<li id="drag_number" ftype="number"><a id="nb" class="btn-field" title="适用于填写涉及到数学运算的数字,身份证号、银行卡号、工号等请使用单行文本。" href="#"><i class="iconfont">i>数字a>li>
<li id="drag_checkboxes" ftype="checkbox"><a id="cb" class="btn-field" title="适用于在几个选项里选多个,如投票" href="#"><i class="iconfont">i>多选框a>li>
<li id="drag_dropdown" ftype="dropdown"><a id="dd" class="btn-field" title="适用于在非常多的选项里选一个,如省份选择" href="#"><i class="iconfont">i>下拉框a>li>
<li ftype="time"><a id="ti" class="btn-field" title="适用于填写特定的时间" href="#"><i class="iconfont">i>时间a>li>
<li ftype="likert"><a id="lk" class="btn-field" title="适用于处理批量单选" href="#"><i class="iconfont">i>组合单选框a>li>
<li ftype="image"><a id="im" class="btn-field" title="在表单上加入图片,起到宣传产品或美化表单的作用" href="#"><i class="iconfont">i>图片a>li>
<li id="drag_dropdown" ftype="html"><a id="ht" class="btn-field" title="适用于添加HTML显示元素,如“p,a,span,div”等" href="#"><i class="iconfont">i>HTMLa>li>
ul>
<h3 class="fields-group">联系信息字段h3>
<ul id="col3">
<li ftype="name"><a id="nm" class="btn-field" title="适用于填写用户姓名" href="#"><i class="iconfont">i>姓名a>li>
<li ftype="address"><a id="ad" class="btn-field" title="适用于填写全国的地址" href="#"><i class="iconfont">i>地址a>li>
<li ftype="phone"><a id="ph" class="btn-field" title="适用于填写中国大陆内的手机和座机号码" href="#"><i class="iconfont">i>电话a>li>
ul>
<ul id="col4">
<li ftype="email"><a id="em" class="btn-field" title="适用于填写电子邮箱地址" href="#"><i class="iconfont">i>电子邮箱a>li>
<li ftype="map"><a id="mp" class="btn-field" title="通过地图收集地理信息,手机上可自动定位" href="#"><i class="iconfont">i>地理位置a>li>
<li ftype="url"><a id="ws" class="btn-field" title="适用于填写网站链接" href="#"><i class="iconfont">i>网址a>li>
ul>
<h3 class="fields-group">宏控件h3>
<ul id="col5">
<li ftype="goods"><a id="gd" class="btn-field" title="和已知系统数据配合使用,如当前登入人" href="#"><i class="iconfont">i>当前登入人a>li>
ul>
<ul id="col6">
<li ftype="goods" subtype="noimg"><a id="gd2" class="btn-field" title="和已知系统数据配合使用,如组织结构部门" href="#"><i class="iconfont">i>登入人部门a>li>
ul>
div>
div>
<div id="middle">
<div class="forms">
<div id="fbForm" class="form form-focused">
<h2 id="fTitle">h2>
<div id="fDescription">div>
div>
div>
<div id="nofields" class="notice hide" style="margin:30px 18px 0px 28px">
<div id="addFromButton" style="cursor:pointer;">
<h2 class="color-red">没有字段!h2>
<a href="#">表单中没有字段,点击或拖动左边的组件添加字段。a>
div>
div>
<ul id="fields" class="fields">ul>
<div class="formButtons hide" id="formButtons">
<table style="margin:auto;font-size:1.0em">
<tr>
<td style="border:none;"><a class="btn left" id="preview">预览a>td>
<td style="border:none;"><a class="btn blue left" id="saveForm" href="#">保存a>td>
tr>
table>
div>
div>
<div id="right">
<div class="notice hide" style="margin-top:30px;border:none" id="noFieldSelected">
<h3><b>没有选择字段b>h3>
<p>请先在右侧选择需要编辑的字段,然后在此编辑字段的属性。p>
div>
<div id="fieldProperties" class="hide">
<h3 class="property-title">表单属性h3>
<div id="allPropsContainer">
<ul id="allProps">
<li id="plabel">
<label class="desc" for="lbl">
字段名称
label>
<textarea id="lbl" name="LBL" class="xxl" rows="2">textarea>
li>
<li id="ptype" class="left half">
<label class="desc" for="type">
字段类型
<a href="#" class="help" title="关于字段类型" rel="可以修改表单保存之前添加字段的类型。">(?)a>
label>
<select id="type" name="TYP" class="xxl">
<optgroup label="标准类型">
<option value="text">单行文本option>
<option value="textarea">多行文本option>
<option value="radio">单选框option>
<option value="number">数字option>
<option value="checkbox">多选框option>
<option value="dropdown">下拉框option>
optgroup>
<optgroup label="常用类型">
<option value="email">电子邮箱option>
<option value="address">地址option>
<option value="map">地理位置option>
<option value="phone">手机option>
<option value="name">姓名option>
<option value="file">上传文件option>
<option value="date">日期option>
<option value="time">时间option>
<option value="url">网址option>
<option value="likert">组合单选框option>
<option value="dropdown2">多级下拉框option>
<option value="image">图片option>
<option value="goods">配图商品option>
<option value="goodsnoimg">无图商品option>
optgroup>
select>
li>
<li class="right half" id="pfldsize">
<label class="desc" for="fldsize">
字段长度
<a href="#" class="help" title="关于字段长度" rel="用于限定字段输入框的长度(“多行文本”字段限定输入框高度)。">(?)a>
label>
<select id="fldsize" name="FLDSZ" class="xxl">
<option value="s">短option>
<option value="m">中option>
<option value="xxl">长option>
select>
li>
<li class="right half" id="playout">
<label class="desc" for="layout">
字段布局
<a href="#" class="help hide" title="关于字段布局" rel="此属性仅对复选框和单选框类型的字段有效,用于定义复选框或单选框的排列方式。其中自动排列是指按一个接一个的方式进行排列。">(?)a>
label>
<select id="layout" name="LAY" class="xxl">
<option value="one">一列option>
<option value="two">二列option>
<option value="three">三列option>
<option value="oneByOne">自动排列option>
select>
li>
<li class="right half" id="pdateformat">
<label class="desc" for="dateformat">
日期格式
<a href="#" class="help hide" title="关于日期格式" rel="此属性用于指定日期的输入格式。YYYY代表年,MM代表月,DD代表日。">(?)a>
label>
<select id="dateformat" name="FMT" class="xxl">
<option value="ymd" selected="selected">YYYY - MM - DDoption>
@*<option value="mdy">MM / DD / YYYYoption>
<option value="dmy">DD / MM / YYYYoption>*@
select>
li>
<li class="right half" id="pphoneformat">
<label class="desc" for="phoneformat">
电话格式
<a href="#" class="help hide" title="关于电话格式" rel="此属性用于指定电话的输入格式。支持普通的电话号码输入和“区号-总机-分机”的座机号码输入。">(?)a>
label>
<select id="phoneformat" name="FMT" class="xxl">
<option value="mobile" selected="selected">手机option>
<option value="tel">座机option>
select>
li>
<li class="right half" id="pnameformat">
<label class="desc" for="nameformat">
姓名格式
<a href="#" class="help hide" title="关于姓名格式" rel="此属性用于指定姓名的输入格式。支持普通的姓名格式和带称呼的加长格式。">(?)a>
label>
<select id="nameformat" name="FMT" class="xxl">
<option value="short" selected="selected">普通option>
<option value="extend">加长option>
select>
li>
<li class="right half" id="pmoneyformat">
<label class="desc" for="moneyfomat">货币格式label>
<select id="moneyfomat" name="FMT" class="xxl">
<option value="yen">¥ 人民币/日元option>
<option value="dollars">$ 美元option>
<option value="pounds">£ 英镑option>
<option value="euros">€ 欧元option>
select>
li>
<li class="left half" id="pN">
<label class="desc" for="N">层级label>
<select id="N" name="pN" class="xxl">
<option value="2" selected="selected">2option>
<option value="3">3option>
<option value="4">4option>
select>
li>
<li class="clear noheight">li>
<li id="plikert" class="bggray">
<fieldset>
<legend>
行标签
<a href="#" class="help hide" title="关于行标签" rel="此属性用于指定组合单选框中表示组合类别的标签。">(?)a>
legend>
<ul id="likertRows">ul>
fieldset>
<fieldset>
<legend>
列标签
<a href="#" class="help hide" title="关于列标签" rel="此属性用于指定组合单选框中表示级次的标签。">(?)a>
legend>
<ul id="likertCols">ul>
<div class="center">
<a id="btnLikertPredefine" href="#" class="btn gray">批量编辑a>
div>
fieldset>
li>
<li class="clear noheight">li>
<li id="pitems" class="clear bggray">
<fieldset>
<legend>
选择项
<a href="#" class="help hide" title="关于选择项" rel="此属性用于指定有哪些选择项可以提供给用户选择。利用旁边的增加或删除按钮或以增加或删除选择项。对于下拉框在没有指定默认选中项的情况下将自动选中第一项。">(?)a>
legend>
<ul id="itemList">ul>
<div id="pitems_radio" class="center">
<a id="btnItemsPredefine" href="#" class="btn gray">批量编辑a>
div>
<div id="pitems_batchedit" class="center">
<a id="btnItemsBatch" href="#" class="btn gray">批量编辑a>
div>
fieldset>
li>
<li id="pgoods" class="clear bggray">
<fieldset>
<legend>
商品列表
<a href="#" class="help hide" title="关于商品列表" rel="此属性用于指定在表单中显示的商品。如果是图片商品,图片长宽比例请保持1:1,文件体积需要在500KB以内,支持.jpg格式。提示:按住商品列表拖动可以排序哦。">(?)a>
legend>
<ul id="goodsList" class="clearfix">ul>
<div id="pgoods_radio" class="center add-goods">
<form name="goodsUploadForm" class="add-image-btn" action="" method="POST" enctype="multipart/form-data" style="height:35px;padding:5px 0px;vertical-align: middle;">
<a id="btnAddGoods" title="添加配图商品" class="btn gray" href="#">
<span style="display:block;">+ 添加配图商品span>
<input id="fileToUpload" title="添加配图商品" name="fileToUpload" class="file-prew" title="支持jpg、jpeg、png格式,文件小于500K" type="file" size="3" accept="image/jpeg,image/png,image/bmp,image/gif" />
a>
form>
<div id="addNoImgGoods" class="add-goods-btn" style="height:35px;padding:5px 0px;vertical-align: middle;">
<a id="btnAddNoImgGoods" title="添加无图商品" class="btn gray"><span>+ 添加无图商品span>a>
div>
<div class="clear">
<input id="goodsForBuy" value="1" name="FBUY" type="checkbox">
<label for="goodsForBuy">商品用于向供应商询价label>
<a href="#" class="help hide" title="关于商品用于向供应商询价" rel="当勾选此选项时,将由制表人确信数量,填表人根据数量填写单价。主要用于向供应商询价,供应商填写表单进行报价的场景。">(?)a><br>
div>
div>
fieldset>
li>
<li id="pimage">
<form name="uploadImageForm" action="" method="POST" enctype="multipart/form-data" style="padding:5px 0px;">
<label class="desc" for="uploadImage">
上传图片<a href="#" class="help hide" title="关于图片" rel="在表单中添加图片显示,支持gif格式,每张图片最大2M。">(?)a>
label>
<a class="btn gray filewrap">
<span>上传图片span>
<input type="file" id="uploadImage" name="uploadImage" title="支持jpg、jpeg、png格式,文件小于500K" accept="image/jpeg,image/png,image/bmp,image/gif" />
a>
form>
li>
<li class="left half clear" id="poptions">
<fieldset>
<legend>设置legend>
<ul>
<li id="popt_required">
<input id="reqd" name="REQD" type="checkbox" value="1" />
<label for="reqd">必须输入label>
<a href="#" class="help hide" title="关于必须输入" rel="强制填表人该字段必须输入,否则将不能提交表单。观看视频说明">(?)a>
li>
<li id="popt_unique">
<input id="uniq" name="UNIQ" type="checkbox" value="1" />
<label for="uniq">不许重复label>
<a href="#" class="help" title="关于不许重复" rel="用于保证字段输入值的唯一性,适用于如手机号、QQ号等需要保证唯一性的输入值。">(?)a>
li>
<li id="popt_hidenum">
<input id="hidenum" name="HDNM" type="checkbox" value="1" />
<label for="hidenum">隐藏数字label>
<a href="#" class="help hide" title="关于隐藏数字" rel="在单选框下方通常都有一个数字用于标识此选项的分值,此属性用于指定是否隐藏此数字。">(?)a>
li>
<li id="popt_authcode">
<div>
<input id="internal" name="INTERNAL" type="checkbox" value="1" />
<label for="internal">启用国际手机label> <a href="#" class="help hide" title="关于启用国际手机号" rel="启用后可以向全球200多个国家和地区发送短信,请先联系客户咨询使用详情。查看资费明细">(?)a>
div>
<input id="authcode" name="AUTH" type="checkbox" value="1" />
<label for="authcode">验证码label> <a href="#" class="help hide" title="关于手机验证码" rel="启用验证码需要满足以下两个条件:1、签名通过审核(可联系在线客服审核);2、有可用短信量(短信需要单独购买);查看资费明细">(?)a>
<div id="signcnt" class="hide">
<input id="sign" name="SIGN" placeholder="短信签名" type="text" maxlength="16" style="width:60px;" />
<a id="btnSignSumbmit" target="_blank" href="/web/formview/5606403b0cf2f6fe39b1965d" class="btn no-icon btn-blue small">提交审核a>
div>
li>
<li id="popt_dismark">
<input id="chkDismark" name="DISMK" type="checkbox" value="1" />
<label for="chkDismark">禁止手动标注label>
<a href="#" class="help hide" title="禁止手动标注" rel="默认情况下,地理位置支持自动定位和手动标注。您可以勾选此选项来禁用手动标注,满足某些需要真实确认填表人位置的场景。">(?)a>
li>
ul>