Files
swiftadmin/public/static/system/module/formDesign/formDesign.js

2494 lines
76 KiB
JavaScript
Raw Normal View History

2024-07-13 12:53:20 +08:00
// +----------------------------------------------------------------------
// | layui表单设计器 [基于Sortable开发]
// +----------------------------------------------------------------------
// | Copyright (c) 2020-2030 http://www.swiftadmin.net
// +----------------------------------------------------------------------
// | git://github.com/meystack/layui-form-design.git 616550110
// +----------------------------------------------------------------------
// | Author: meystack <coolsec@foxmail.com> Apache 2.0 License Code
// +----------------------------------------------------------------------
layui.define(['form', 'jquery', 'layer', 'admin', 'cascader'], function (exports) {
"use strict";
var $ = layui.$
, form = layui.form
, layer = layui.layer
, admin = layui.admin
, cascader = layui.cascader
//模块名
, MOD_NAME = 'formDesign'
, MOD_INDEX = 'layui_' + MOD_NAME + '_index' //模块索引名
, TAG_NAME = undefined
//外部接口
, MODULE_FORMDESIGN_NAME = {
config: {}
, index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0
//设置全局项
, set: function (options) {
var that = this;
that.config = $.extend({}, that.config, options);
return that;
}
//事件
, on: function (events, callback) {
return layui.onevent.call(this, MOD_NAME, events, callback);
}
}
//操作当前实例
, thisTags = function () {
var that = this
, options = that.config
, id = options.id || that.index;
thisTags.that[id] = that; //记录当前实例对象
return {
config: options
//重置实例
, reload: function (options) {
that.reload.call(that, options);
}
}
}
//字符常量
, STR_ELEM = 'layui-MODULE_FORMDESIGN_NAME', STR_HIDE = 'layui-hide', STR_DISABLED = 'layui-disabled'
, STR_NONE = 'layui-none', STR_EMPTY = ''
, STR_FORMDESIGN = 'formDesign', LAY_FORM_ITEM = 'layui-form-item', LAY_FORM_DIV = '</div>'
, LAY_INLINE_CLASS = 'layui-input-inline', LAY_BLOCK_CLASS = 'layui-input-block'
, LAY_INPUT_INLINE = '<div class="layui-input-inline">', LAY_INPUT_BLOCK = '<div class="layui-input-block">'
, LAY_COMPONENT_MOVE = 'layui-component-move', LAY_COMPONENT_TOOLS = 'layui-component-tools'
//主模板
, TPL_MAIN = ['<div id="tpl_main" class="tpl_main">从左侧拖入组件进行表单设计</div>'].join('')
, TPL_RIGHT_MAIN = ['<div id="tpl_right_main">请点击组件修改属性</div>'].join('')
//构造器
, Class = function (options) {
var that = this;
that.index = ++MODULE_FORMDESIGN_NAME.index;
that.config = $.extend({}, that.config, MODULE_FORMDESIGN_NAME.config, options);
that.render();
};
//默认配置
Class.prototype.config = {
id: null,
data: [], // 当前元素集合
eval: '', // 当前HTML数据
count: 0, // 当前组件总数
state: null, // 当前活动实例
index: [], // 组件分类索引
itemIndex: {}, // 子组件元素索引
master: undefined // 主界面拖拽实例
};
// 重载实例
Class.prototype.reload = function (options) {
var that = this;
// 防止数组深度合并
layui.each(options, function (key, item) {
if (layui._typeof(item) === 'array') delete that.config[key];
});
that.config = $.extend(true, {}, that.config, options);
that.render();
};
// 语言标签
Class.prototype.lang = {
index: "序号",
tag: "组件类型",
label: "标签名",
name: "<font color=\"red\">* </font>字段名",
type: '表单类型',
placeholder: '占位提示',
default: '默认值',
min: '最小', // 当类型为number的时候
max: '最大',
data_min: '最小', // 自动渲染组件
data_max: '最大',
maxlength: '文本长度', // text
lay_verify: '验证规则',
width: '组件宽度',
height: '组件高度',
lay_skin: '样式',
labelhide: '隐藏标签',
labelwidth: '文本宽度',
uploadtype: '上传样式',
readonly: "只读属性",
disabled: "禁用表单",
required: "必填项",
lay_search: '搜索模式',
data_datetype: "日期类型",
options: "选项",
data_maxvalue: "最大值",
data_minvalue: "最小值",
data_dateformat: "显示格式",
data_half: "显示半星",
theme: "皮肤",
data_theme: "主题",
data_color: "颜色",
data_length: "星星个数",
interval: "间隔毫秒",
data_range: '左右面板',
data_step: '步长',
data_input: '输入框',
data_showstep: '显示断点',
data_default: '默认值',
data_value: '选项值',
data_parents: '关联父类',
tips: '文字提示',
size: '文件大小',
data_size: '文件大小',
data_accept: '上传类型',
msg: '消息提示',
offset: '提示位置',
btnsize: '按钮大小',
text: '文本',
textarea: '多行文本',
border: '分割线',
column: '栅格列数',
editorType: '编辑器类型',
}
// 组件属性
Class.prototype.fields = {
input: {
index: '-1',
tag: 'input',
name: '-1',
label: "单行文本",
type: 'text',
placeholder: "请输入",
default: '',
labelwidth: '110',
width: 100,
maxlength: '',
min: 0,
max: 0,
required: false,
readonly: false,
disabled: false,
labelhide: false,
lay_verify: ''
},
textarea: {
index: '-1',
tag: 'textarea',
name: '-1',
label: "多行文本",
placeholder: "请输入",
default: '',
maxlength: '',
labelwidth: 110,
width: 100,
required: false,
readonly: false,
disabled: false,
labelhide: false
},
radio: {
index: '-1',
tag: "radio",
name: '-1',
label: "单选框",
labelwidth: 110,
width: 100,
disabled: false,
labelhide: false,
options: [
{
title: '男',
value: '1',
checked: true,
},
{
title: '女',
value: '0',
checked: false,
}
]
},
checkbox: {
index: '-1',
tag: "checkbox",
name: '-1',
label: "多选框",
lay_skin: 'primary',
labelwidth: 110,
width: 100,
disabled: false,
labelhide: false,
options: [
{
title: '写作',
value: 'write',
checked: true,
},
{
title: '阅读',
value: 'read',
checked: true,
},
{
title: '游戏',
value: 'game',
checked: false,
}
]
},
select: {
index: '-1',
tag: "select",
name: '-1',
label: "下拉框",
labelwidth: 110,
width: 100,
lay_search: false,
disabled: false,
required: false,
labelhide: false,
options: [
{
title: '选项1',
value: '1',
checked: false,
},
{
title: '选项2',
value: '2',
checked: true,
},
{
title: '选项3',
value: '3',
checked: false,
}
]
},
date: {
index: '-1',
tag: "date",
name: '-1',
label: "日期组件",
labelwidth: 110,
width: 100,
data_datetype: "datetime", // year month date time datetime = select
data_dateformat: "yyyy-MM-dd HH:mm:ss",
placeholder: 'yyyy-MM-dd',
data_maxvalue: "9999-12-31",
data_minvalue: "1900-01-01",
data_range: false, // switch
readonly: false,
disabled: false,
required: false,
labelhide: false,
},
colorpicker: {
index: '-1',
tag: "colorpicker",
name: '-1',
label: "颜色选择器",
labelwidth: 110,
width: 100,
disabled: false,
required: false,
labelhide: false,
},
slider: {
index: '-1',
tag: "slider",
name: '-1',
label: "滑块",
labelwidth: 110,
width: 100,
data_max: 100,
data_min: 0,
data_step: 1,
data_default: 10,
data_theme: '#1890ff',
data_input: false,
data_showstep: false,
disabled: false,
labelhide: false,
},
rate: {
index: '-1',
tag: "rate",
name: '-1',
label: "评分",
labelwidth: 110,
width: 100,
data_default: 1,
data_length: 5,
data_half: false,
data_theme: '#1890ff',
readonly: false,
labelhide: false,
},
switch: {
index: '-1',
tag: "switch",
name: '-1',
label: "开关",
labelwidth: 110,
width: 100,
disabled: false,
labelhide: false,
},
cascader: {
index: '-1',
tag: "cascader",
name: '-1',
label: "级联选择器",
data_value: "label", // 默认为标签
labelwidth: 110,
width: 100,
data_parents: true,
labelhide: false
},
editor: {
index: '-1',
tag: "editor",
name: '-1',
label: "编辑器",
editorType: 'lay-editor', // 编辑器类型
labelwidth: 110,
width: 100,
labelhide: false
},
upload: {
index: '-1',
tag: "upload",
name: '-1',
label: "文件上传",
uploadtype: 'file',
labelwidth: 110,
width: 100,
data_size: 102400,
data_accept: 'file', // 文件 音频 视频 images
disabled: false,
required: false,
labelhide: false
},
tags: {
index: '-1',
tag: "tags",
name: '-1',
label: "关键词",
labelwidth: 110,
width: 100,
labelhide: false,
},
json: {
index: '-1',
tag: "json",
name: '-1',
label: "数组组件",
labelwidth: 110,
width: 100,
labelhide: false,
},
tips: {
index: '-1',
tag: "tips",
name: '-1',
msg: '消息提示',
offset: 4,
},
button: {
index: '-1',
tag: "button",
name: '-1',
text: '按钮',
theme: '',
btnsize: '',
},
note: {
index: '-1',
tag: "note",
name: '-1',
textarea: '便签信息',
width: 100,
},
subtraction: {
index: '-1',
tag: "subtraction",
name: '-1',
border: '',
width: 100,
},
space: {
index: '-1',
tag: "space",
name: '-1',
height: 10, // 像素
},
tab: {
index: '-1',
tag: "tab",
name: '-1',
options: [
{
title: '选项1',
value: 'tab1',
checked: true,
},
{
title: '选项2',
value: 'tab2',
checked: false,
},
],
children: [
{
children: []
},
{
children: [],
},
]
},
grid: {
index: '-1',
tag: "grid",
name: '-1',
column: 2,
children: [
{
children: []
},
{
children: [],
},
]
},
};
// 获取组件JSON数据
Class.prototype.getComponentJson = function (name) {
var type = this.fields[name];
try {
return JSON.parse(JSON.stringify(type));
} catch (error) {
console.warn(name + ' is not existing');
}
return type;
}
// 初始化渲染
Class.prototype.render = function () {
var that = this
, options = that.config;
options.id = options.elem.replace('#', '');
// 获取当前元素
var othis = options.elem = $(options.elem);
if (!othis[0]) return;
$('#Propertie').html(TPL_RIGHT_MAIN);
var arrs = ['sort_1', 'sort_2', 'sort_3'];
for (let index = 0; index < arrs.length; index++) {
const element = arrs[index];
const getById = document.getElementById(element);
that.config.index[element] = new Sortable(getById, {
group: {
name: STR_FORMDESIGN,
pull: 'clone',
put: false,
},
sort: false,
animation: 150,
onChoose: function (evt) { }, // 拖动前显示
onAdd: function (evt) { }, // 添加到这里
onEnd: function (evt) { }, // 拖动结束
});
}
// 主要接口
options.master = new Sortable(document.getElementById(options.id), {
group: {
name: STR_FORMDESIGN,
},
animation: 150,
ghostClass: "sortableghost",
chosenClass: "sortablechosen",
swapClass: 'highlight',
filter: function (evt, item) {
if ($(item).hasClass('layui-tab')) {
return true;
}
if ($(item).hasClass('tpl_main')) {
return true;
}
if ($(item).data('type') == 'space') {
return true;
}
return false;
},
onAdd: function (evt) {
// FIX-BUG
if (!options.count) {
evt.newIndex = options.count;
}
var item = evt.item, id = $(item).attr('id');
var data = that.getComponentJson($(item).data('tag'));
if (typeof id != 'undefined') {
data = JSON.parse(JSON.stringify(that.recursiveFindElem(options.data, id)));
that.recursiveDelete(options.data, id);
}
data.index = options.count++;
data.name = data.tag + '_' + data.index;
options.data.splice(evt.newIndex, 0, data);
options.state = data;
that.renderComponent(options.data, $('#' + options.id));
},
onUpdate: function (evt) {
if (evt.to.id == options.id) {
[options.data[evt.newIndex], options.data[evt.oldIndex]] = [options.data[evt.oldIndex], options.data[evt.newIndex]];
}
},
onEnd: function (evt) { }
});
// 查询下当前data的数据信息是否为字符串
if (typeof options.eval == 'string') {
try {
var data = JSON.parse($(options.eval).val());
options.data = data;
options.state = data[0];
options.count = data.length;
that.reloadComponent();
} catch (error) {
othis.append(TPL_MAIN);
// layer.msg('初始化','info');
}
}
else {
othis.append(TPL_MAIN);
}
that.events();
};
//事件
Class.prototype.events = function () {
var that = this, options = that.config;
$('body').on('click', '#formBuilder ul li', function (e) {
var othis = $(this), index = $(othis).index(),
parentId = $(othis).parents('#layui-tab').parent().attr('id');
var element = that.recursiveFindElem(options.data, parentId);
try {
// 切换选项卡状态
for (var key = 0; key < element.options.length; key++) {
var subElem = element.options[key];
if (key == index) {
subElem.checked = true;
} else {
subElem.checked = false;
}
}
} catch (error) { console.log(index, parentId); }
})
// 解析组件属性
$('body').on('click', '#' + options.id + ' .layui-form-item', function (e) {
// 禁止冒泡
// 过滤元素中按钮
if ($(e.toElement).hasClass('layui-btn') == false
&& $(e.toElement).hasClass('layui-upload-file') == false
&& $(e.toElement).parent().hasClass('layui-tab-title') == false) {
e.preventDefault();
e.stopPropagation();
}
var othis = $(this), name = othis.attr('id');
if (typeof name == 'undefined') {
return true;
}
$('div.active').each(function (k, n) {
$(n).removeClass('active');
})
$(othis).addClass('active');
options.state = that.recursiveFindElem(options.data, name);
that.getPropertieValues(options.state);
})
// 复制节点
$('body').on('click', '#' + options.id + ' .layui-icon-picture-fine', function (e) {
var othis = this;
var copyElem = [];
var name = $(othis).parents('.' + LAY_FORM_ITEM).attr('id');
var cycleElem = function (array, name) {
for (let index = 0; index < array.length; index++) {
const element = array[index];
if (element.name == name) {
copyElem = JSON.parse(JSON.stringify(element));
copyElem.index = options.count++;;
copyElem.name = copyElem.tag + '_' + copyElem.index;
// 节点插入
array.splice(index + 1, 0, copyElem);
break;
}
if (typeof element.children != 'undefined'
&& element.children.length) {
var subElem = element.children;
for (let i = 0; i < subElem.length; i++) {
if (subElem[i].children.length) {
var item = cycleElem(subElem[i].children, name);
if (item != [] && typeof item != 'undefined') {
return item;
}
}
}
}
}
}
cycleElem(options.data, name);
options.state = copyElem;
// 复制BUG 需要去重
var nodes = [];
var randRepeat = function (array) {
for (let index = 0; index < array.length; index++) {
var element = array[index];
if (nodes.indexOf(element.name) != -1) {
element.name = element.name + 't';
}
nodes.push(element.name);
if (typeof element.children != 'undefined'
&& element.children.length) {
var subElem = element.children;
for (let i = 0; i < subElem.length; i++) {
if (subElem[i].children.length) {
randRepeat(subElem[i].children);
}
}
}
}
}
randRepeat(options.data);
that.reloadComponent();
})
// 删除节点
$('body').on('click', '#' + options.id + ' .layui-icon-delete', function (e) {
var othis = this;
layer.confirm('确定要删除元素吗?', {
}, function (index, layero) {
var name = $(othis).parents('.' + LAY_FORM_ITEM).attr('id');
// 点击删除后,返回为未定义
options.state = that.recursiveDelete(options.data, name) || [];
that.reloadComponent();
layer.close(index);
})
})
// 当前EVAL存在则进行数据赋值
$('body').on('click', function (e) {
try {
if ($(options.eval).length) {
$(options.eval).val(JSON.stringify(options.data));
}
} catch (error) {
console.warn(error);
}
})
// 编辑标签
$('body').on('keyup', '#Propertie #label', function (e) {
$('#' + options.state.name).find('label:eq(0)').text($(this).val());
var element = that.recursiveFindElem(options.data, options.state.name);
element.label = $(this).val();
})
// 占位提示
$('body').on('keyup', '#Propertie #placeholder', function (e) {
$('#' + options.state.name).find(options.state.tag + ':eq(0)').prop('placeholder', $(this).val());
var element = that.recursiveFindElem(options.data, options.state.name);
element.placeholder = $(this).val();
})
// layui-change 更新后操作
// layui-keyup 键入后操作
$('body').on('change', '#Propertie .layui-change', function (e) {
var othis = this;
var oid = $(othis).attr('id');
var oval = $(othis).val();
if (oid == 'name') {
var existing = that.recursiveFindElem(options.data, oval);
if (oval.length <= 1 || existing) {
layer.msg('Logo is shorter or already exist', 'error');
return false;
}
}
var element = that.recursiveFindElem(options.data, options.state.name);
try {
if (typeof element[oid] != 'undefined') {
element[oid] = oval;
}
} catch (error) {
console.log('undefined element');
}
that.reloadComponent();
})
// 图片上传类型修改
$('body').on('click', '#Propertie #uploadtype', function (e) {
var othis = this;
var oval = $(othis).attr('value');
var element = that.recursiveFindElem(options.data, options.state.name);
try {
element.uploadtype = oval;
} catch (error) {
console.log('undefined element');
}
$('#Propertie #uploadtype').each(function (i, e) {
$(e).prop('class', 'layui-badge layui-bg-gray');
})
$(othis).prop('class', 'layui-badge layui-bg-blue');
that.reloadComponent();
})
// 级联选择器类型
$('body').on('click', '#Propertie #data_value', function (e) {
var othis = this;
var oval = $(othis).attr('value');
var element = that.recursiveFindElem(options.data, options.state.name);
try {
element.data_value = oval;
} catch (error) {
console.log('undefined element');
}
$('#Propertie #data_value').each(function (i, e) {
$(e).prop('class', 'layui-badge layui-bg-gray');
})
$(othis).prop('class', 'layui-badge layui-bg-blue');
that.reloadComponent();
})
// 全局SELECT属性
form.on('select(componentSelected)', function (data) {
var field = $(data.elem).data('field')
, element = that.recursiveFindElem(options.data, options.state.name);
if (!data.value) {
return layer.error('请选择字段');
}
try {
if (element.tag === 'grid') {
var children = element.children;
var length = children.length;
if (data.value > length) {
// 添加元素
children.push({ children: [] });
} else if (data.value < length) {
var d = length - data.value;
for (var i = 0; i < children.length; i++) {
if (d <= 0) {
break;
}
// 当前无子类
if (!children[i].children.length) {
d--;
children.splice(i, 1);
}
}
// 如果过滤完还有的话
// 则还需要循环下
if (d >= 1) {
while (d) {
d--;
children.splice(d, 1);
}
}
}
}
element[field] = data.value;
if (field === 'name') {
element['label'] = tableInfo[data.value];
}
} catch (error) {
console.warn('undefined element');
}
that.reloadComponent();
})
// 全局组件状态
form.on('switch(componentChecked)', function (data) {
let field = $(this).data('field')
, element = that.recursiveFindElem(options.data, options.state.name);
try {
// 过滤主题
if (field === 'lay_skin') {
element.lay_skin = data.elem.checked ? 'primary' : STR_EMPTY;
} else {
element[field] = data.elem.checked ? true : false;
}
} catch (error) {
console.log('undefined element');
}
that.reloadComponent();
})
// 其他验证规则
form.on('checkbox(verify)', function (data) {
that.setInputVerify(data.elem.checked, $(this).val());
let element = that.recursiveFindElem(options.data, options.state.name);
let verify = element.lay_verify === '' ? [] : element.lay_verify.split('|');
if (data.elem.checked) {
verify.push(data.value);
} else {
verify.splice(data.value, 1);
}
element.lay_verify = verify.join('|');
})
// 添加选项
$('body').on('click', 'button.layui-add-option', function (click) {
that.checkSelectRadio(options.state.tag, $('#Propertie #name').val(), null);
})
// 编辑radio checkbox 组件信息
$('body').on('change', '#form-options input', function (click) {
var othis = $(this), parentIndex = $(othis).parent('.' + LAY_INLINE_CLASS).index(),
selfIndex = $(othis).index() - 1, val = $(othis).val(), field = $('#field').val();
var element = that.recursiveFindElem(options.data, options.state.name);
for (const key in element.options) {
if (key == parentIndex) {
var item = element.options[key];
if (selfIndex) {
item.value = val;
} else {
item.title = val;
}
}
}
that.reloadComponent();
})
// 删除选项
$('body').on('click', '#form-options .layui-icon-subtraction', function (click) {
that.checkSelectRadio(options.state.tag, $('#Propertie #name').val(), $(this).prev().val(), false);
})
// 预览表单
$('body').on('click', '.layui-btn-component', function (e) {
var othis = this, subHtml = STR_EMPTY,
formName = $('#formName').val(),
html = '<div class="layui-fluid"><form id="' + formName + '" class="layui-form">';
html += $('#formBuilder').html();
html += '</form></div>';
html = html.replace(/<ol[^>]+>/g, '').replace(/<\/ol>/g, '');
html = html.replace(/<div class="layui-component-tools">.*?<\/div>/g, '');
// 获取提交代码
subHtml = html.substring(0, html.indexOf('</form>'));
subHtml += '<div class="layui-footer layui-form-item layui-center">';
subHtml += '<button class="layui-btn layui-btn-primary" type="button" sa-event="closeDialog">取消</button>';
subHtml += '<button class="layui-btn lay-submit" onclick="javascript:layer.msg(\'提交测试\');" type="button" >提交</button>';
subHtml += '</div>';
subHtml += html.substring(html.indexOf('</form>'));
html = subHtml;
var formWidth = $('#formWidth').val();
if (!formWidth) {
formWidth = '65%';
}
var formHeight = $('#formHeight').val();
if (!formHeight) {
formHeight = '65%';
}
layer.open({
type: 1,
title: '预览表单 - ' + formName,
maxmin: true,
area: [formWidth, formHeight],
content: html,
success: function (index, layero) {
// 暂时只渲染layui元素
// 剩下的需要在自身页面进行渲染
form.render();
}
})
})
// 清空表单设计
$('body').on('click', '.layui-form-clear', function (e) {
layer.confirm('确定要清空表单设计吗?', {
}, function (index, layero) {
options.data = [];
$('#' + options.id).html(TPL_MAIN);
$('#Propertie').html(TPL_RIGHT_MAIN);
layer.close(index);
})
})
// 导出表单
$('body').on('click', '.layui-btn-export', function (e) {
$('#json-code').val(JSON.stringify(options.data, null, 4));
$('#import-code').addClass(STR_HIDE);
$('#copy-code').removeClass(STR_HIDE);
layer.open({
type: 1
, offset: '130px'
, content: $('.layui-htmlview')
, area: ['800px', '660px']
, shade: false
, resize: false
, success: function (layero, index) { }
});
})
// 复制代码
$('body').on('click', '#copy-code', function (e) {
var data = document.getElementById("json-code");
data.select();
if (document.execCommand('copy')) {
layer.msg('复制成功');
}
layer.closeAll();
})
// 导入表单
$('body').on('click', '.layui-btn-import', function (e) {
$('#copy-code').addClass(STR_HIDE);
$('#import-code').removeClass(STR_HIDE);
layer.open({
type: 1
, offset: '130px'
, content: $('.layui-htmlview')
, area: ['800px', '660px']
, shade: false
, resize: false
, success: function (layero, index) {
$('body').on('click', '#import-code', function (e) {
try {
var data = $('#json-code').val();
options.data = JSON.parse(data);
options.state = options.data[0];
that.reloadComponent();
layer.close(index);
} catch (error) {
layer.msg('缺少参数', 'error');
}
})
}
});
})
// 加载表单
$('body').on('click', '.button--text', function (e) {
var id = $(this).data('id');
layer.confirm('是否加载这个模板?加载后会覆盖设计器当前表单', function (index) {
$(layer).find('.layui-layer-btn0').css('pointer-events', 'none');
$.ajax({
url: '//api.swiftadmin.net/form/read?id=' + id,
type: "get",
data: [],
success: function (res) {
if (res.code == 200) {
options.data = JSON.parse(res.data);
options.state = options.data[0];
that.reloadComponent();
}
}
});
layer.close(index);
})
})
};
/**
* 增删组件选项
* @param {*} tag
* @param {*} name
* @param {*} value
* @param {*} action
*/
Class.prototype.checkSelectRadio = function (tag, name, value, action = true) {
var options = this.config;
var element = this.recursiveFindElem(options.data, name);
if (typeof element === 'undefined') {
return layer.error('请选择字段后再操作');
}
if (action) {
if (typeof element.options === 'undefined') {
return layer.error('当前组件无选项');
}
element.options.splice(element.options.length, 0, {
title: '选项' + element.options.length,
value: 'value',
checked: false
});
if (element.tag == 'tab') {
element.children.push({ children: [] });
}
} else {
for (const key in element.options) {
var item = element.options[key];
if (item.value == value) {
element.options.splice(key, 1);
if (element.tag == 'tab') {
element.children.splice(key, 1);
}
break;
}
}
}
this.reloadComponent();
}
/**
* 设置表单验证规则
* @param {*} checked
* @param {*} field
*/
Class.prototype.setInputVerify = function (checked = false, field = '') {
var elem = this.config.state.name;
var rules = $('#' + elem).find('input:eq(0)').attr('lay-verify') || [];
if (typeof rules != 'object') {
rules = rules.split('|');
}
if (checked) {
rules[rules.length] = field;
$('#' + elem).find('input:eq(0)').attr('lay-verify', rules.join('|'));
} else {
for (let index = 0; index < rules.length; index++) {
const el = rules[index];
if (el == field) {
rules.splice(index, 1);
}
}
if (rules.length) {
$('#' + elem).find('input:eq(0)').attr('lay-verify', rules.join('|'));
}
else {
$('#' + elem).find('input:eq(0)').removeAttr('lay-verify');
}
}
}
/**
* 获取HTML代码
* @param {*} lable
* @param {*} id
* @param {*} value
* @param {*} classed
*/
Class.prototype.getPropertieHtml = function (lable, id, value, classed = '', attr = '') {
var proHtml = '<div class="' + LAY_FORM_ITEM + '">';
if (lable) {
proHtml += '<label class="layui-form-label">' + lable + '</label>';
}
proHtml += LAY_INPUT_INLINE;
proHtml += '<input type="text"';
if (id) {
proHtml += 'id="' + id + '"';
}
proHtml += 'class="layui-input ' + classed + '"';
proHtml += 'value="' + value + '" ' + attr + '>';
proHtml += LAY_FORM_DIV + LAY_FORM_DIV;
return proHtml;
}
/**
* 模板碎片
* @param {*} lable
* @returns
*/
Class.prototype.getPropertieDebris = function (lable, hide = '') {
var proHtml = '<div class="' + LAY_FORM_ITEM + ' ' + hide + '">';
if (lable) {
proHtml += '<label class="layui-form-label">' + lable + '</label>';
}
proHtml += LAY_INPUT_INLINE;
return proHtml;
}
/**
* 获取标签文字
* @param {*} field
*/
Class.prototype.getLang = function (field) {
if (typeof this.lang[field] != 'undefined') {
return this.lang[field];
}
else {
return field + ' undefined';
}
}
/**
* 获取表单属性
* @param {*} elem
* @param {*} type
*/
Class.prototype.getPropertieValues = function (data, type) {
var that = this,
options = that.config,
optionsHtml = STR_EMPTY;
for (const key in data) {
// 过滤index
if (key == 'index') {
continue;
}
var value = data[key];
if (key == 'options' || key == 'children') {
// 过滤信息
}
else {
optionsHtml += that.getPropertieDebris(that.getLang(key));
}
switch (key) {
case 'tag':
optionsHtml += '<input class="layui-input layui-disabled" disabled value="' + value + '" data-type="' + key + '">';
break;
case 'label':
case 'placeholder': // 标签和描述占位符
optionsHtml += '<input class="layui-input layui-keyup" value="' + value + '" id="' + key + '">';
break;
case 'name':
if (typeof tableInfo !== undefined) {
if (data.tag == 'tab') {
optionsHtml += '<input class="layui-input layui-disabled" value="' + value + '" id="name">';
} else {
optionsHtml += '<select id="name" lay-filter="componentSelected" data-field="name" lay-search>';
// 初始化下拉列表
optionsHtml += '<option value="">请选择</option>';
for (const item in tableInfo) {
optionsHtml += '<option value="' + item + '"';
if (value === item) {
optionsHtml += 'selected';
}
optionsHtml += '>' + item + '</option>';
}
optionsHtml += '</select>';
}
}
break;
case 'msg':
case 'text':
case 'color':
case 'default':
case 'data_default':
case 'data_theme':
optionsHtml += '<input class="layui-input layui-change" value="' + value + '" id="' + key + '">';
break;
case 'type':
optionsHtml += '<select lay-filter="componentSelected" data-field="type">';
var inputType = [
{
title: '文本',
value: 'text',
},
{
title: '密码',
value: 'password',
},
{
title: '数字',
value: 'number',
},
];
for (let index = 0; index < inputType.length; index++) {
const element = inputType[index];
optionsHtml += '<option value="' + element.value + '"';
if (element.value === data.type) {
optionsHtml += 'selected';
}
optionsHtml += '>' + element.title + '</option>';
}
optionsHtml += '</select>';
break;
case 'data_datetype':
optionsHtml += '<select lay-filter="componentSelected" data-field="data_datetype" >';
var date_types = [
{
title: '默认',
value: 'date',
},
{
title: '年选择器',
value: 'year',
},
{
title: '年月选择器',
value: 'month',
},
{
title: '时间选择器',
value: 'time',
},
{
title: '日期时间选择器',
value: 'datetime',
},
];
for (var index in date_types) {
const element = date_types[index];
optionsHtml += '<option value="' + element.value + '"';
if (element.value == data.data_datetype) {
optionsHtml += 'selected';
}
optionsHtml += '>' + element.title + '</option>';
}
optionsHtml += '</select>';
break;
case 'data_dateformat':
optionsHtml += '<select lay-filter="componentSelected" data-field="data_dateformat" >';
var dateformat = ['yyyy-MM-dd HH:mm:ss', 'yyyy年MM月dd日', 'dd/MM/yyyy', 'yyyyMM', 'H点M分', 'yyyy-MM', 'yyyy年M月d日H时m分s秒'];
for (var index in dateformat) {
const element = dateformat[index];
optionsHtml += '<option value="' + element + '"';
if (element == data.data_dateformat) {
optionsHtml += 'selected';
}
optionsHtml += '>' + element + '</option>';
}
optionsHtml += '</select>';
break;
case 'offset':
var attrs = { 1: '上', 2: '左', 3: '下', 4: '右' };
optionsHtml += '<select lay-filter="componentSelected" data-field="offset" >';
for (const key in attrs) {
optionsHtml += '<option value="' + key + '" ';
if (key == data.offset) {
optionsHtml += 'selected';
}
optionsHtml += '>' + attrs[key] + '</option>';
}
optionsHtml += '</select>';
break;
case 'theme':
var attrs = {
'': '默认',
'layui-btn-normal': '百搭',
'layui-btn-warm': '暖色',
'layui-btn-danger': '警告',
'layui-btn-disabled': '禁用'
};
optionsHtml += '<select lay-filter="componentSelected" data-field="theme">';
for (const key in attrs) {
optionsHtml += '<option value="' + key + '" ';
if (key == data.theme) {
optionsHtml += 'selected';
}
optionsHtml += '>' + attrs[key] + '</option>';
}
optionsHtml += '</select>';
break;
case 'btnsize':
var attrs = {
'': '默认按钮',
'layui-btn-lg': '大型按钮',
'layui-btn-sm': '小型按钮',
'layui-btn-xs': '迷你按钮',
'layui-btn-fluid': '流体按钮'
};
optionsHtml += '<select lay-filter="componentSelected" data-field="btnsize">';
for (const key in attrs) {
optionsHtml += '<option value="' + key + '" ';
if (key == data.btnsize) {
optionsHtml += 'selected';
}
optionsHtml += '>' + attrs[key] + '</option>';
}
optionsHtml += '</select>';
break;
case 'data_accept':
optionsHtml += '<select lay-filter="componentSelected" data-field="data_accept">';
var arr = [
{
title: '文件',
value: 'file',
},
{
title: '视频',
value: 'video',
},
{
title: '音频',
value: 'audio',
},
{
title: '图片',
value: 'images',
}
];
for (var index in arr) {
const element = arr[index];
optionsHtml += '<option value="' + element.value + '"';
if (element.value == data.data_accept) {
optionsHtml += 'selected';
}
optionsHtml += '>' + element.title + '</option>';
}
optionsHtml += '</select>';
break;
case 'max':
case 'min':
case 'size':
case 'height':
case 'data_max':
case 'data_min':
case 'data_step':
case 'data_size':
optionsHtml += '<input type="number" min="0" class="layui-input layui-change" value="' + value + '" id="' + key + '" >';
break;
case 'data_maxvalue':
case 'data_minvalue':
optionsHtml += '<input class="layui-input layui-change" value="' + value + '" id="' + key + '" >';
break;
case 'width': // 滑块操作
optionsHtml += '<div data-min="20" data-max="100" id="' + key + '" class="layui-sliders" data-value="' + value + '"></div>';
break;
case 'labelwidth':
optionsHtml += '<div data-min="60" data-max="255" id="' + key + '" class="layui-sliders" data-value="' + value + '"></div>';
break;
case 'maxlength':
optionsHtml += '<input type="number" min="1" id="maxlength" class="layui-input layui-change" value="' + (value ? value : 255) + '">';
break;
case 'minmax':
for (const key in data.minmax) {
var num = data.minmax[key];
optionsHtml += '<input id="' + num.title + '" type="number" class="layui-input layui-minmax" value="' + num.value + '">';
if (key == 0) {
optionsHtml += '<em>-</em>';
}
}
break;
case 'lay_skin':
case 'required':
case 'readonly':
case 'disabled':
case 'labelhide':
case 'lay_search':
case 'data_range':
case 'data_showstep':
case 'data_half':
case 'data_input':
case 'data_parents':
optionsHtml += '<input type="checkbox" lay-skin="switch" lay-filter="componentChecked" ';
if (data[key]) {
optionsHtml += 'checked=""';
}
optionsHtml += 'data-field="' + key + '">';
break;
case 'data_value':
var type = ['label', 'value'];
for (const index in type) {
optionsHtml += ' <span class="layui-badge ';
if (type[index] == data.data_value) {
optionsHtml += 'layui-bg-blue';
} else {
optionsHtml += 'layui-bg-gray';
}
optionsHtml += '" id="' + key + '" value="' + type[index] + '" >' + type[index] + '</span>';
}
break;
case 'lay_verify':
var verify = [
{
title: '手机',
value: 'phone'
},
{
title: '邮箱',
value: 'email'
},
{
title: '网址',
value: 'url'
},
{
title: '数字',
value: 'number'
},
{
title: '日期',
value: 'date'
},
{
title: '身份证',
value: 'identity'
},
];
for (const key in verify) {
var check = verify[key];
optionsHtml += '<input type="checkbox" lay-skin="primary" lay-filter="verify" value="' + check.value + '"';
optionsHtml += 'title="' + check.title + '"';
if (data.lay_verify.indexOf(check.value) != -1) {
optionsHtml += 'checked=""';
}
optionsHtml += '>';
}
break;
case 'uploadtype':
var type = ['file', 'images', 'multiple'];
for (const index in type) {
optionsHtml += ' <span class="layui-badge ';
if (type[index] == data.uploadtype) {
optionsHtml += 'layui-bg-blue';
} else {
optionsHtml += 'layui-bg-gray';
}
optionsHtml += '" id="' + key + '" value="' + type[index] + '" >' + type[index] + '</span>';
}
break;
case 'maxlength':
case 'data_length':
optionsHtml += '<input type="number" min="1" id="' + key + '" class="layui-input layui-change" value="' + value + '">';
break;
case 'textarea':
optionsHtml += '<textarea class="layui-textarea layui-change" id="' + key + '" >' + value + '</textarea>';;
break;
case 'border':
var attrs = {
'': '默认',
'layui-border-red': '赤色',
'layui-border-orange': '橙色',
'layui-border-green ': '墨绿色',
'layui-border-cyan': '青色',
'layui-border-blue': '蓝色',
'layui-border-black': '黑色',
};
optionsHtml += '<select lay-filter="componentSelected" data-field="border">';
for (const key in attrs) {
optionsHtml += '<option value="' + key + '" ';
if (key == data.border) {
optionsHtml += 'selected';
}
optionsHtml += '>' + attrs[key] + '</option>';
}
optionsHtml += '</select>';
break;
case 'editorType':
var attrs = {
'lay-editor': 'tinymce',
'lay-markdown': 'markdown',
};
optionsHtml += '<select lay-filter="componentSelected" data-field="editorType">';
for (const key in attrs) {
optionsHtml += '<option value="' + key + '" ';
if (key == data.editorType) {
optionsHtml += 'selected';
}
optionsHtml += '>' + attrs[key] + '</option>';
}
optionsHtml += '</select>';
break;
case 'options':
optionsHtml += this.formOptionHeader();
for (const key in data.options) {
var option = data.options[key];
optionsHtml += LAY_INPUT_INLINE;
optionsHtml += '<i class="layui-icon layui-icon-slider"></i>';
optionsHtml += '<input class="layui-input" value="' + option.title + '" >';
optionsHtml += '<input class="layui-input" value="' + option.value + '" >';
optionsHtml += '<i class="layui-icon layui-icon-subtraction"></i>';
optionsHtml += LAY_FORM_DIV;
}
optionsHtml += '<div class="layui-input-inline layui-inlioc">';
optionsHtml += '<button type="button" class="layui-btn layui-btn-xs layui-add-option">添加</button>';
optionsHtml += LAY_FORM_DIV
optionsHtml += LAY_FORM_DIV + LAY_FORM_DIV;
break;
case 'column':
var attrs = [2, 3, 4];
optionsHtml += '<select lay-filter="componentSelected" data-field="column">';
for (const i in attrs) {
var val = attrs[i];
optionsHtml += '<option value="' + val + '" ';
if (val == data.column) {
optionsHtml += 'selected';
}
optionsHtml += '>' + val + '</option>';
}
optionsHtml += '</select>';
break;
default:
break;
}
optionsHtml += '</div></div>';
}
$('#Propertie').html(optionsHtml);
form.render(null, 'Propertie');
// 最大化时间回调操作
var datetime = $('#data_maxvalue, #data_minvalue');
datetime.each(function (index, obj) {
layui.laydate.render({
elem: this
, type: 'date'
, format: 'yyyy-MM-dd'
, done: function (value, date, endDate) {
var element = that.recursiveFindElem(options.data, options.state.name);
try {
element[$(obj).attr('id')] = value;
} catch (error) {
console.log(error);
}
that.reloadComponent();
}
});
})
// 选项拖动接口
if ($('#Propertie #form-options').length) {
new Sortable(document.getElementById('form-options'), {
handle: '.layui-icon-slider',
animation: 150,
onAdd: function (evt) { },
onUpdate: function (evt) {
var element = that.recursiveFindElem(options.data, options.state.name);
try {
var op = element.options;
[op[evt.newIndex], op[evt.oldIndex]] = [op[evt.oldIndex], op[evt.newIndex]];
// 是否内容区域也需要编辑?
that.reloadComponent();
} catch (error) {
// 捕获异常
console.warn(error);
}
},
onEnd: function (evt) { }
});
}
layui.each($(".layui-sliders"), function (key, elem) {
var othat = $(this),
obj = othat.attr('id'),
val = othat.data('value'),
min = othat.data('min') || 10,
max = othat.data('max') || 100,
theme = othat.data('theme') || '#1890ff';
layui.slider.render({
elem: elem
, min: min
, max: max
, input: true
, theme: theme
, value: val
, step: 2
, change: function (value) {
if (value <= min || isNaN(value)) {
value = min;
}
var element = that.recursiveFindElem(options.data, options.state.name);
try {
element[obj] = value
} catch (error) {
console.warn(error);
}
that.reloadComponent();
}
})
})
}
/**
* 获取选项表头
* @param {*} options
* @returns
*/
Class.prototype.formOptionHeader = function (options = 'form-options') {
var _options = '<fieldset id="layui-elem-field" class="layui-elem-field layui-field-title">';
_options += '<legend>选项</legend>';
_options += ' </fieldset>';
_options += '<div id="' + options + '" class="' + LAY_FORM_ITEM + '">';
return _options;
}
/**
* 获取工具栏HTML
* @returns
*/
Class.prototype.getToolsHtml = function () {
var tools = '<div class="' + LAY_COMPONENT_TOOLS + '">';
tools += ' <i class="layui-icon layui-icon-picture-fine" title="复制" ></i>';
tools += ' <i class="layui-icon layui-icon-delete" title="删除"></i>';
tools += LAY_FORM_DIV;
return tools;
}
// 获取组件代码
Class.prototype.renderComponent = function (data, elem) {
var that = this,
outerHTML = STR_EMPTY,
options = that.config;
/**
* 代码预处理
* 编辑器需要预先移除节点
*/
$(elem).find('.editorsrv').each(function (i, n) {
$(n).parent().find('.tox-tinymce').remove();
$(n).remove();
});
elem.empty(STR_EMPTY);
// 循环渲染表单
for (let index = 0; index < data.length; index++) {
var element = data[index];
outerHTML = that.renderComponentItem[element.tag].render(element);
elem.append($(outerHTML).append(that.getToolsHtml()).prop("outerHTML"));
switch (element.tag) {
case 'input':
break;
case 'date':
admin.components.datetime();
break;
case 'colorpicker':
admin.components.colorpicker();
break;
case 'slider':
admin.components.slider();
break;
case 'rate':
admin.components.rate();
break;
case 'upload':
admin.components.upload();
break;
case 'tags':
admin.components.tags();
break;
case 'cascader':
admin.components.cascader('input#' + element.name);
break;
case 'editor':
if (element.editorType === 'lay-editor') {
tinymce.init({
selector: '#' + element.name + '_tiny',
language: 'zh_CN',
})
} else {
let elem = '#' + element.name + '_tiny';
let height = $(elem).data('height') || '400px';
let _id = 'markdown_' + Math.round(Math.random() * 36);
$(elem).after('<div id="' + _id + '" ></div>');
new Cherry({
id: _id,
toolbars: {
theme: 'light',
float: false,
bubble : false // array or false
},
editor: {
height: height,
defaultModel: 'editOnly',
}
});
}
break;
case 'tab':
case 'grid':
var children = $('#' + element.name + ' .children');
var childItem = []
$.each(children, function (index, item) {
that.gridtabSortable(item);
childItem[index] = item;
})
// 递归渲染里面的子元素
$.each(element.children, function (index, item) {
if (item.children.length) {
that.renderComponent(item.children, $(childItem[index]));
}
})
break;
default:
break;
}
if (typeof options.state != 'undefined') {
that.getPropertieValues(options.state);
} else if (options.data.length) {
options.state = options.data[options.data.length - 1];
that.getPropertieValues(options.state);
}
}
// 取消其他活动选项
$('#' + options.id + ' div.active').each(function (k, n) {
$(n).removeClass('active');
})
if (typeof options.state != undefined) {
$('div#' + options.state.name).addClass('active');
}
// 渲染表单
form.render();
}
/**
* 重新渲染组件
*/
Class.prototype.reloadComponent = function () {
this.renderComponent(this.config.data, $('#' + this.config.id));
}
/**
* 是否隐藏标签
* @param {*} labelhide
* @param {*} data
* @returns
*/
var getBeforeLabel = function (labelhide = false, data) {
var labelHtml = '<label class="layui-form-label';
if (labelhide) {
labelHtml += ' ' + 'layui-hide';
}
labelHtml += '"';
if (data.labelwidth && data.labelwidth != 110) {
labelHtml += 'style="width:' + data.labelwidth + 'px;"';
}
labelHtml += '>';
if (data.required) {
labelHtml += '<font color="red">* </font>';
}
labelHtml += data.label + '</label>';
labelHtml += '<div class="' + LAY_BLOCK_CLASS + '"';
var styleCSS = [];
if (labelhide) {
styleCSS.push('margin-left:0');
}
// 这里存在一个BUG应该是如果标签隐藏了那么就不需要再次去增加就可以了这里只是一个MLF的像素
if (data.labelwidth && data.labelwidth != 110) {
// 数据偏移需要增加30
var labelwidth = Number(data.labelwidth) + 30;
styleCSS.push('margin-left:' + labelwidth + 'px');
}
styleCSS = styleCSS.join(';');
if (styleCSS) {
labelHtml += 'style="' + styleCSS + '"';
}
labelHtml += '>';
return labelHtml;
}
/**
* ITEM前置模板
* @param {IETM} data
* @returns
*/
var getBeforeItem = function (data) {
var _BeforeItem = '<div id="' + data.name + '" class="layui-form-item" data-index="' + data.index + '" data-tag="' + data.tag + '"';
if (data.width && data.width != 100) {
_BeforeItem += 'style="width:' + data.width + '%"';
}
_BeforeItem += '>';
return _BeforeItem;
}
// 渲染组件HTML
Class.prototype.renderComponentItem = {
input: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input type="' + data.type + '" name="' + data.name + '" class="layui-input"';
html += 'value="' + data.default + '" placeholder="' + data.placeholder + '"';
// 限定数字格式
if (data.type == 'number') {
if (data.min) {
html += 'min="' + data.min + '"';
}
if (data.max) {
html += 'max="' + data.max + '"';
}
} else {
if (data.maxlength) {
html += 'maxlength="' + data.maxlength + '"';
}
}
// 禁用只读表单
if (data.readonly) {
html += 'readonly=""';
}
if (data.disabled) {
html += 'disabled=""';
}
if (data.lay_verify) {
html += 'lay-verify="' + data.lay_verify + '"';
}
html += '>';
html += '</div></div>';
return html;
},
},
textarea: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<textarea name="' + data.name + '" class="layui-textarea" placeholder="' + data.placeholder + '"';
if (data.required) {
html += 'lay-verify="required"';
}
if (data.readonly) {
html += 'readonly=""';
}
if (data.disabled) {
html += 'disabled=""';
}
if (data.maxlength && data.maxlength != 255) {
html += 'maxlength="' + data.maxlength + '"';
}
html += '></textarea>';
html += '</div></div>';
return html;
}
},
radio: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
if (data.options.length) {
for (let index = 0; index < data.options.length; index++) {
var elem = data.options[index];
html += '<input type="radio" name="' + data.name + '" value="' + elem.value + '" title="' + elem.title + '"';
if (elem.checked) {
html += 'checked=""';
}
if (data.disabled) {
html += 'disabled=""';
}
html += '>';
}
}
html += '</div></div>';
return html;
}
},
checkbox: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
if (data.options.length) {
for (let index = 0; index < data.options.length; index++) {
var elem = data.options[index];
var name = data.name;
if (data.name) {
name += '[' + elem.value + ']';
}
html += '<input type="checkbox" name="' + name + '" lay-skin="' + data.lay_skin + '" value="' + elem.value + '" title="' + elem.title + '"';
if (elem.checked) {
html += 'checked=""';
}
if (data.disabled) {
html += 'disabled=""';
}
html += '>';
}
}
html += '</div></div>';
return html;
}
},
select: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<select name="' + data.name + '"';
if (data.searchMode) {
html += 'lay-search=""';
}
if (data.required) {
html += 'lay-verify="required"';
}
if (data.disabled) {
html += 'disabled=""';
}
html += '>';
html += '<option value="">请选择</option>';
if (data.options.length) {
for (let index = 0; index < data.options.length; index++) {
var elem = data.options[index];
html += '<option value="' + elem.value + '">' + elem.title + '</option>';
}
}
html += '</select>';
html += '</div></div>';
return html;
}
},
date: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input type="text" name="' + data.name + '" class="layui-input" placeholder="' + data.placeholder + '" lay-datetime=""';
if (data.data_range) {
html += 'data-range="true"';
}
if (data.data_datetype) {
html += 'data-datetype="' + data.data_datetype + '"';
}
if (data.data_dateformat) {
html += 'data-dateformat="' + data.data_dateformat + '"';
}
if (data.data_maxvalue) {
html += 'data-maxvalue="' + data.data_maxvalue + '"';
}
if (data.data_minvalue) {
html += 'data-minvalue="' + data.data_minvalue + '"';
}
if (data.required) {
html += 'lay-verify="required"';
}
if (data.disabled) {
html += 'disabled=""';
}
if (data.readonly) {
html += 'readonly=""';
}
html += '>';
html += '</div></div>';
return html;
}
},
colorpicker: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input class="layui-input layui-hide ' + data.name + '" name="' + data.name + '"/>';
html += '<div lay-colorpicker="' + data.name + '" data-value="' + data.default + '"></div>';
html += '</div></div>';
return html;
}
},
slider: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input class="layui-input layui-hide ' + data.name + '" name="' + data.name + '"/>';
html += '<div class="lay-slider" lay-slider="slider" data_default="' + data.data_default + '" data-theme="' + data.data_theme + '"';
if (data.data_showstep) {
html += 'data-showstep="' + data.data_showstep + '"';
}
if (data.data_step) {
html += 'data-step="' + data.data_step + '"';
}
if (data.data_max) {
html += 'data-max="' + data.data_max + '"';
}
if (data.data_min) {
html += 'data-min="' + data.data_min + '"';
}
if (data.data_input) {
html += 'data-input="' + data.data_input + '"';
}
if (data.disabled) {
html += 'disabled=""';
}
if (data.readonly) {
html += 'readonly=""';
}
html += '></div>';
html += '</div></div>';
return html;
}
},
rate: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input class="layui-input layui-hide ' + data.name + '" name="' + data.name + '"/>';
html += '<div lay-rate="' + data.name + '" data-default="' + data.data_default + '" data-class="' + data.name + '" data-theme="' + data.data_theme + '"';
if (data.data_half) {
html += 'data-half="true"';
}
if (data.data_length) {
html += 'data-length="' + data.data_length + '"';
}
if (data.readonly) {
html += 'data-readonly="true"';
}
html += '></div>';
html += '</div></div>';
return html;
}
},
switch: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input type="checkbox" name="' + data.name + '" value="1" lay-skin="switch" />';
html += '</div></div>';
return html;
}
},
cascader: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input id="' + data.name + '" class="layui-input" data-parents="' + data.data_parents + '" data-value="' + data.data_value + '">';
html += '</div></div>';
return html;
}
},
editor: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<textarea id="' + data.name + '_tiny" '+ data.editorType +' name="' + data.name + '" class="layui-hide editorsrv" ';
html += '></textarea>';
html += '</div></div>';
return html;
}
},
upload: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
switch (data.uploadtype) {
case 'images':
html += '<input class="layui-input layui-input-upload ' + data.name + '" name="' + data.name + '" >';
html += '<button type="button" class="layui-btn" lay-choose="' + data.name + '" data-type="images" >';
html += '<i class="layui-icon layui-icon-windows"></i>选择</button>';
html += '<div class="clear"></div>';
html += '<div class="layui-upload-drag" lay-upload="' + data.name + '" data-type="images"';
html += 'data-accept="' + data.data_accept + '"';
html += 'data-size="' + data.size + '"';
html += '>';
html += '<i class="layui-icon"></i>';
html += '<p>点击上传,或将文件拖拽到此处</p>';
html += '<div class="layui-hide">';
html += '<hr>';
html += '<img src="" class="layui-upload-dragimg ' + data.name + '" alt="上传成功后渲染" >';
html += '<span class="layui-badge layui-upload-clear" >删除</span>';
html += '</div></div>';
break;
case 'multiple':
html += '<div class="layui-imagesbox">';
html += '<div class="layui-input-inline">';
html += '<div class="layui-upload-drag" lay-upload="' + data.name + '" data-type="multiple"';
html += 'data-accept="' + data.data_accept + '"';
html += 'data-size="' + data.data_size + '"';
html += '>';
html += '<i class="layui-icon layui-icon-upload"></i>';
html += '<p>点击上传,或将文件拖拽到此处</p>';
html += '<div class="layui-hide"></div>';
html += '</div>';
html += '<button type="button" class="layui-btn layui-btn-xs layui-btn-fluid"><i class="layui-icon layui-icon-windows"></i> 选择</button>';
html += '</div>';
html += '</div>';
break;
default:
html += '<input type="text" name="' + data.name + '" class="layui-input layui-input-upload ' + data.name + '"';
if (data.disabled) {
html += 'disabled=""';
}
if (data.required) {
html += 'lay-verify="required"';
}
html += 'data-accept="' + data.data_accept + '"';
html += 'data-size="' + data.data_size + '"';
html += '>';
html += '<button type="button" class="layui-btn" lay-upload="' + data.name + '" data-type="normal" >';
html += '<i class="layui-icon layui-icon-upload"></i>上传</button>';
html += '<button type="button" class="layui-btn ml10" lay-choose="' + data.name + '" data-type="normal" >';
html += '<i class="layui-icon layui-icon-windows"></i>选择</button>';
html += '</div></div>';
break;
}
return html;
}
},
tags: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<input type="text" lay-tags="" id="' + data.name + '" name="' + data.name + '" class="layui-input" >';
html += '</div></div>';
return html;
}
},
json: {
render: function (data) {
var html = getBeforeItem(data);
html += getBeforeLabel(data.labelhide, data);
html += '<table class="layui-table" >';
html += '<thead>';
html += ' <tr>';
html += '<th>名称</th>';
html += '<th>变量值</th>';
html += '<th>操作</th>';
html += '</tr>';
html += '</thead>';
html += '<tbody>';
html += '</tbody>';
html += '</table>';
html += '<button type="button" class="layui-btn layui-btn-normal layui-jsonvar-add" data-name="' + data.name + '" >追加</button>';
html += LAY_FORM_DIV;
html += LAY_FORM_DIV;
return html;
}
},
tips: {
render: function (data) {
var html = getBeforeItem(data);
html += '<div class="' + LAY_INLINE_CLASS + '" >';
html += ' <i class="layui-icon layui-icon-about" lay-tips="' + data.msg + '" data-offset="' + data.offset + '" ></i>';
html += LAY_FORM_DIV;
html += LAY_FORM_DIV;
return html;
}
},
button: {
render: function (data) {
var html = getBeforeItem(data);
html += '<div class="' + LAY_INLINE_CLASS + '" >';
html += '<button type="button" class="layui-btn ' + data.theme + ' ' + data.btnsize + '" >' + data.text + '</button> ';
html += LAY_FORM_DIV;
html += LAY_FORM_DIV;
return html;
}
},
note: {
render: function (data) {
var html = getBeforeItem(data);
html += '<blockquote class="layui-elem-quote">' + data.textarea + '</blockquote>';
html += LAY_FORM_DIV;
return html;
}
},
subtraction: {
render: function (data) {
var html = getBeforeItem(data);
html += '<hr class="' + data.border + '">';
html += LAY_FORM_DIV;
return html;
}
},
space: {
render: function (data) {
var html = getBeforeItem(data);
html += '<div style="height:' + data.height + 'px;"></div>';
html += LAY_FORM_DIV;
return html;
}
},
tab: {
render: function (data) {
var html = getBeforeItem(data);
html += '<div id="layui-tab" id="' + data.name + '" class="layui-tab layui-tab-brief">';
html += '<ul class="layui-tab-title">';
var content = STR_EMPTY;
for (var key in data.options) {
var item = data.options[key]
html += '<li class="' + (item.checked ? 'layui-this' : '') + '">' + item.title + '</li>';
content += '<div id="saphp-tab' + key + '" class="layui-tab-item ' + (item.checked ? 'layui-show ' : '') + 'children" data-index="' + key + '"></div>';
}
html += '</ul>';
html += '<div class="layui-tab-content">';
html += content;
html += '</div>';
html += LAY_FORM_DIV;
return html;
}
},
grid: {
render: function (data) {
var html = '<div id="' + data.name + '" class="layui-form-item layui-row" data-index="' + data.index + '" data-tag="' + data.tag + '">';
// 计算每一个区块大小
if (data.children.length) {
var col = 12 / data.column;
for (let index = 0; index < data.column; index++) {
var elem = data.children[index];
html += '<div class="layui-col-md' + col + ' layui-grid-' + index + ' children" data-index="' + index + '"></div>';
}
}
html += '</div>';
return html;
}
},
}
/**
* 渲染form表单ITEM可以拖放
* @param {*} params
*/
Class.prototype.gridtabSortable = function (itemId) {
var that = this,
options = that.config;
var item = new Sortable.create(itemId, {
group: {
name: STR_FORMDESIGN
},
direction: 'vertical',
ghostClass: "sortableghost",
animation: 150,
swapClass: 'highlight',
filter: function (evt, item) {
// 限定OL标签
// if ($(item)[0].tagName != 'OL'
// || $(item).data('type') == 'space') {
// return true;
// }
// console.log($(item).data('tag'));
return false;
},
onChoose: function (evt) { },
onAdd: function (evt) {
// 表格内禁止嵌入表格
if ($(evt.item).data('tag') == 'tab') {
$(evt.item).remove();
layer.msg('禁止嵌套选项卡', 'error');
return false;
}
var item = evt.item, id = $(item).attr('id'),
parentId = $(evt.item.parentElement.parentElement).attr('id'),
parentIndex = $(evt.item.parentElement).index();
if (typeof parentId == 'undefined') {
parentId = $(evt.item).parents('.layui-tab').parent().attr('id');
}
// 查找栅格的ID
var gridElem = that.recursiveFindElem(options.data, parentId);
if (typeof id != 'undefined') {
// 创建新组件
var data = JSON.parse(JSON.stringify(that.recursiveFindElem(options.data, id)));
data.index = options.count++;
data.name = data.tag + '_' + data.index;
gridElem.children[parentIndex].children.splice(evt.newIndex, 0, data);
that.recursiveDelete(options.data, id);
} else {
var data = that.getComponentJson($(item).data('tag'));
data.index = options.count++;
data.name = data.tag + '_' + data.index;
gridElem.children[parentIndex].children.splice(evt.newIndex, 0, data);
}
options.state = data;
that.renderComponent(options.data, $('#' + options.id));
},
onUpdate: function (evt) {
var parentId = $(evt.item.parentElement.parentElement).attr('id'),
parentIndex = evt.item.parentElement.dataset.index;
if (typeof parentId == 'undefined') {
parentId = $(evt.item).parents('.layui-tab').parent().attr('id');
}
var gridElem = that.recursiveFindElem(options.data, parentId);
var children = gridElem.children[parentIndex].children;
[children[evt.newIndex], children[evt.oldIndex]] = [children[evt.oldIndex], children[evt.newIndex]];
},
onEnd: function (evt) { }
});
this.config.itemIndex[itemId] = item;
}
// 查找原始元素
Class.prototype.recursiveFindElem = function (array, name) {
var that = this;
for (let index = 0; index < array.length; index++) {
const element = array[index];
if (element.name == name) {
return element;
}
if (typeof element.children != 'undefined'
&& element.children.length) {
var subElem = element.children;
for (let i = 0; i < subElem.length; i++) {
if (subElem[i].children.length) {
var item = that.recursiveFindElem(subElem[i].children, name);
if (item && typeof item != 'undefined') {
return item;
}
}
}
}
}
}
// 删除原始元素
Class.prototype.recursiveDelete = function (array, name) {
var that = this;
for (let index = 0; index < array.length; index++) {
const element = array[index];
// 数据异常???
if (element.name == name) {
array.splice(index, 1);
break;
}
if (typeof element.children != 'undefined'
&& element.children.length) {
var subElem = element.children;
for (let i = 0; i < subElem.length; i++) {
if (subElem[i].children.length) {
that.recursiveDelete(subElem[i].children, name);
}
}
}
}
}
// 生成随机数
Class.prototype.Math = function () {
return Math.round(Math.random() * 1000);
}
//记录所有实例
thisTags.that = {};
//获取当前实例对象
thisTags.getThis = function (id) {
var that = thisTags.that[id];
if (!that) hint.error(id ? (MOD_NAME + ' instance with ID \'' + id + '\' not found') : 'ID argument required');
return that
};
//重载实例
MODULE_FORMDESIGN_NAME.reload = function (id, options) {
var that = thisTags.that[id];
that.reload(options);
return thisTags.call(that);
};
//核心入口
MODULE_FORMDESIGN_NAME.render = function (options) {
var inst = new Class(options);
return thisTags.call(inst);
};
layui.link(layui.cache.base + 'formDesign/formdesign.css');
exports(MOD_NAME, MODULE_FORMDESIGN_NAME);
})