Jquery+layui的动态表单构建
页面代码
<meta charset="utf-8">
<style>
.upload_img_list {
margin: 10px 0 0 0
}
.upload_img_list dd {
position: relative;
margin: 0 10px 10px 0;
float: left;
width: 92px;
}
.upload_img_list .operate {
position: absolute;
top: 0;
right: 0;
z-index: 1
}
.upload_img_list .operate i {
cursor: pointer;
background: #2F4056;
padding: 2px;
line-height: 15px;
text-align: center;
color: #fff;
margin-left: 1px;
float: left;
filter: alpha(opacity = 80);
-moz-opacity: .8;
-khtml-opacity: .8;
opacity: .8;
}
.upload_img_list dd .img {
width: 92px;
height: 92px;
}
</style>
<script src="/static/js/commonjs.js"></script>
rel="stylesheet" type="text/css">
<div id="app" style="width: 980px">
<form class="layui-form" action="" lay-filter="form">
<div id="form"></div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit="" lay-filter="save">保存</button>
<button type="button" οnclick="doclose()"
class="layui-btn layui-btn-primary">关闭</button>
</div>
</div>
</form>
</div>
<script src="/static/js/form_create.js"></script>
<script>
var model_name = "fd_estate";
//排除项
var exclude_table_col = [ "create_time", "update_time", "deleted",
"create_by", "update_by" ];
var pics = {};
var must = []; //必填项
var islimit = false;
$(function() {
layui
.use(
[ 'form', 'upload', 'laydate' ],
function() {
var form = layui.form;
var upload = layui.upload;
var laydate = layui.laydate;
//数据源请求接口
$.get("http://127.0.0.1:8080/model/test",
{
model : model_name
},
function(data) {
console.info(data)
if (data.code == 0) {
var metadata = data.data.metadata;
console.log(metadata)
var cols = []
var fieldset = fd_title(data.data.title);
$("#app").prepend(fieldset);
for (var i = 0; i < metadata.length; i++) {
cols = cols
.concat(metadata[i].section.children)
var group = fd_group(metadata[i].section.label);
$("#form")
.append(group);
for (var cj = 0; cj < metadata[i].section.children.length; cj++) {
var child = metadata[i].section.children[cj];
if (child.inputType.vadidate.required) {
var item={
key:child.column,
value:child.label,
type:child.inputType.type
};
must.push(item);
console.log("必填项数组===",must)
}
if (exclude_table_col.indexOf(child.column) > -1) {
console.log("必填项数组===",child.column)
continue;
}
if (child.inputType.type == inputType.FD_TEXT) {
var item=fd_item();
$("#form").append(item);
var input = fd_input(child);
$("#form").children().last().append(input);
} else if (child.inputType.type == inputType.FD_AREATEXT) {
var item=fd_item();
$("#form").append(item);
var textarea = fd_textarea(child);
$("#form").children().last().append(textarea);
} else if (child.inputType.type == inputType.FD_DATE) {
var item=fd_item();
$("#form").append(item);
var time = fd_date(child);
$("#form").children().last().append(time);
fd_date_init(laydate,child);
} else if (child.inputType.type == inputType.FD_PIC) {
pics[child.column] = [];
var item=fd_item();
$("#form").append(item);
var pic_view = fd_addpic(child);
$("#form").children().last().append(pic_view);
initpic(child,upload);
} else if (child.inputType.type == inputType.FD_NUMBER) {
var item=fd_item();
$("#form").append(item);
var number_txt = fd_number(child);
$("#form").children().last().append(number_txt);
} else if (child.inputType.type == inputType.FD_SELECT) {
var item=fd_item();
$("#form").append(item);
var select_txt = fd_select(child);
$("#form").children().last().append(select_txt);
form.render('select');
}
} }} });
//监听提交
form.on('submit(save)', function(data) {
data.field.file = pics;
//校验必填项
for(var i=0;i<must.length;i++){
if(must[i].type==inputType.FD_PIC){
layer.msg("请填写"+data.field.file[must[i].key].length);
if(data.field.file[must[i].key].length<=0){
layer.msg("请上传"+must[i].value);
return false;
}
}else{
if(data.field[must[i].key]==''){
layer.msg("请填写"+must[i].value);
return false;
}
}
}
$.post("http://127.0.0.1:8080/model/test", {
data : {
model : model_name,
data_json : data.field
},
}, function(res) {
alert("数据");
});
layer.msg(JSON.stringify(data.field));
return false;
});
});
});
function doclose() {
alert("关闭窗口")
parent.vm.iframeclose();
var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
parent.layer.close(index); //再执行关闭
}
</script>
每个标签的封装js
function fd_item(){
var item_str="<div class='layui-form-item'></div>";
return item_str;
}
function fd_input(child) {
var required=child.inputType.vadidate.required;
if (required) {
required = "required";
} else {
required = "";
}
var input = "<label class='layui-form-label'>"
+ child.label
+ "</label><div class='layui-input-block'><input type='text'"
+ " id='" + child.column + "' " + "name='" + child.column + "' " + required
+ " placeholder='" + child.label
+ "' autocomplete='off' class='layui-input'></div>";
return input;
}
function fd_number(child) {
var required=child.inputType.vadidate.required;
if (required) {
required = "required";
} else {
required = "";
}
var input = "<label class='layui-form-label'>"
+ child.label
+ "</label><div class='layui-input-block'><input type='number' name='"
+ child.column + "'" + required + " placeholder='" + child.label
+ "' autocomplete='off' class='layui-input'></div>";
return input;
}
function fd_title(title) {
var return_txt = "<div class='layui-elem-quote' style='margin-top: 20px;font-size: 20px;'><p>"
+ title + "</p></div>";
return return_txt;
}
function fd_textarea(child) {
var max=child.inputType.vadidate.max;
if(max=="-1"||max==-1){
max="";
}else{
max="maxlength='"+max+"'";
}
var return_txt = "<label class='layui-form-label'>"
+ child.label
+ "</label><div class='layui-input-block'><textarea type='text' id='"
+ child.column
+ "' name='"
+ child.column+"'"+max
+ " autocomplete='off' placeholder='"
+ child.label + "' class='layui-textarea'></textarea></div>";
return return_txt;
}
function fd_group(title) {
var return_txt = "<fieldset class='layui-elem-field layui-field-title' style='margin-top: 20px; width: 300px;font-size: 16px;'><legend style='font-size: 16px;'>"
+ title + "</legend></fieldset>";
return return_txt;
}
/*
* title:标题,例如:门责图片 limitpicnum:图片上传数量限制
*
*/
function fd_addpic(child) {
var id=child.column;
var title=child.label;
var limitpicnum=child.inputType.vadidate.max;
var choose_txt = "<button type='button' class='layui-btn' id='" + id
+ "'>请选择图片</button>";
if (islimit == true) {
choose_txt = "";
}
var picsString = "<div class='upload_img_list' style='display: flex; flex-wrap: nowrap' id='"+id+"_view'></div>";
var return_txt = "<label class='layui-form-label'>"
+ title
+ "</label><div class='layui-input-block'><div class='layui-upload'>"
+ choose_txt
+ "<div class='layui-upload-list' style='display: flex; flex-wrap: nowrap'>"
+ picsString
+ "</div></div></div><div class='layui-input-block'><span style='color: red;'>图片限制上传"
+ limitpicnum + "张</span></div>";
return return_txt;
}
function fd_showpic(limitpicnum, id) {
var temp = "";
if (pics[id] == null || pics[id] == undefined || pics[id] == NaN
|| pics[id] == '') {
pics[id] = [];
}
for (var i = 0; i < pics[id].length; i++) {
temp = temp
+ "<dd id='"
+ i
+ "'><div class='operate'><i class='layui-icon layui-icon-delete' style='color: #fff;' οnclick='piccancel("
+ i
+ ",""
+ pics[id].join(",")
+ "","
+ limitpicnum
+ ",""
+ id
+ "")'></i></div><img class='img' src='http://192.168.1.42:7112"
+ pics[id][i] + "' id='"+id+"_view'></dd>"
}
return temp;
}
function initpic(child, upload) {
var id=child.column;
var limitpicnum=child.inputType.vadidate.max;
var multipleUpload = upload.render({
elem : '#' + id, // 绑定元素
url : 'http://192.168.1.42:7112/common/upload/zipimg', // 上传接口
exts : 'png|jpg|jpeg',
accept : 'images',
acceptMime : 'image/jpg, image/png,image/jpeg',
multiple : true, // 允许多文件上传
number : limitpicnum, // 允许上传文件数,0不限,当不限制图片上传数量时,请注意数据库字段允许的最大长度
before : function(obj) {
},
done : function(res, index, upload) {
// 如果上传失败
if (res.code > 0) {
return layer.msg(index, '上传失败');
} else {
if (pics[id].length >= limitpicnum) {
islimit = true;
} else {
pics[id].push(res.url);
$('#' + id+'_view').empty();
$('#' + id+'_view').append(fd_showpic(limitpicnum, id));
if (pics[id].length == limitpicnum) {
islimit = true;
}
}
}
// 上传成功
},
error : function() {
},
allDone : function(obj) { // 当文件全部被提交后,才触发
}
});
}
function piccancel(index, pic_list, limitpicnum, id) { // 删除图片
console.log("删除===",pics[id])
pic_list = pic_list.split(",");
pic_list.splice(index, 1); // 操作图片数组
pics[id] = pic_list;
if (pics[id].length < limitpicnum) { // 判断此时图片数量是否达到限制,未达到则显示上传按钮
islimit = false;
}
$('#' + id+'_view').empty();
$('#' + id+'_view').append(fd_showpic(limitpicnum, id));
}
function fd_txt(title, name, placeholder, required) {
if (required) {
required = "required";
} else {
required = "";
}
var input = "<label class='layui-form-label'>"
+ title
+ "</label><div class='layui-input-block'><input type='text' name='"
+ name + "'" + required + "placeholder='" + placeholder
+ "' autocomplete='off' class='layui-input'></div>";
return input;
}
function fd_date(child) {
var required=child.inputType.vadidate.required;
if (required) {
required = "required";
} else {
required = "";
}
var input = "<label class='layui-form-label'>"
+ child.label
+ "</label><div class='layui-input-block'><input type='txt' id='fd_"
+ child.column + "'name='" + child.column + "'" + required + " placeholder='"
+ child.label
+ "' autocomplete='off' class='layui-input'></div>";
return input;
}
function fd_date_init(laydate,child) {
var format=child.inputType.format;
var type = "date";
if (format == "yyyy" || format == "YYYY") {
type = "year";
} else if (format == "yyyy-mm" || format == "YYYY-MM"
|| format == "YYYY-mm" || format == "yyyy-MM") {
type = "month";
}
laydate.render({
elem : '#fd_' + child.column,
type : type,
done : function(value) {
}
});
}
function fd_select(child) {
var list=child.inputType.option.options;
var temp = "";
for (var i = 0; i < list.length; i++) {
temp = temp + "<option value='" + list[i].label + "'>" + list[i].value
+ "</option>"
}
var select_str = "<label class='layui-form-label'>"
+ child.label
+ "</label><div class='layui-input-block'><select lay-search='' name='"
+ child.column
+ "' lay-filter='"
+ child.column
+ "'>"
+ temp
+ "</select></div>";
return select_str;
}
公共js
var inputType = {
FD_TEXT : "fd_text",//限制 是否必填
FD_AREATEXT :"fd_areatext",//限制文字的长度
FD_PIC :"fd_pic",
FD_DATE :"fd_date",//限制 是否必填
FD_NUMBER :"fd_number",//输入类型为数字 限制 是否必填
FD_SELECT:"fd_select"
};
数据格式
{
table:"", // 生成的表名
name:"", // 表单元数据 查询name 唯一
title:"", // 中文业务名
parent_table:{
isChildren:true/flase, // 是否有关联
table:"", // 关联表
column:"", // 关联字段
value:"" // 查询值
}, // 关联表名
metadata:[
{
section:{
label:"", // 块级 label显示 例:基本信息
children:[
{
column:"", // 表单项name 提交时的字段名
label:"", // 表单项的提示label
inputType:{
type:"",
// number数字 rich富文本 text文本 date时间控件
// password密码框 textarea多行文本
// select下拉框 image图片上传 file文件上传
// 二级联动,根据不同项目初期定稿 例:
// 街镇联动 streetAndRoad
// 后端读到街镇联动,自动加入 street_id road_id 字段
// 前端读到街镇联动,自动加入 街镇联动的下拉框,接口定稿
format:"",
// date搭配字段 时间格式的限制
// YYYY-MM/YYYY-MM-dd/YYYY-MM-dd HH:II:SS
option:{
// select搭配字段
type:"",
// static静态 link外链 foreign表格关联
table:"",
// 表格关联搭配字段 关联表
label:"",
// 表格关联搭配字段 option的value 通常id
value:"", // 表格关联搭配字段 option显示的字段
url:"", // 外链搭配字段 接口地址
options:[ // option显示数组
{label:"",value:""}
]
},
vadidate:{ // 字段验证限制
required:true/false, // 必填
max:"",
// 最大输入数 string长度 number大小 上传数
min:"", // 最小输入数
}
}
}
]
}
},
{
section:{...}
}
]
}
构建效果