define(['jquery', 'layui', 'upload'], function($, layui, Upload) { var form = layui.form; var Form = { config: { fieldlisttpl:'
' }, events: { bindevent: function(layform) { }, validator: function(layform, success, error, submit) { if (!layform.is("form") || layform.hasClass("form-commonsearch")) return; var submitBtn = $("[lay-submit]", layform), filter = submitBtn.attr('lay-filter'); $(".layer-footer [lay-submit],.fixed-footer [lay-submit],.normal-footer [lay-submit]", layform).removeClass("disabled"); //自定义验证 form.verify({ username: function(value, elem){ if (!/^\w{3,30}$/.test(value)) { return '用户名只能由3-30位数字、字母、下划线组合'; } }, password: function(value, elem) { if (!/^[\S]{6,30}$/.test(value)) { return '密码长度必须在6-30位之间,不能包含空格'; } } }) //验证通过提交表单 form.on('submit(' + filter + ')', function(data) { submitBtn.addClass("disabled"); var submitResult = Form.api.submit(layform, function(data, ret) { //that.holdSubmit(false); submitBtn.removeClass("disabled"); if (false === $(this).triggerHandler("success.form", [data, ret])) { return false; } if (typeof success === 'function') { if (false === success.call($(this), data, ret)) { return false; } } //提示及关闭当前窗口 var msg = ret.hasOwnProperty("msg") && ret.msg !== "" ? ret.msg : '操作成功!'; parent.Toastr.success(msg); parent.$(".btn-refresh").trigger("click"); if (window.name) { var index = parent.Layer.getFrameIndex(window.name); parent.Layer.close(index); } return false; }, function(data, ret) { if (false === $(this).triggerHandler("error.form", [data, ret])) { return false; } submitBtn.removeClass("disabled"); if (typeof error === 'function') { if (false === error.call($(this), data, ret)) { return false; } } }, submit); //如果提交失败则释放锁定 if (!submitResult) { submitBtn.removeClass("disabled"); } return false; }) //自定义关闭按钮事件 layform.on("click", ".layer-close", function () { if (window.name) { var index = parent.Layer.getFrameIndex(window.name); parent.Layer.close(index); } return false; }); }, faselect: function(layform) { //绑定fachoose选择附件事件 if ($(".faselect,.fachoose", layform).length > 0) { $(".faselect,.fachoose", layform).off('click').on('click', function() { var that = this; var multiple = $(this).data("multiple") ? $(this).data("multiple") : false; var mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : ''; var admin_id = $(this).data("admin-id") ? $(this).data("admin-id") : ''; var user_id = $(this).data("user-id") ? $(this).data("user-id") : ''; mimetype = mimetype.replace(/\/\*/ig, '/'); var url = $(this).data("url") ? $(this).data("url") : (typeof Backend !== 'undefined' ? "general.attachments/select" : "user/attachment"); parent.Yzn.api.open(url + "?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mime=" + mimetype + "&admin_id=" + admin_id + "&user_id=" + user_id, '选择', { callback: function(data) { var button = $(that); var maxcount = $(button).data("maxcount"); var input_id = $(button).data("input-id") ? $(button).data("input-id") : ""; maxcount = typeof maxcount !== "undefined" ? maxcount : 0; if (input_id && data.multiple) { var urlArr = []; var inputObj = $("#" + input_id); var value = $.trim(inputObj.val()); if (value !== "") { urlArr.push(inputObj.val()); } var nums = value === '' ? 0 : value.split(/\,/).length; var files = data.url !== "" ? data.url.split(/\,/) : []; $.each(files, function(i, j) { var url = Config.upload.fullmode ? Yzn.api.cdnurl(j, true) : j; urlArr.push(url); }); if (maxcount > 0) { var remains = maxcount - nums; if (files.length > remains) { Toastr.error('你最多选择' + remains + '个文件'); return false; } } var result = urlArr.join(","); inputObj.val(result).trigger("change"); } else if (input_id) { var url = Config.upload.fullmode ? Yzn.api.cdnurl(data.url, true) : data.url; $("#" + input_id).val(url).trigger("change").trigger("validate"); } } }); return false; }); } }, favisible: function(layform) { if ($("[data-favisible]", layform).length == 0) { return; } var checkCondition = function(condition) { var conditionArr = condition.split(/&&/); var success = 0; var baseregex = /^([a-z0-9\_\[\]]+)([>|<|=|\!]=?)(.*)$/i, strregex = /^('|")(.*)('|")$/, regregex = /^regex:(.*)$/; var operator_result = { '>': function(a, b) { return a > b; }, '>=': function(a, b) { return a >= b; }, '<': function(a, b) { return a < b; }, '<=': function(a, b) { return a <= b; }, '==': function(a, b) { return a == b; }, '!=': function(a, b) { return a != b; }, 'in': function(a, b) { return b.split(/\,/).indexOf(a) > -1; }, 'regex': function(a, b) { var regParts = b.match(/^\/(.*?)\/([gim]*)$/); var regexp = regParts ? new RegExp(regParts[1], regParts[2]) : new RegExp(b); return regexp.test(a); } }; var $disabledElements = layform.find(':disabled').removeAttr('disabled'); var dataArr = layform.serializeArray(), dataObj = {}, fieldName, fieldValue; $disabledElements.attr('disabled', 'disabled'); var field = layform.attr('data-field') || 'row'; $(dataArr).each(function(i, field) { fieldName = field.name; fieldValue = field.value; fieldName = fieldName.substr(-2) === '[]' ? fieldName.substr(0, fieldName.length - 2) : fieldName; dataObj[fieldName] = typeof dataObj[fieldName] !== 'undefined' ? [dataObj[fieldName], fieldValue].join(',') : fieldValue; }); $.each(conditionArr, function(i, item) { var basematches = baseregex.exec(item); if (basematches) { var name = basematches[1], operator = basematches[2], value = basematches[3].toString(); if (operator === '=') { var strmatches = strregex.exec(value); operator = strmatches ? '==' : 'in'; value = strmatches ? strmatches[2] : value; } var regmatches = regregex.exec(value); if (regmatches) { operator = 'regex'; value = regmatches[1]; } var chkname; if (name.match(/[\[\]]+/)) { chkname = name; } else { chkname = "row[" + name + "]"; if (typeof dataObj[chkname] === 'undefined' && typeof dataObj[name] !== 'undefined') { chkname = name; } } if (typeof dataObj[chkname] === 'undefined') { return false; } var objvalue = dataObj[chkname]; if ($.isArray(objvalue)) { objvalue = dataObj[chkname].join(","); } if (['>', '>=', '<', '<='].indexOf(operator) > -1) { objvalue = parseFloat(objvalue); value = parseFloat(value); } var result = operator_result[operator](objvalue, value); success += (result ? 1 : 0); } }); return success === conditionArr.length; }; var formEach = function() { $("[data-favisible][data-favisible!='']", layform).each(function() { var visible = $(this).data("favisible"); var groupArr = visible ? visible.toString().split(/\|\|/) : []; var success = 0; $.each(groupArr, function(i, j) { if (checkCondition(j)) { success++; } }); if (success > 0) { $(this).removeClass("layui-hide"); } else { $(this).addClass("layui-hide"); } }); } layform.on("keyup change click configchange", "input,textarea,select", function() { formEach(); }); form.on('select', function(data) { formEach(); }); form.on('checkbox', function(data) { formEach(); }); form.on('switch', function(data) { formEach(); }); form.on('radio', function(data) { formEach(); }); layform.on('reset', function() { setTimeout(function() { formEach(); }, 50); }); //追加上忽略元素 setTimeout(function() { form.verify({ required: function(value, elem) { if ($(elem).closest('.layui-hide[data-favisible]').is(':hidden')) { return; } if (!/[\S]+/.test(value) || value === undefined || value === null) { return '必填项不能为空'; } } }); }, 0); $("input,textarea,select", layform).trigger("configchange"); }, fieldlist: function(layform) { // 绑定fieldlist组件 if ($(".fieldlist", layform).length > 0) { require(['dragsort'], function(undefined) { //刷新隐藏textarea的值 var refresh = function(container, obj) { var data = {}; var name = container.data("name"); var textarea = $("textarea[name='" + name + "']", layform); var template = container.data("template"); $.each($("input,select,textarea", container).serializeArray(), function(i, j) { var reg = /\[(\w+)\]\[(\w+)\]$/g; var match = reg.exec(j.name); if (!match) return true; match[1] = "x" + parseInt(match[1]); if (typeof data[match[1]] == 'undefined') { data[match[1]] = {}; } if (typeof obj != 'undefined' && $(obj.elem).attr('name') == j.name) { data[match[1]][match[2]] = obj.value; } else { data[match[1]][match[2]] = j.value; } }); //使用数组保存 var usearray = container.data("usearray") || false; //保留空数据 var keepempty = container.data("keepempty") || false; var result = template || usearray ? [] : {}; var keys = Object.keys(Object.values(data)[0] || {}); var isassociative = !usearray && keys.indexOf("value") > -1 && (keys.length === 1 || (keys.length === 2 && keys.indexOf("key") > -1)); if(isassociative && keys.length ===2){ result = {}; } $.each(data, function (i, j) { if (j) { if (isassociative) { if (keys.length === 2) { if (j.key != '' || keepempty) { result['__PLACEHOLDKEY__' + j.key] = j.value; } } else { //一维数组 result.push(j.value); } } else { result.push(j); } } }); textarea.val(JSON.stringify(result).replace(/__PLACEHOLDKEY__/g, '')); }; //追加一行数据 var append = function(container, row, initial) { var tagName = container.data("tag") || (container.is("table") ? "tr" : "dd"); var index = container.data("index"); var name = container.data("name"); var template = container.data("template"); var data = container.data(); index = index ? parseInt(index) : 0; container.data("index", index + 1); row = row ? row : {}; row = typeof row.key === 'undefined' || typeof row.value === 'undefined' ? {key: '', value: ''} : row; var options = container.data("fieldlist-options") || {}; var vars = {index: index, name: name, data: data, options: options, key: row.key, value: row.value, row: row.value}; var tpl = template ? $("#" + template).html() : Form.config.fieldlisttpl; var html = layui.laytpl(tpl).render(vars); var obj = $(html); if ((options.deleteBtn === false || options.removeBtn === false) && initial) obj.find(".btn-remove").remove(); if (options.dragsortBtn === false && initial) obj.find(".btn-dragsort").remove(); if ((options.readonlyKey === true || options.disableKey === true) && initial) { obj.find("input[name$='[key]']").prop("readonly", true); } obj.attr("fieldlist-item", true); obj.insertAfter($(tagName + "[fieldlist-item]", container).length > 0 ? $(tagName + "[fieldlist-item]:last", container) : $(tagName + ":first", container)); form.render(); if ($(".btn-append,.append", container).length > 0) { //兼容旧版本事件 $(".btn-append,.append", container).trigger("fa.event.appendfieldlist", obj); } else { //新版本事件 container.trigger("fa.event.appendfieldlist", obj); } return obj; }; var fieldlist = $(".fieldlist", layform); //表单重置 layform.on("reset", function () { setTimeout(function () { fieldlist.trigger("fa.event.refreshfieldlist"); }); }); //监听文本框改变事件 $(document).on('change keyup changed', ".fieldlist input,.fieldlist textarea,.fieldlist select", function() { var container = $(this).closest(".fieldlist"); refresh(container); }); //追加控制(点击按钮) fieldlist.on("click", ".btn-append,.append", function(e, row) { var container = $(this).closest(".fieldlist"); append(container, row); refresh(container); }); //移除控制(点击按钮) fieldlist.on("click", ".btn-remove", function() { var container = $(this).closest(".fieldlist"); var tagName = container.data("tag") || (container.is("table") ? "tr" : "dd"); $(this).closest(tagName).remove(); refresh(container); }); //追加控制(通过事件) fieldlist.on("fa.event.appendtofieldlist", function(e, row) { var container = $(this); append(container, row); refresh(container); }); form.on('radio(fieldlist)', function(data) { var container = $(this).closest(".fieldlist"); refresh(container, data); }); form.on('select(fieldlist)', function(data) { var container = $(this).closest(".fieldlist"); refresh(container, data); }); //根据textarea内容重新渲染 fieldlist.on("fa.event.refreshfieldlist", function() { var container = $(this); var textarea = $("textarea[name='" + container.data("name") + "']", layform); //先清空已有的数据 $("[fieldlist-item]", container).remove(); var json = {}; try { var val = textarea.val().replace(/"(\d+)"\:/g, "\"__PLACEHOLDERKEY__$1\":"); json = JSON.parse(val); } catch (e) {} $.each(json, function(i, j) { append(container, {key: i.toString().replace("__PLACEHOLDERKEY__", ""), value: j}, true); }); }); //拖拽排序 fieldlist.each(function() { var container = $(this); var tagName = container.data("tag") || (container.is("table") ? "tr" : "dd"); container.dragsort({ itemSelector: tagName, dragSelector: ".btn-dragsort", dragEnd: function() { refresh(container); }, placeHolderTemplate: $("<" + tagName + "/>") }); if (typeof container.data("options") === 'object' && container.data("options").appendBtn === false) { $(".btn-append,.append", container).hide(); } $("textarea[name='" + container.data("name") + "']", layform).on("fa.event.refreshfieldlist", function() { //兼容旧版本事件 $(this).closest(".fieldlist").trigger("fa.event.refreshfieldlist"); }); }); fieldlist.trigger("fa.event.refreshfieldlist"); }) } }, selectpage: function(layform) { // 绑定selectpage组件 if ($(".selectpage", layform).length > 0) { require(['selectpage'], function() { $('.selectpage', layform).selectPage({ eAjaxSuccess: function(data) { data.list = typeof data.data !== 'undefined' ? data.data : []; data.totalRow = typeof data.count !== 'undefined' ? data.count : data.data.length; return data; } }) }) $(layform).on("reset", function() { setTimeout(function() { $(".selectpage", layform).each(function() { if ($(this).val()) { var selectpage = $(this).data("selectPageObject"); selectpage.elem.hidden.val($(this).val()); $(this).selectPageRefresh(); } else { $(this).selectPageClear(); } }); }, 1); }) } }, cxselect: function(layform) { //绑定cxselect元素事件 if ($("[data-toggle='cxselect']", layform).length > 0) { require(['cxselect'], function() { $.cxSelect.defaults.jsonName = 'name'; $.cxSelect.defaults.jsonValue = 'value'; $.cxSelect.defaults.jsonSpace = 'data'; $("[data-toggle='cxselect']", layform).cxSelect(); }); } }, citypicker: function(layform) { // 绑定城市选择组件 if ($("[data-toggle='city-picker']", layform).length > 0) { require(['citypicker'], function() { $(layform).on("reset", function() { setTimeout(function() { $("[data-toggle='city-picker']", layform).citypicker('refresh'); }, 1); }); }) } }, datetimepicker: function(layform) { // 绑定时间组件 if ($(".datetime", layform).length > 0) { $(".datetime", layform).each(function() { var format = $(this).attr('data-date'), type = $(this).attr('data-date-type'), range = $(this).attr('data-date-range'); if (type === undefined || type === '' || type === null) { type = 'datetime'; } var options = { elem: this, type: type, trigger: 'click', }; if (format !== undefined && format !== '' && format !== null) { options['format'] = format; } if (range !== undefined) { if (range === null || range === '') { range = '-'; } options['range'] = range; options['shortcuts'] = [{ text: "今天", value: function() { var today = new Date(); return [ new Date(today.getFullYear(), today.getMonth(), today.getDate()), new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59) ]; } }, { text: "昨天", value: function() { var yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); return [ new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate()), new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate(), 23, 59, 59) ]; } }, { text: "7天前", value: function() { var today = new Date(); var sevenDaysAgo = new Date(); sevenDaysAgo.setDate(today.getDate() - 7); return [ new Date(sevenDaysAgo.getFullYear(), sevenDaysAgo.getMonth(), sevenDaysAgo.getDate()), new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59) ]; } }, { text: "本月", value: function() { var date = new Date(); var year = date.getFullYear(); var month = date.getMonth(); return [ new Date(year, month, 1), new Date(year, month + 1, 0, 23, 59, 59) ]; } }, { text: "上个月", value: function() { var date = new Date(); var year = date.getFullYear(); var month = date.getMonth(); return [ new Date(year, month - 1, 1), new Date(year, month, 0, 23, 59, 59) ]; } } ] } layui.laydate.render(options); }) } }, tagsinput: function(layform) { if ($(".form-tags", layform).length > 0) { require(['tagsinput'], function() { $(".form-tags", layform).tagsInput({ width: 'auto', defaultText: $(this).data('remark') || '关键词回车确认', height: '26px', }) layform.on("reset", function () { setTimeout(function () { $(".form-tags", layform).resetTags(); }, 0); }); }); } }, colorpicker: function(layform) { // 绑定颜色组件 if ($('.colorpicker', layform).length > 0) { $('.colorpicker', layform).each(function() { var input_id = $(this).data("input-id"); var inputObj = $("#" + input_id); layui.colorpicker.render({ elem: $(this), color: inputObj.val(), done: function(color) { inputObj.val(color); } }); }); } }, cropper: function(layform) { //裁剪图片 layform.off('click', '.btn-cropper').on('click', '.btn-cropper', function() { var input = $("#" + $(this).data("input-id")); var image = $(this).parent('.file-panel').prev('img').data('original'); var url = image; var parentWin = (parent ? parent : window); parentWin.Yzn.api.open('general.attachments/cropper?url=' + image, '裁剪', { callback: function(data) { if (typeof data !== 'undefined') { //data URI 转换为一个 File 对象 var arr = data.dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } var urlArr = url.split('.'); var suffix = 'png'; url = urlArr.join(''); var filename = url.substr(url.lastIndexOf('/') + 1); var exp = new RegExp("\\." + suffix + "$", "i"); filename = exp.test(filename) ? filename : filename + "." + suffix; var file = new File([u8arr], filename, { type: mime }); Upload.api.send(file, function(data) { input.val(input.val().replace(image, data.url)).trigger("change"); }, function(data) {}); } }, area: ["800px", "600px"], }) }); }, xmSelect: function(layform) { // 绑定下拉框多选组件 if ($('.form-selects', layform).length > 0) { require(['xm-select'], function(xmSelect) { $('.form-selects', layform).each(function() { var name = $(this).data("name"); var list = Array.isArray($(this).data("list")) || typeof $(this).data("list") === "object" ? $(this).data("list") : []; var value = $(this).data("value"); var newArr = []; $.each(list, function(i, j) { var vote = {}; vote.value = i; vote.name = j; newArr.push(vote); }) if (typeof value != 'object' && value) { value = typeof value === "number" ? [value] : value.split(',') } xmSelect.render({ el: this, initValue: value, name: name, data: newArr }) }) }) } }, plupload: function(layform) { Form.events.faupload(layform); }, faupload: function(layform) { //绑定上传元素事件 if ($(".plupload,.faupload", layform).length > 0) { Upload.api.upload($(".plupload,.faupload", layform)); } }, }, api: { submit: function(form, success, error, submit) { if (form.length === 0) { Toastr.error("表单未初始化完成,无法提交"); return false; } if (typeof submit === 'function') { if (false === submit.call(form, success, error)) { return false; } } var type = form.attr("method") ? form.attr("method").toUpperCase() : 'POST'; type = type && (type === 'GET' || type === 'POST') ? type : 'POST'; url = form.attr("action"); url = url ? url : location.href; //修复当存在多选项元素时提交的BUG var params = {}; var multipleList = $("[name$='[]']", form); if (multipleList.length > 0) { var postFields = form.serializeArray().map(function(obj) { return $(obj).prop("name"); }); $.each(multipleList, function(i, j) { if (postFields.indexOf($(this).prop("name")) < 0) { params[$(this).prop("name")] = ''; } }); } //调用Ajax请求方法 Yzn.api.ajax({ type: type, url: url, data: form.serialize() + (Object.keys(params).length > 0 ? '&' + $.param(params) : ''), dataType: 'json', complete: function(xhr) { var token = xhr.getResponseHeader('__token__'); if (token) { $("input[name='__token__']").val(token); } } }, function(data, ret) { //$('.form-group', form).removeClass('has-feedback has-success has-error'); if (data && typeof data === 'object') { //刷新客户端token if (typeof data.token !== 'undefined') { $("input[name='__token__']").val(data.token); } //调用客户端事件 if (typeof data.callback !== 'undefined' && typeof data.callback === 'function') { data.callback.call(form, data); } } if (typeof success === 'function') { if (false === success.call(form, data, ret)) { return false; } } }, function(data, ret) { if (data && typeof data === 'object' && typeof data.token !== 'undefined') { $("input[name='__token__']").val(data.token); } if (typeof error === 'function') { if (false === error.call(form, data, ret)) { return false; } } }); return true; }, bindevent: function(form, success, error, submit) { form = typeof form === 'object' ? form : $(form); var events = Form.events; events.bindevent(form); events.validator(form, success, error, submit); events.selectpage(form); events.faupload(form); events.faselect(form); events.fieldlist(form); events.cxselect(form); events.citypicker(form); events.datetimepicker(form); events.colorpicker(form); events.cropper(form); events.xmSelect(form); events.tagsinput(form); events.favisible(form); } }, } return Form; });