function FormUtil(layui, viewer) {
    var $ = layui.$;
    var layer = layui.layer;
    var upload = layui.upload;
    var laydate = layui.laydate;
    var form = layui.form;
    var Viewer = viewer;
    var restAjax = layui.restajax;
    var viewerObj = {};

    /**
     * 初始化图片上传
     * @param opt
     */
    function initUploadImage(opt) {
        var maxCount = opt.maxCount ? parseInt(opt.maxCount) : 9
        maxCount = opt.maxCount < 0 ? 9 : opt.maxCount;
        var fieldName = opt.fieldName;
        var headers = opt.headers;
        headers = headers ? headers : {};
        var isApp = opt.isApp;
        var isAppRelease = opt.isAppRelease;
        var isShow = opt.isShow;

        var id = '#' + fieldName;
        var fileBoxId = id + 'FileBox';
        var uploadBtnId = id + 'UploadBtn';
        var deleteBtnClass = '.delete-' + fieldName + '-btn';

        function init(callback) {
            var fileIds = $(id).val();
            var fileIdArray = fileIds ? fileIds.split(',') : [];

            var html = '';
            for (var i = 0, fileId; fileId = fileIdArray[i++];) {
                html += [
                    '<div class="form-upload-image">',
                    '   <img src="route/file/v2/download/true/' + fileId + '" align="加载失败">',
                    '   <a class="layui-btn layui-btn-xs layui-btn-danger delete-btn delete-' + fieldName + '-btn" href="javascript:void(0);" data-id="' + fileId + '" data-name="' + fieldName + '">',
                    '       <i class="fa fa-trash-o"></i>',
                    '   </a>',
                    '</div>',
                ].join('');
            }

            $(fileBoxId).empty();
            $(fileBoxId).append(html);

            if (fileIdArray.length < maxCount) {
                $(uploadBtnId).removeClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', false);
            } else {
                $(uploadBtnId).addClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', true);
            }

            callback ? callback() : '';
        }

        function addClick() {
            var layerLoadingIndex;
            var url = 'api/file/v2/upload-image';
            if (isApp) {
                url = 'app/file/v2/upload-image'
            }
            if (isAppRelease) {
                url = 'app/file/v2/upload-image-release'
            }
            upload.render({
                elem: uploadBtnId,
                url: url,
                accept: 'images',
                acceptMime: 'image/*',
                field: 'image',
                exts: 'jpg|png|gif|bmp|jpeg',
                name: fieldName,
                headers: headers,
                before: function (obj) {
                    layerLoadingIndex = layer.msg('上传中...', {icon: 16, time: 0, shade: 0.3})
                },
                done: function (res, index, upload) {
                    layer.close(layerLoadingIndex);
                    var name = this.name;
                    var files = $('#' + this.name).val();
                    if (files.length > 0) {
                        files += ',';
                    }
                    files += res.data.fileId;
                    $('#' + name).val(files);
                    init(function () {
                        viewerObj[name].update();
                    });
                },
                error: function (index, upload) {
                    layer.close(layerLoadingIndex);
                    layer.msg('文件上传失败');
                },
                progress: function (n, elem, res, index) {
                    var percent = n + '%'
                    console.log(percent);
                    console.log(elem);
                    console.log(res);
                    console.log(index);
                    element.progress('demo-' + index, n + '%');
                }
            });
            $(document).on('click', deleteBtnClass, function () {
                var name = this.dataset.name;
                var id = this.dataset.id;
                var files = $('#' + name).val().replace(id, '');
                files = files.replace(/\,+/g, ',');
                if (files.charAt(0) == ',') {
                    files = files.substring(1);
                }
                if (files.charAt(files.length - 1) == ',') {
                    files = files.substring(0, files.length - 1);
                }
                $('#' + name).val(files);
                init(function () {
                    viewerObj[name].update();
                });
            });
        }

        init(function () {
            viewerObj[fieldName] = new Viewer(document.getElementById(fieldName + 'FileBox'), {navbar: false});
        });

        if (!isShow) {
            addClick();
        } else {
            $(uploadBtnId).hide();
        }
    }

    /**
     * 初始化图片上传
     * @param fieldName
     * @param maxCount
     */
    this.initUploadImage = function (fieldName, maxCount) {
        initUploadImage({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: false
        });
    }

    /**
     * 初始化APP图片上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppUploadImage = function (fieldName, maxCount, headers) {
        initUploadImage({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: true,
            isAppRelease: false,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 初始化APP放行图片上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppReleaseUploadImage = function (fieldName, maxCount, headers) {
        initUploadImage({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: true,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 显示上传图片
     * @param fieldName
     * @param maxCount
     */
    this.initShowUploadImage = function (fieldName, maxCount) {
        initUploadImage({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: true
        });
    }

    /**
     * 初始化文件上传
     * @param opt
     */
    function initUploadFile(opt) {
        var maxCount = opt.maxCount ? parseInt(opt.maxCount) : 3
        maxCount = opt.maxCount < 0 ? 3 : opt.maxCount;
        var fieldName = opt.fieldName;
        var headers = opt.headers;
        headers = headers ? headers : {};
        var isApp = opt.isApp;
        var isAppRelease = opt.isAppRelease;
        var isShow = opt.isShow;

        var id = '#' + fieldName;
        var fileBoxId = id + 'FileBox';
        var uploadBtnId = id + 'UploadBtn';
        var deleteBtnClass = '.delete-' + fieldName + '-btn';

        function init() {
            var files = $(id).val();
            var fileArray = files ? files.split(',') : [];

            var html = '';
            if (fileArray.length > 0) {
                html += [
                    '<div class="form-upload-file">',
                    '   <table class="layui-table" lay-size="sm">',
                    '       <colgroup>',
                    '           <col>',
                    '           <col width="60">',
                    '       </colgroup>',
                    '       <thead>',
                    '       <tr>',
                    '           <th>文件名</th>',
                    '           <th class="operation">操作</th>',
                    '       </tr>',
                    '       </thead>',
                    '       <tbody>',
                ].join('');
                for (var i = 0, file; file = fileArray[i++];) {
                    var idNameArray = file.split(':');
                    var fileId = idNameArray[0];
                    var fileName = idNameArray[1];
                    html += [
                        '<tr>',
                        '   <td><a href="route/file/v2/download/false/'+ fileId +'" target="_blank">' + fileName + '</a></td>',
                        '   <td class="operation">',
                        '       <button type="button" class="layui-btn layui-btn-xs layui-btn-danger delete-btn delete-' + fieldName + '-btn" data-id="' + fileId + '" data-name="' + fileName + '" data-field-name="' + fieldName + '">删除</button>',
                        '   </td>',
                        '</tr>',
                    ].join('');
                }
                html += [
                    '       </tbody>',
                    '   </table>',
                    '</div>'
                ].join('');
            }

            $(fileBoxId).empty();
            $(fileBoxId).append(html);

            if (fileArray.length < maxCount) {
                $(uploadBtnId).removeClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', false);
            } else {
                $(uploadBtnId).addClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', true);
            }
        }

        function addClick() {
            var layerLoadingIndex;
            var url = 'api/file/v2/upload-file';
            if (isApp) {
                url = 'app/file/v2/upload-file'
            }
            if (isAppRelease) {
                url = 'app/file/v2/upload-file-release'
            }
            upload.render({
                elem: uploadBtnId,
                url: url,
                accept: 'file',
                acceptMime: [
                    'application/pdf',
                    'application/msword',
                    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                    'application/vnd.ms-excel',
                    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                    'application/vnd.ms-powerpoint',
                    'application/vnd.openxmlformats-officedocument.presentationml.presentation',
                    'application/vnd.ms-works',
                    'text/plain',
                    'application/x-rar',
                    'application/x-zip-compressed'
                ].join(','),
                field: 'file',
                exts: 'pdf|doc|docx|xls|xlsx|ppt|pptx|wps|txt|rar|zip',
                name: fieldName,
                headers: headers,
                before: function (obj) {
                    layerLoadingIndex = layer.msg('上传中...', {icon: 16, time: 0, shade: 0.3})
                },
                done: function (res, index, upload) {
                    layer.close(layerLoadingIndex);
                    var name = this.name;
                    var files = $('#' + this.name).val();
                    if (files.length > 0) {
                        files += ',';
                    }
                    files += res.data.fileId + ':' + res.data.fileName.replace(/\,/g, '，');
                    $('#' + name).val(files);
                    init();
                },
                error: function (index, upload) {
                    layer.close(layerLoadingIndex);
                    layer.msg('文件上传失败');
                },
                progress: function (n, elem, res, index) {}
            });
            $(document).on('click', deleteBtnClass, function () {
                var id = this.dataset.id;
                var name = this.dataset.name;
                var fieldName = this.dataset.fieldName;
                var files = $('#' + fieldName).val().replace(id + ':' + name, '');
                files = files.replace(/\,+/g, ',');
                if (files.charAt(0) == ',') {
                    files = files.substring(1);
                }
                if (files.charAt(files.length - 1) == ',') {
                    files = files.substring(0, files.length - 1);
                }
                $('#' + fieldName).val(files);
                init();
            });
        }

        init();
        if (!isShow) {
            addClick();
        } else {
            $(uploadBtnId).hide();
        }

    }

    /**
     * 初始化文件上传
     * @param fieldName
     * @param maxCount
     */
    this.initUploadFile = function (fieldName, maxCount) {
        initUploadFile({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: false
        })
    }

    /**
     * 初始化APP文件上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppUploadFile = function (fieldName, maxCount, headers) {
        initUploadFile({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: true,
            isAppRelease: false,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 初始化APP放行文件上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppReleaseUploadFile = function (fieldName, maxCount, headers) {
        initUploadFile({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: true,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 显示上传文件
     * @param fieldName
     * @param maxCount
     */
    this.initShowUploadFile = function (fieldName, maxCount) {
        initUploadFile({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: true
        });
    }

    /**
     * 初始化视频上传
     * @param opt
     */
    function initUploadVideo(opt) {
        var maxCount = opt.maxCount ? parseInt(opt.maxCount) : 1
        maxCount = opt.maxCount < 0 ? 1 : opt.maxCount;
        var fieldName = opt.fieldName;
        var headers = opt.headers;
        headers = headers ? headers : {};
        var isApp = opt.isApp;
        var isAppRelease = opt.isAppRelease;
        var isShow = opt.isShow;

        var id = '#' + fieldName;
        var fileBoxId = id + 'FileBox';
        var uploadBtnId = id + 'UploadBtn';
        var deleteBtnClass = '.delete-' + fieldName + '-btn';

        function init() {
            var files = $(id).val();
            var fileArray = files ? files.split(',') : [];
            var html = '';
            for (var i = 0, file; file = fileArray[i++];) {
                var idNameArray = file.split(':');
                var fileId = idNameArray[0];
                var fileName = idNameArray[1];
                html += [
                    '<div class="form-upload-video">',
                    '   <video width="320" height="240" controls>',
                    '       <source src="route/file/v2/download/true/' + fileId + '" type="video/mp4">',
                    '       您的浏览器不支持 video 标签',
                    '   </video>',
                    '   <a class="layui-btn layui-btn-xs layui-btn-danger delete-btn delete-' + fieldName + '-btn" href="javascript:void(0);" data-id="' + fileId + '" data-name="' + fileName + '" data-field-name="' + fieldName + '">',
                    '       <i class="fa fa-trash-o"></i>',
                    '   </a>',
                    '</div>',
                ].join('');
            }

            $(fileBoxId).empty();
            $(fileBoxId).append(html);

            if (fileArray.length < maxCount) {
                $(uploadBtnId).removeClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', false);
            } else {
                $(uploadBtnId).addClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', true);
            }
        }

        function addClick() {
            var layerLoadingIndex;
            var url = 'api/file/v2/upload-video';
            if (isApp) {
                url = 'app/file/v2/upload-video'
            }
            if (isAppRelease) {
                url = 'app/file/v2/upload-video-release'
            }
            upload.render({
                elem: uploadBtnId,
                url: url,
                accept: 'video',
                acceptMime: 'video/mp4',
                exts: 'mp4',
                field: 'video',
                name: fieldName,
                headers: headers,
                before: function (obj) {
                    layerLoadingIndex = layer.msg('上传中...', {icon: 16, time: 0, shade: 0.3})
                },
                done: function (res, index, upload) {
                    layer.close(layerLoadingIndex);
                    var name = this.name;
                    var files = $('#' + this.name).val();
                    if (files.length > 0) {
                        files += ',';
                    }
                    files += res.data.fileId + ':' + res.data.fileName.replace(/\,/g, '，');
                    $('#' + name).val(files);
                    init();
                },
                error: function (index, upload) {
                    layer.close(layerLoadingIndex);
                    layer.msg('文件上传失败');
                },
                progress: function (n, elem, res, index) {}
            });
            $(document).on('click', deleteBtnClass, function () {
                var name = this.dataset.name;
                var id = this.dataset.id;
                var fieldName = this.dataset.fieldName;
                var files = $('#' + fieldName).val().replace(id + ':' + name, '');
                files = files.replace(/\,+/g, ',');
                if (files.charAt(0) == ',') {
                    files = files.substring(1);
                }
                if (files.charAt(files.length - 1) == ',') {
                    files = files.substring(0, files.length - 1);
                }
                $('#' + fieldName).val(files);
                init();
            });
        }

        init();

        if (!isShow) {
            addClick();
        } else {
            $(uploadBtnId).hide();
        }
    }

    /**
     * 初始化视频上传
     * @param fieldName
     * @param maxCount
     */
    this.initUploadVideo = function (fieldName, maxCount) {
        initUploadVideo({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: false
        })
    }

    /**
     * 初始化APP视频上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppUploadVideo = function (fieldName, maxCount, headers) {
        initUploadVideo({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: true,
            isAppRelease: false,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 初始化APP放行视频上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppReleaseUploadVideo = function (fieldName, maxCount, headers) {
        initUploadVideo({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: true,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 显示上传视频
     * @param fieldName
     * @param maxCount
     */
    this.initShowUploadVideo = function (fieldName, maxCount) {
        initUploadVideo({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: true
        });
    }

    function initUploadAudio(opt) {
        var maxCount = opt.maxCount ? parseInt(opt.maxCount) : 1
        maxCount = opt.maxCount < 0 ? 1 : opt.maxCount;
        var fieldName = opt.fieldName;
        var headers = opt.headers;
        headers = headers ? headers : {};
        var isApp = opt.isApp;
        var isAppRelease = opt.isAppRelease;
        var isShow = opt.isShow;

        var id = '#' + fieldName;
        var fileBoxId = id + 'FileBox';
        var uploadBtnId = id + 'UploadBtn';
        var deleteBtnClass = '.delete-' + fieldName + '-btn';

        function init() {
            var files = $(id).val();
            var fileArray = files ? files.split(',') : [];
            var html = '';
            for (var i = 0, file; file = fileArray[i++];) {
                var idNameArray = file.split(':');
                var fileId = idNameArray[0];
                var fileName = idNameArray[1];
                html += [
                    '<div class="form-upload-video">',
                    '   <audio src="route/file/v2/download/true/' + fileId + '" controls>',
                    '       您的浏览器不支持 audio 标签。',
                    '   </audio>',
                    '   <a class="layui-btn layui-btn-xs layui-btn-danger delete-btn delete-' + fieldName + '-btn" href="javascript:void(0);" data-id="' + fileId + '" data-name="' + fileName + '" data-field-name="' + fieldName + '">',
                    '       <i class="fa fa-trash-o"></i>',
                    '   </a>',
                    '</div>',
                ].join('');
            }

            $(fileBoxId).empty();
            $(fileBoxId).append(html);

            if (fileArray.length < maxCount) {
                $(uploadBtnId).removeClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', false);
            } else {
                $(uploadBtnId).addClass('layui-btn-disabled');
                $(uploadBtnId).attr('disabled', true);
            }
        }

        function addClick() {
            var layerLoadingIndex;
            var url = 'api/file/v2/upload-audio';
            if (isApp) {
                url = 'app/file/v2/upload-audio'
            }
            if (isAppRelease) {
                url = 'app/file/v2/upload-audio-release'
            }
            upload.render({
                elem: uploadBtnId,
                url: url,
                accept: 'audio',
                acceptMime: [
                    'audio/wav',
                    'audio/mp3'
                ],
                exts: 'wav|mp3',
                field: 'audio',
                name: fieldName,
                headers: headers,
                before: function (obj) {
                    layerLoadingIndex = layer.msg('上传中...', {icon: 16, time: 0, shade: 0.3})
                },
                done: function (res, index, upload) {
                    layer.close(layerLoadingIndex);
                    var name = this.name;
                    var files = $('#' + this.name).val();
                    if (files.length > 0) {
                        files += ',';
                    }
                    files += res.data.fileId + ':' + res.data.fileName.replace(/\,/g, '，');
                    $('#' + name).val(files);
                    init();
                },
                error: function (index, upload) {
                    layer.close(layerLoadingIndex);
                    layer.msg('文件上传失败');
                },
                progress: function (n, elem, res, index) {}
            });
            $(document).on('click', deleteBtnClass, function () {
                var name = this.dataset.name;
                var id = this.dataset.id;
                var fieldName = this.dataset.fieldName;
                var files = $('#' + fieldName).val().replace(id + ':' + name, '');
                files = files.replace(/\,+/g, ',');
                if (files.charAt(0) == ',') {
                    files = files.substring(1);
                }
                if (files.charAt(files.length - 1) == ',') {
                    files = files.substring(0, files.length - 1);
                }
                $('#' + fieldName).val(files);
                init();
            });
        }

        init();

        if (!isShow) {
            addClick();
        } else {
            $(uploadBtnId).hide();
        }
    }

    /**
     * 初始化音频上传
     * @param fieldName
     * @param maxCount
     */
    this.initUploadAudio = function (fieldName, maxCount) {
        initUploadAudio({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: false
        })
    }

    /**
     * 初始化APP音频上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppUploadAudio = function (fieldName, maxCount, headers) {
        initUploadAudio({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: true,
            isAppRelease: false,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 初始化APP放行音频上传
     * @param fieldName
     * @param maxCount
     * @param headers
     */
    this.initAppReleaseUploadAudio = function (fieldName, maxCount, headers) {
        initUploadAudio({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: true,
            isShow: false,
            headers: headers
        });
    }

    /**
     * 显示上传音频
     * @param fieldName
     * @param maxCount
     */
    this.initShowUploadAudio = function (fieldName, maxCount) {
        initUploadAudio({
            fieldName: fieldName,
            maxCount: maxCount,
            isApp: false,
            isAppRelease: false,
            isShow: true
        });
    }

    /**
     * 初始化日期
     * @param opt
     */
    this.initDate = function (opt) {
        laydate.render({
            elem: '#' + opt.id,
            type: opt.datetype,
            format: opt.dateformat,
            value: opt.dateDefaultValue,
            min: opt.dataMinValue,
            max: opt.dataMaxValue,
            trigger: 'click'
        });
    }

    /**
     * 初始化checkbox数据
     * @param form
     * @param checkedData
     * @param id
     */
    this.initCheckboxData = function (formName, checkedData, id) {
        var dataArray = checkedData.split(',');
        var obj = {};
        for (var i = 0, data; data = dataArray[i++];) {
            obj[id + '[' + data + ']'] = true;
        }
        form.val(formName, obj);
    }

    /**
     * 设置复选框值
     * @param formData
     * @param id
     */
    this.setCheckboxValue = function (formData, id) {
        formData.field[id] = restAjax.checkBoxToString(formData.field, id);
    }

    /**
     * 设置开关值
     * @param formData
     * @param id
     */
    this.setSwitchValue = function (formData, id) {
        formData.field[id] = formData.field[id] ? 1 : 0;
    }

    /**
     * 清空上传字段
     * @param formData
     */
    this.clearUploadField = function (formData) {
        var fileInputs = $(formData.form).find('input[type="file"]');
        if (fileInputs.length == 0) {
            return;
        }
        $.each(fileInputs, function (index, item) {
            delete formData.field[item.name];
        });
    }

}