文件内容 form.js 198 KB 189788 字符
"use strict";

var _classPath = "";
/**
 * 用于view承载extend扩展信息,比如extendUser特殊地方需要使用
 */
var _global_expend_object = {};

/**
 * 字段集合 或者index.html中的查询字段
 */
var _global_data_properties = null;//当前模型的属性列表

/**
 * 表的属性
 */
var _global_class_attributes = null;

/**
 * 组合路径
 * @returns 
 */
function auto_path() {
    if (_classPath.indexOf("/") >= 0) {
        return _classPath;
    } else {
        return `/${readRootPath()}/${_classPath}`;
    }
}

/**
 * 获取根路径 示例/api/app
 * @returns 
 */
function auto_root_path() {
    if (_classPath.indexOf("/") >= 0) {
        return _classPath.substring(0, _classPath.lastIndexOf("/"));
    } else {
        return `/${readRootPath()}`;
    }
}

/**
 * 为子页面调用使用,点击layer.open的确定按钮 子页面点击选择 即关闭页面
 */
function FuncClickSure() {

    // $(".layui-layer-btn0").trigger('click');
    // console.log(location.href, "trigger.click");
    // var lays = document.getElementsByClassName("layui-layer-shade");
    // if (lays) {
    //     for (var _lay of lays) {
    //         $(_lay).trigger('click');
    //     }
    // }

    // 找到所有包含 btn0 的弹层,按 z-index 降序排列,取第一个
    $('.layui-layer').has('.layui-layer-btn0').sort(function (a, b) {
        return $(b).css('z-index') - $(a).css('z-index');
    }).first().find('.layui-layer-btn0').trigger('click');

}

/**
 * 隐藏dialog下方的确定取消按钮条
 */
function FuncHiddenSureButtons() {
    // console.log('layer-btn hide ',location.href);
    $(".layui-layer-btn").hide();
    console.log(location.href, "FuncHiddenSureButtons");
}

/**
 * 2026.01.05 修正 ./ ../等的问题!
 * @param {*} path 
 * @returns 
 */
function autoUrl(path) {
    // 获取当前页面的协议、域名和路径
    const protocol = window.location.protocol;
    const host = window.location.host;
    const currentPath = window.location.pathname;
    const baseUrl = protocol + '//' + host;

    let fullUrl;

    if (path.startsWith('/')) {
        // 如果 path 是绝对路径,直接拼接协议和域名
        fullUrl = baseUrl + path;
    } else {
        // 如果 path 是相对路径,先使用URL API解析
        const currentDir = currentPath.substring(0, currentPath.lastIndexOf('/') + 1);
        fullUrl = new URL(path, baseUrl + currentDir).href;
    }

    // 处理多个 pasteform 文件夹路径
    const urlObj = new URL(fullUrl);
    const parts = urlObj.pathname.split('/').filter(p => p);

    const newParts = [];
    let pasteformFound = false;

    for (const part of parts) {
        if (part === 'pasteform') {
            if (!pasteformFound) {
                newParts.push(part);
                pasteformFound = true;
            }
        } else {
            newParts.push(part);
        }
    }

    urlObj.pathname = '/' + newParts.join('/');
    return urlObj.href;
}

/**
 * 打开一个窗口
 * @param {*} title 
 * @param {*} url 
 * @param {*} _w 设定的宽度,可以不设置,默认为90%,可以设置为xxxpx
 * @param {*} _h 设定的高度,可以不设置,默认为90%,可以设置为xxxpx
 */
function open_window(title, url, _w, _h, endcallback) {
    if (url.indexOf('pasteform') >= 0) {
        url = autoUrl(url);
    }
    if (!_w) {
        _w = '1200px';
    }
    if (!_h) {
        _h = '800px';
    }
    var _th = '100%';
    var _tw = '100%';
    if (_w) {
        var maxHeight = $(window).width();
        if (_w.indexOf('px') >= 0) {
            var _current_w = Number(_w.replace('px', ''));
            if (_current_w <= maxHeight) {
                _tw = _w;
            } else {
                console.log('target.width', _w, "max.width", maxHeight);
            }
        }
        if (_w.indexOf("%") > 0) {
            _tw = _w;
        }
    }
    if (_h) {
        var maxHeight = $(window).height();
        if (_h.indexOf('px') >= 0) {
            var _current_h = Number(_h.replace('px', ''));
            if (_current_h <= maxHeight) {
                _th = _h;
            }
        }
        if (_h.indexOf("%") > 0) {
            _th = _h;
        }
    }
    window.top.layer.open({
        type: 2,
        area: [_tw, _th],
        fix: false, //不固定
        maxmin: true,
        resize: true,
        shadeClose: true,
        shade: 0.8,
        title: title,
        content: url,
        success: function (layero, index) {
            // if(has_reset_size){
            //     setTimeout(()=>{
            //         layero.css('opacity', '1');
            //         console.log('延迟设置为1透明度');
            //     },1000);
            // }
            //TODO 后续调整为,页面注备就绪后再显示 skin不行是显示后追加的样式 而不是一开始... .. .
        },
        end: function () {
            if (endcallback) {
                endcallback();
            }
        }
    });

    //如果当前页面有回调函数,则先进行0透明 后面再显示
    // if (window.top.set_dialog_height) {
    //     window.top.set_dialog_height(_height, _index);
    // } else {
    //     console.log('没有在父级找到函数set_dialog_height');
    // }
}

/**
 * 打开,从右侧打开到左侧
 * @param {*} title 
 * @param {*} url 
 * @param {*} _w 
 * @param {*} _h 
 * @param {*} endcallback 
 */
function open_left(title, url, _w, _h, endcallback) {
    if (url.indexOf('pasteform') >= 0) {
        url = autoUrl(url);
    }
    if (!_w) {
        _w = '50%';
    }
    if (!_h) {
        _h = '100%';
    }
    var _th = '100%';
    var _tw = '50%';
    if (_w) {
        var maxHeight = $(window).width();
        if (_w.indexOf('px') >= 0) {
            var _current_w = Number(_w.replace('px', ''));
            if (_current_w <= maxHeight) {
                _tw = _w;
            } else {
                console.log('target.width', _w, "max.width", maxHeight);
            }
        }
        if (_w.indexOf("%") > 0) {
            _tw = _w;
        }
    }
    if (_h) {
        var maxHeight = $(window).height();
        if (_h.indexOf('px') >= 0) {
            var _current_h = Number(_h.replace('px', ''));
            if (_current_h <= maxHeight) {
                _th = _h;
            }
        }
        if (_h.indexOf("%") > 0) {
            _th = _h;
        }
    }
    window.layer.open({
        type: 2,
        area: [_tw, _th],
        fix: false, //不固定
        maxmin: false,
        resize: false,
        shadeClose: true,
        shade: 0.2,
        offset: 'r',
        title: title,
        anim: 'slideLeft',
        skin: 'layui-layer-win10',
        content: url,
        success: function (layero, index) {
        },
        end: function () {
            if (endcallback) {
                endcallback();
            }
        }
    });

    //如果当前页面有回调函数,则先进行0透明 后面再显示
    // if (window.top.set_dialog_height) {
    //     window.top.set_dialog_height(_height, _index);
    // } else {
    //     console.log('没有在父级找到函数set_dialog_height');
    // }
}

//可以再来一个 右侧往左弹出的,用于特殊地方!

/**
 * 打开一个对话框,并等待选择结果
 * @param {*} _title 标题
 * @param {*} _url url
 * @param {*} _w 宽度 xxxpx/xxx%
 * @param {*} _h 高度
 * @param {*} callback 回调
 */
function open_select(_title, _url, _w, _h, callback) {

    //解析linkquery特性
    // var _linkquery = handlerBuildLinkQueryUrl();
    // if(_linkquery){
    //     if(_url.indexOf("?")>=0){
    //         _url = _url+_linkquery;
    //     }else{
    //         _url = '?'+_linkquery.substring(1);
    //     }
    // }
    // console.log( "line.218",_url);
    //补充linkquery
    _url = handlerAutoQueryIncludeLinkQuery(_url);
    // console.log( "line.221",_url);
    //补充表单{{:=item.xxx}}动态参数
    _url = handlerBuildDynamicUrl(_url);
    // console.log( "line.224",_url);

    if (!_w) {
        _w = '80%';
    }
    if (!_h) {
        _h = '90%';
    }
    var _th = '100%';
    var _tw = '100%';

    if (_w) {
        var _max_height = $(window).width();
        if (_w.indexOf('px') >= 0) {
            var _current_w = Number(_w.replace('px', ''));
            if (_current_w < _max_height) {
                _tw = _w;
            }
        }
        if (_w.indexOf("%") > 0) {
            _tw = _w;
        }
    }
    if (_h) {
        var _max_height = $(window).height();
        if (_h.indexOf('px') >= 0) {
            var _current_h = Number(_h.replace('px', ''));
            if (_current_h < _max_height) {
                _th = _h;
            }
        }
        if (_h.indexOf("%") > 0) {
            _th = _h;
        }
    }

    window.top.layer.open({
        type: 2,
        area: [_tw, _th],
        fixed: true,
        maxmin: false,
        resize: false,
        scrollbar: false,
        shade: 0.6,
        shadeClose: true,
        title: _title,
        content: _url,
        btn: ['确定', '取消'],
        success: function (layero, index) {
        },
        yes: function (index, layero) {
            // console.log('yes:', _url);
            var _select = $(layero).find("iframe")[0].contentWindow.SelectObject;
            window.top.layer.close(index);
            // console.log('selected:', _select);
            callback(_select);
        },
        end: function () {
            console.log('open_select.end', _url);
        }
    });
}

/**
 * 子窗口穿透过来,重新计算高度
 * @param {*} _height 
 * @param {*} _index 
 */
function set_dialog_height(_height, _index) {
    var _max_height = $(window).height();
    if (_height < _max_height * 0.9) {
        $(`#layui-layer${_index}`).css('height', _height);
        $(`#layui-layer${_index}`).css('top', (_max_height - _height) / 2);
        $(`#layui-layer-iframe${_index}`).css('height', (_height - 40));
    } else {
        var ilayerHeight = $(`#layui-layer${_index}`).height();
        $(`#layui-layer-iframe${_index}`).css('height', (ilayerHeight - 40));
    }
}

/**
 * 查找某一个属性
 * _global_data_properties
 * 如果要查找_global_list_properties 则使用 funcQueryPropertry
 * @param {*} _name 
 * @returns 
 */
function funcFindPropertry(_name) {
    if (_global_data_properties) {
        for (var one of _global_data_properties) {
            if (one.name == _name) {
                return one;
            }
        }
    }
    return null;
}

/**
 * 查找这个属性
 * _global_list_properties
 * @param {*} _name 
 * @returns 
 */
function funcQueryPropertry(_name) {
    if (_global_list_properties) {
        for (var one of _global_list_properties) {
            if (one.name == _name) {
                return one;
            }
        }
    }
    return null;
}

/**
 * 查找同级的另外一个字段,有可能有__ _global_data_properties
 * @param {*} _name extendUser
 * @param {*} _from userId 这个可能为 user__userId
 * @returns 
 */
function funcFindExpendPropertry(_name, _from) {
    var _new_name = false;
    if (_from) {
        if (_from.indexOf("__") > 0) {
            var _la = _from.lastIndexOf("__");
            var _head = _from.substring(0, _la);
            _new_name = _head + "__" + _name;
        }
    }
    if (_global_data_properties) {
        //是否要进行忽略大小写的查找对比?
        for (var one of _global_data_properties) {
            if (one.name == _name || (_new_name && one.name == _new_name)) {
                return one;
            }
        }
    }
    //_readObject是session_key暂存的 需要转化成一个voloModelInfo
    if (_global_expend_object) {
        if (_global_expend_object.hasOwnProperty(_name)) {
            var info = {
                name: _name,
                hidden: true,
                value: _global_expend_object[_name]
            };
            return info;
        }
        //应对多层级的问题
        if (_new_name) {
            if (_global_expend_object.hasOwnProperty(_new_name)) {
                var info = {
                    name: _new_name,
                    hidden: true,
                    value: _global_expend_object[_new_name]
                };
                return info;
            }
        }
    }
    return null;
}

/**
 * 从某一个字段中查找某一个属性
 * @param {*} attributes 
 * @param {*} _name 
 * @returns 
 */
function funcFindAttribute(attributes, _name) {
    if (attributes) {
        for (var one of attributes) {
            if (one.name == _name) {
                return one;
            }
        }
    }
    return null;
}

/**
 * 打开一个表的列表,然后进行选择!
 * 后续用 funcLinkOuterOpenSelect
 * @param {*} title 
 * @param {*} className userInfo或者userInfo&level=1或者./pasteform/index.html?path=userInfo&level=1
 * @param {*} num 
 * @param {*} callback 
 */
function funcOuterOpenSelect(title, className, num, callback) {
    var _url = className;
    if (_url.indexOf('/') == -1) {
        _url = `${handlerPasteFormPath()}index.html?model=select&path=${className}`;
    } else {
        _url = handlerBuildDynamicUrl(className);
    }
    if (_url.indexOf("/") == -1) {
        _url = `${handlerPasteFormPath()}index.html?path=${_url}`;
    }
    open_select(title, _url + '&select_num=' + num, "", "", callback);
}

/**
 * 获取pasteform的根目录 
 * 返回格式 /page/pasteform/
 * 也有可能是 比如/manage/pasteform/
 * 注意pasteform的框架的文件夹必须是这个名字才行!
 * 如果没有,则返回空
 */
function handlerPasteFormPath() {
    var _path = location.pathname;
    var _path_index = _path.indexOf("/pasteform/");
    if (_path_index >= 0) {
        return _path.substring(0, _path_index) + "/pasteform/";
    }
    return "";
}

/**
 * 打开对话框,基于sessionStorage存储读取对象信息并显示到表单中等待回传
 * @param {*} _title 
 * @param {*} _className 
 * @param {*} _session_key 
 * @param {*} callback 
 */
function funcObjectOpenSelect(_title, _className, _session_key, callback) {
    var _url = _className;
    if (_url.indexOf('/') == -1) {
        _url = `${handlerPasteFormPath()}view.html?model=object&path=${_className}&session_key=${_session_key}`;
    } else {
        _url = handlerBuildDynamicUrl(_className);
    }
    open_select(_title, _url, "", "", callback);
}

/**
* 注入时间区间 注意这个daterange库是改版过的,就是在库里面已经为这个输入框赋值了
* @param {*} elcid 
*/
function HandlerInitDateRange(elcid, _value) {
    var _start = '';
    var _end = '';
    if (_value) {
        var splits = _value.split(' ');
        _start = splits[0];
        var sizes = splits.length;
        _end = splits[sizes - 1];
    }
    if (typeof (pickerDateRange) != 'undefined') {
        if ($(`#${elcid}`).length > 0) {
            new pickerDateRange(elcid, {
                isTodayValid: true,
                defaultText: '  至  ',
                startDate: _start,
                endDate: _end,
                success: function (obj) { },
                clear: function () { }
            });
        } else {

        }
    } else {
        console.log('没有找到模块pickerDateRange 注入daterange失败!');
    }
}

// 判断字符串是否以.js结尾的函数,兼容旧浏览器
function isJsFile(str, suffix) {
    // const suffix = '.js';
    return str.slice(-suffix.length) === suffix;
}

/**
 * 载入js或者css等 当前残缺的版本 请使用 loadResource
 * @param {*} src 
 * @param {*} func 
 */
function loadLibFile(src, func) {
    if (src) {
        if (isJsFile(src, ".js")) {
            const script = document.createElement('script');
            script.src = src;
            script.onload = () => {
                if (func) {
                    const functionToExecute = window[func];
                    // 检查函数是否存在且为函数类型
                    if (typeof functionToExecute === 'function') {
                        // 执行函数
                        functionToExecute();
                    } else {
                        console.error(`名为 ${func} 的函数不存在或者不是一个有效的函数。`);
                    }
                }
            };
            script.onerror = () => {
                console.error(`Failed to load script: ${src}`);
            };
            document.head.appendChild(script);
        }
        if (isJsFile(src, ".css")) {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = src;
            link.onload = () => {
                if (func) {
                    const functionToExecute = window[func];
                    // 检查函数是否存在且为函数类型
                    if (typeof functionToExecute === 'function') {
                        // 执行函数
                        functionToExecute();
                    } else {
                        console.error(`名为 ${func} 的函数不存在或者不是一个有效的函数。`);
                    }
                }
            };
            link.onerror = () => {
                console.error(`Failed to load CSS: ${src}`);
            };
            document.head.appendChild(link);
        }
        //载入模板数据
        if (isJsFile(src, ".html")) {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = src;
            link.onload = () => {
                if (func) {
                    const functionToExecute = window[func];
                    // 检查函数是否存在且为函数类型
                    if (typeof functionToExecute === 'function') {
                        // 执行函数
                        functionToExecute();
                    } else {
                        console.error(`名为 ${func} 的函数不存在或者不是一个有效的函数。`);
                    }
                }
            };
            link.onerror = () => {
                console.error(`Failed to load CSS: ${src}`);
            };
            document.head.appendChild(link);
        }
    }
}


/**
 * 异步加载资源的函数
 * @param {*} src 
 * @param {*} func 
 * @returns 
 */
async function loadResource(src, func) {
    try {
        if (isJsFile(src, ".js")) {
            await loadScript(src);
        }
        else if (isJsFile(src, ".css")) {
            await loadCSS(src);
        }
        else if (isJsFile(src, ".html")) {
            await loadHTML(src);
        }
        // 资源加载完成后执行回调函数
        if (func) {
            const functionToExecute = window[func];
            if (typeof functionToExecute === 'function') {
                functionToExecute();
            } else {
                console.error(`名为 ${func} 的函数不存在或者不是一个有效的函数。`);
            }
        }
        return true; // 加载成功       
    } catch (error) {
        console.error(`Failed to load resource: ${src}`, error);
        return false; // 加载失败
    }
}

// 加载JS文件
function loadScript(src) {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = src;
        script.onload = () => resolve();
        script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
        document.head.appendChild(script);
    });
}

// 加载CSS文件
function loadCSS(src) {
    return new Promise((resolve, reject) => {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = src;
        link.onload = () => resolve();
        link.onerror = () => reject(new Error(`Failed to load CSS: ${src}`));
        document.head.appendChild(link);
    });
}

// 加载HTML模板 - 正确的方式
function loadHTML(src) {
    return new Promise((resolve, reject) => {
        fetch(src)
            .then(response => {
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                return response.text();
            })
            .then(html => {
                // 创建一个临时容器来存放HTML内容
                const container = document.createElement('div');
                container.style.display = 'none'; // 隐藏容器
                container.innerHTML = html;
                document.body.appendChild(container);

                // 将容器存储在全局变量中以便后续访问
                if (!window.loadedTemplates) {
                    window.loadedTemplates = {};
                }
                window.loadedTemplates[src] = container;

                resolve(container);
            })
            .catch(error => {
                reject(new Error(`Failed to load HTML: ${src} - ${error.message}`));
            });
    });
}

/**
 * 获取范围内的随机值
 * @param {*} n 
 * @param {*} m 
 */
function randomValue(n, m) {
    return Math.floor(Math.random() * (m - n + 1)) + n;
}

//组列表
var _ui_data_list = new Array();

var BtnExpend = null;
/**
 * 缓存,哪些changeui特性
 */
var _changeui_list = new Array();//attribute val
/**
* 读取数据的模型 处理数据的模型
* @param {*} properties 
*/
async function LoadModelProperity(properties) {

    if (_config.model == "add" || _config.model == "list") {
        //加载query如果有 只有新增的时候需要,编辑模式不需要!!!
        LoadQuery(properties);
    }

    handlerExchangeDataTypeToUIType(properties);

    //如果要加载markdown
    if (_global_need_loadmarkdown) {
        await new Promise((resolve, reject) => {
            var _script = document.createElement("script");
            _script.src = "../lib/editor.md/editormd.min.js";
            _script.type = "text/javascript";
            _script.onload = function () {
                resolve();
            }
            _script.onerror = function () {
                reject();
            }
            document.head.appendChild(_script);
        });
        //../lib/editor.md/css/editormd.min.css
        const _style = document.createElement('link');
        _style.type = 'text/css';
        _style.rel = "stylesheet";
        _style.href = "../lib/editor.md/css/editormd.min.css";
        document.head.appendChild(_style);

        var _paste = document.createElement("script");
        _paste.src = "../lib/editor.md/md.paste.js";
        _paste.type = "text/javascript";
        document.head.appendChild(_paste);
    }
    //如果要加载富文本
    if (_global_need_loadrichhtml) {
        await new Promise((resolve, reject) => {
            var _script = document.createElement("script");
            _script.src = "../lib/wangeditor/wangEditor.min.js";
            _script.type = "text/javascript";
            _script.onload = function () {
                resolve();
            }
            _script.onerror = function () {
                reject();
            }
            document.head.appendChild(_script);
        });
        E = window.wangEditor;
    }

    //剔除hide的项目
    _global_data_properties = _global_data_properties.filter(item => !item.hide);

    //处理group模式
    for (var k = 0; k < properties.length; k++) {
        var item = properties[k];
        if (item.attributes) {
            var _group = funcFindAttribute(item.attributes, "group");
            if (_group) {
                handlerTakeGroupInfo(_group.args1, _ui_data_list, item);
            } else {
                _ui_data_list.push(item);
            }
        } else {
            _ui_data_list.push(item);
        }
        if (item.value) {
            if (item.value != null) {
                if (typeof (item.value) == "object") {
                    _global_expend_object[item.name] = item.value;
                }
            }
        }
    }

    //最上方的组描点
    var _ui_tabs = new Array();
    if (_ui_data_list && _ui_data_list.length > 0) {
        if (_ui_data_list[0].isgroup) {
            _ui_data_list.forEach(ia => {
                if (ia.isgroup) {
                    _ui_tabs.push(ia);
                }
            });
            $(".newform").css('padding-top', '0px');
        }
    }


    //handlerChangeUiAttribute
    //整理changeui的联动
    if (_changeui_list && _changeui_list.length > 0) {
        var changeUiMaps = new Map();
        for (let change_item of _changeui_list) {
            var read = changeUiMaps.get(change_item.name);
            if (read) {
                read.attributes.push(change_item.attribute);
            } else {
                changeUiMaps.set(change_item.name, {
                    value: change_item.value.toString(),
                    attributes: [change_item.attribute]
                });
            }
        }
        changeUiMaps.forEach((data, key) => {
            privateChangeUiHandler(data.attributes, data.value, false);
        })
        // for (let change_item of _changeui_list) {
        //     //name表示哪个字段 理论name一样value肯定一样,因为是传入值,可能attribute有多个 在这里要进行合并
        //     handlerChangeUiAttribute(change_item.attribute, change_item.value, false);
        // }

    }

    // console.log(_ui_data_list);

    //进行多级模板渲染!
    var _template_form = $("#template_form").html();
    var _template_item = $("#template_tr_item").html();
    var _tpl_form = template(_template_form);
    var _tpl_item = template(_template_item);

    //以下是新版本
    var _ahtml = _tpl_form({ list: _ui_data_list, templatetr: _tpl_item, config: _config, tabs: _ui_tabs });
    $(".paste-form-body").html(_ahtml);

    //以下是旧版本
    // var _template = $("#templatemodel").html();
    // var _ahtml = template(_template, { list: properties, config: _config });
    // $(".paste-form-body").html(_ahtml);

    setTimeout(function () {
        FormLoaded(properties);
        funcAppendInputLength();
        //计算高度,返回
        var _height = $(".newform").height() + 140 + 70;
        if (_has_outer) {
            //如果计算的高度小于600,表单中有outer则至少保证高度为600
            if (_height < 600) {
                _height = 600;
            }
        }
        var _index = parent.layer.getFrameIndex(window.name); //获取窗口索引
        // if (window.parent.set_dialog_height) {
        //     window.parent.set_dialog_height(_height, _index);
        // } else {
        //     console.log('没有在父级找到函数set_dialog_height');
        // }
        //这里有问题,如果是父级的呢 估计要多重扩展!
        if (window.top.set_dialog_height) {
            window.top.set_dialog_height(_height, _index);
        } else {
            console.log('没有在父级找到函数set_dialog_height');
        }
        /**
         * selects lselect paste-form-body
         */

        //合并改版 旧版本
        // $(".paste-form-body").on('click', '.ulitems li', function () {
        //     if ($(this).hasClass('selected')) {
        //         $(this).removeClass('selected');
        //     } else {
        //         $(this).addClass('selected');
        //     }
        //     let nameElc = $(this).parents(".ulitems");
        //     var _name = nameElc.attr('name');
        //     if (_name) {
        //         var _pro = funcFindPropertry(_name);
        //         if (_pro) {
        //             var _maxnum = 0;
        //             var _attribute = funcFindAttribute(_pro.attributes, "selects");
        //             if (_attribute) {
        //                 if (_attribute.args4) {
        //                     _maxnum = Number(_attribute.args4);
        //                 }
        //             } else {
        //                 _attribute = funcFindAttribute(_pro.attributes, "lselect");
        //                 if (_attribute) {
        //                     if (_attribute.args4) {
        //                         _maxnum = Number(_attribute.args4);
        //                     }
        //                 }
        //             }
        //             if (_maxnum > 0) {
        //                 var _selnum = nameElc.find(".selected").length;
        //                 if (_selnum > _maxnum) {
        //                     if (_maxnum > 1) {
        //                         $(this).removeClass('selected');
        //                         layer.msg(`限定最多选择${_maxnum}项`);
        //                     } else {
        //                         $(this).siblings().removeClass('selected');
        //                     }
        //                 }
        //                 if (_maxnum == 1) {
        //                     var _val = $(this).attr('value');
        //                     handlerReloadReplace(_pro.attributes, _name, _val);
        //                     handlerChangeUi(_pro.attributes, _val);
        //                     // var _attribute = funcFindAttribute(_pro.attributes, "reload");
        //                     // if (_attribute) {
        //                     //     var _val = $(this).attr('value');
        //                     //     if (_attribute.args1) {
        //                     //         _name = _attribute.args1;
        //                     //     }
        //                     //     handlerBuildNewUrlToLoad(_name, _val);
        //                     // }
        //                 }
        //             }
        //             if (_attribute.name == "selects") {
        //                 //从ui中获取选中得 使用比如{name value }
        //                 updateSelectText(nameElc, _pro);
        //             }
        //             handlerLoaditem(_pro);
        //         }
        //     }
        // });

        //合并改版 新版本
        register_ulitems_click_event();

        // //分组的开关
        // $(".paste-form-body").on('click','.btngroup',function(){
        //     if($(this).hasClass("Hui-iconfont-arrow2-top")){
        //         $(this).removeClass("Hui-iconfont-arrow2-top").addClass("Hui-iconfont-arrow2-bottom");
        //         $(this).parents('.group').find('.gbody').addClass('close');//.hide();
        //     }else{
        //         $(this).removeClass("Hui-iconfont-arrow2-bottom").addClass("Hui-iconfont-arrow2-top");
        //         $(this).parents('.group').find('.gbody').removeClass("close");
        //     }
        // });
        registry_group_click_event();

        //绑定图片拖拽功能
        let boolBreak = false;
        for (let pro of _global_data_properties) {
            if (pro.attributes) {
                for (let la of pro.attributes) {
                    if (la.name == "image" && la.args1) {
                        let numCount = parseInt(la.args1);
                        if (numCount > 1) {
                            if (typeof $.fn.dragSort === 'function') {
                                if ($(`.drag_${pro.name}`).length > 0) {
                                    let dragdom = $(`.drag_${pro.name}`).dragSort({})
                                    pro.dragimages = dragdom.data('dragSort');
                                }
                            } else {
                                loadLibFile("./lib/img_drag.js", 'privateBindImgDrag');
                                boolBreak = true;
                                break;
                            }
                        }
                    }
                };
            }
            if (boolBreak) {
                break;
            }
        }

    }, 100);

    if (location.search.indexOf("model=sunobj") == -1) {
        $(".paste-btn-submit").fadeIn();
    }
}

/**
 * 点击或者选择ulitems的li事件 比如lselect selects select等
 * 合并改版 新版本
 */
function register_ulitems_click_event() {
    $(".ulitems").on('click', 'li', function () {
        if ($(this).hasClass('selected')) {
            $(this).removeClass('selected');
        } else {
            $(this).addClass('selected');
        }
        let nameElc = $(this).parents(".ulitems");
        var _name = nameElc.attr('name');
        if (_name) {
            var _pro = funcFindPropertry(_name);
            if (_pro) {
                var _maxnum = 0;
                var _attribute = funcFindAttribute(_pro.attributes, "selects");
                if (_attribute) {
                    if (_attribute.args4) {
                        _maxnum = Number(_attribute.args4);
                    }
                } else {
                    _attribute = funcFindAttribute(_pro.attributes, "lselect");
                    if (_attribute) {
                        if (_attribute.args4) {
                            _maxnum = Number(_attribute.args4);
                        }
                    }
                }
                if (_maxnum > 0) {
                    var _selnum = nameElc.find(".selected").length;
                    if (_selnum > _maxnum) {
                        if (_maxnum > 1) {
                            $(this).removeClass('selected');
                            layer.msg(`限定最多选择${_maxnum}项`);
                        } else {
                            $(this).siblings().removeClass('selected');
                        }
                    }
                    if (_maxnum == 1) {
                        var _val = $(this).attr('value');
                        handlerReloadReplace(_pro.attributes, _name, _val);
                        handlerChangeUi(_pro.attributes, _val);
                    }
                    if (_maxnum == 1 && _selnum > 0) {
                        if (typeof readPageData === 'function') {
                            readPageData(1);
                        }
                    }
                }
                if (_attribute.name == "selects") {
                    //从ui中获取选中得 使用比如{name value }
                    updateSelectText(nameElc, _pro);
                }
                handlerLoaditem(_pro);
            }
        }
    });
}

/**
 * 把多选的结果渲染到UI中
 * @param {*} $ul 
 * @param {*} namePro 
 * @returns 
 */
function updateSelectText($ul, namePro) {
    var name = $ul.attr('name');
    if (!name) return;

    var $input = $('input[name="' + name + '__sval"]');
    if (!$input.length) return;

    var $selected = $ul.find('.selectli.selected');
    var count = $selected.length;

    if (count === 0) {
        $input.val('');
        return;
    }

    var texts = $selected.map(function () {
        return $(this).text().trim();
    }).get();

    let sval = count > 1 ? '(' + count + ')' + texts.join(' ') : texts.join(' ');

    $input.val(sval);
    namePro.__selected_values = sval;
}

/**
 * 点击selects或者lselect时,弹出选择区域
 * @param {*} elc 
 */
function funcChangeSelectArea(elc) {
    var $panel = $(elc).parent().find('.ulitems');
    var rect = elc.getBoundingClientRect();
    var panel = $panel[0];

    var GAP = 5;          // 面板与触发元素的间距
    var MAX_HEIGHT = 300; // 面板最大高度
    var vw = window.innerWidth;
    var vh = window.innerHeight;

    // ---------- 1. 量面板实际高度(用 max-height 限制后的) ----------
    // 先让它可测量:display 保持,用 visibility:hidden + fixed 量高度
    var prevDisplay = panel.style.display;
    var prevVisibility = panel.style.visibility;
    var prevMaxHeight = panel.style.maxHeight;

    // 临时显示但不被看到
    panel.style.display = 'block';
    panel.style.visibility = 'hidden';
    panel.style.maxHeight = MAX_HEIGHT + 'px';

    // 量高度(此时如果内容多,会被 max-height 限制)
    var panelHeight = panel.offsetHeight || MAX_HEIGHT;
    // 如果内容超过 max-height,offsetHeight 会是 300;不够 300 就是实际高度
    var panelWidth = panel.offsetWidth || rect.width;

    // 恢复
    panel.style.display = prevDisplay;
    panel.style.visibility = prevVisibility;
    panel.style.maxHeight = prevMaxHeight;

    // ---------- 2. 垂直方向:优先下方 ----------
    var spaceBelow = vh - rect.bottom - GAP;
    var spaceAbove = rect.top - GAP;

    var top, finalHeight = Math.min(panelHeight, MAX_HEIGHT);

    if (spaceBelow >= finalHeight) {
        // 下方够 → 放下方
        top = rect.bottom + GAP;
    } else if (spaceAbove >= finalHeight) {
        // 下方不够,上方够 → 放上方(面板底边贴触发元素顶边)
        top = rect.top - GAP - finalHeight;
    } else {
        // 上下都不够 → 选空间大的一边,并把高度压到该空间
        if (spaceBelow >= spaceAbove) {
            top = rect.bottom + GAP;
            finalHeight = Math.max(0, spaceBelow);
        } else {
            finalHeight = Math.max(0, spaceAbove);
            top = rect.top - GAP - finalHeight;
        }
    }

    // 防止 top 出视口
    if (top < GAP) top = GAP;
    if (top + finalHeight > vh - GAP) {
        finalHeight = vh - GAP - top;
    }

    // ---------- 3. 水平方向:默认左对齐,右边不够就往左挪 ----------
    var left = rect.left;
    if (left + panelWidth > vw - GAP) {
        // 超出右边 → 右对齐触发元素
        left = rect.right - panelWidth;
    }
    if (left < GAP) left = GAP;

    // ---------- 4. 应用 ----------
    $panel.css({
        top: top + 'px',
        left: left + 'px',
        width: rect.width + 'px',      // 宽度还是跟触发元素对齐
        maxHeight: finalHeight + 'px', // 关键:动态限制高度
        overflowY: 'auto'              // 内容多时面板内部滚动
    });

    $panel.toggle();
}

// /**
//  * 打开和收缩多选区域 selects
//  * @param {*} elc 
//  */
// function funcChangeSelectArea(elc) {
//     var $panel = $(elc).parent().find('.ulitems');
//     var rect = elc.getBoundingClientRect();

//     $panel.css({
//         top: rect.bottom + 5 + 'px',
//         left: rect.left + 'px',
//         width: rect.width + 'px'
//     });

//     // 用 display 切换,简单可靠
//     $panel.toggle();
// }

/**
 * 载入图片拖拽功能的支持 绑定图片的拖拽功能
 * 字符串在其他地方引用了,不能修改名称
 */
function privateBindImgDrag() {
    for (let pro of _global_data_properties) {
        if (pro.attributes) {
            pro.attributes.forEach(la => {
                if (la.name == "image" && la.args1) {
                    let numCount = parseInt(la.args1);
                    if (numCount > 1) {
                        if (typeof $.fn.dragSort === 'function') {
                            if ($(`.drag_${pro.name}`).length > 0) {
                                let dragdom = $(`.drag_${pro.name}`).dragSort({})
                                pro.dragimages = dragdom.data('dragSort');
                            }
                        } else {
                            console.log('载入img_drag.js失败了?');
                        }
                    }
                }
            });
        }
    }
}

/**
 * 注册分组的点击事件
 */
function registry_group_click_event() {
    //分组的开关
    $(".paste-form-body").on('click', '.ghead', function () {
        var _current = $(this).find(".btnexcept");//展开收缩按钮
        if (_current) {
            if ($(_current).hasClass("Hui-iconfont-arrow2-top")) {
                $(_current).removeClass("Hui-iconfont-arrow2-top").addClass("Hui-iconfont-arrow2-bottom");
                $(_current).parents('.group').find('.gbody').addClass('close');//.hide();
            } else {
                $(_current).removeClass("Hui-iconfont-arrow2-bottom").addClass("Hui-iconfont-arrow2-top");
                $(_current).parents('.group').find('.gbody').removeClass("close");
            }
        }
    });
}

/**
 * 删除输入框的值
 * @param {*} elc 
 */
function handlerClean(elc) {
    var _parent = $(elc).parents('.formControls');
    if (_parent) {
        _parent.find('input,textarea').val('');
    }
}

/**
 * 加载表单的表的数据
 */
function loadHeader(obj) {
    if (obj.title) {
        $(".form-header").find(".ititle").html(obj.title);
    }
    if (obj.desc) {
        $(".form-header").find(".idesc").html(obj.desc);
    }
    if (obj.attributes) {
        _global_class_attributes = obj.attributes;
        for (var _attribute of obj.attributes) {
            switch (_attribute.name) {
                case "button":
                    {
                        if (_attribute.args1) {
                            $(".paste-btn-submit").val(_attribute.args1);
                        }
                    }
                    break;
                case "loadlib":
                    {
                        //载入资源
                        loadLibFile(_attribute.args1, _attribute.args2);
                    }
                    break;
            }
        }
    }
    //_global_attributes = o.attributes;
}


/**
 * parseForm之后的表单数据处理,处理完成后就上传接口了,所以要做一些额外的校验等
 * 读取富文本的内容
 * 读取daterange的内容
 * @param {*} _info 
 */
function FuncHandlerParseFormValue(_info) {
    if (_global_data_properties != null) {
        for (var item of _global_data_properties) {
            switch (item.dataType) {
                case "richtext":
                    {
                        //注意id不一样
                        if ($('#' + item.name + 'editor').is(':visible')) {
                            if (item.editor) {
                                item.value = item.editor.txt.html();
                                _info[item.name] = item.value;
                                var _attribute = funcFindAttribute(item.attributes, "richtext");
                                if (_attribute) {
                                    if (_attribute.args2) {
                                        _info[_attribute.args2] = item.editor.txt.text();
                                    }
                                }
                            }
                        }
                    }
                    break;
                case "markdown":
                    {
                        //注意id不一样
                        if ($('#' + item.name + 'mdeditor').is(':visible')) {
                            if (item.editor) {
                                item.value = item.editor.getMarkdown();
                                _info[item.name] = item.value;
                                if (item.value) {
                                    var _attribute = funcFindAttribute(item.attributes, "markdown");
                                    if (_attribute) {
                                        if (_attribute.args2) {
                                            _info[_attribute.args2] = item.editor.getHTML();
                                        }
                                    }
                                }
                                delete _info[`${item.name}mdeditor-html-code`];
                                delete _info[`${item.name}mdeditor-markdown-doc`];
                            }
                        }
                    }
                    break;
                case "DateTime":
                case "Guid":
                    {
                        if (!item.required) {
                            if (_info[item.name] == '' || _info[item.name] == 'null') {
                                delete _info[item.name];
                            }
                        }
                    }
                    break;
                case "fentoyuan":
                    {
                        var _value = _info[item.name];
                        if (_value) {
                            _info[item.name] = Number((_value * 100).toFixed(2));// Number(Math.fround(_value * 100));
                        }
                    }
                    break;
                case "tosize":
                    {
                        //示例34KB转化34000类似这样的,会有耗损,其实这种情况很少用
                        var _value = _info[item.name];
                        if (_value) {
                            _info[item.name] = parseFileSize(_value);
                        }
                    }
                    break;
                case "score":
                    {
                        _info[item.name] = item.value;
                    }
                    break;
                case "daterange":
                    {

                        if (item.attributes) {
                            for (let _attribute of item.attributes) {
                                if (_attribute.name == 'daterange') {
                                    var _value = _info[item.name];//获取当前选中的值
                                    if (_value) {
                                        var splits = _value.split('  ');
                                        if (splits.length == 3) {
                                            let _start = `${splits[0]} 00:00:00`;
                                            let _end = `${splits[2]} 00:00:00`;
                                            if (_attribute.args1) {
                                                // _info[_attribute.args1] = _start;
                                                setValueToSameLevel(item.name, _info, _attribute.args1, _start);
                                            }
                                            if (_attribute.args2) {
                                                if (_config.next_end_date) {
                                                    let _next_end = new Date(_end);
                                                    _next_end.setDate(_next_end.getDate() + 1);
                                                    let _next_end_str = `${_next_end.getFullYear()}-${(_next_end.getMonth() + 1).toString().padStart(2, '0')}-${_next_end.getDate().toString().padStart(2, '0')} 00:00:00`;
                                                    setValueToSameLevel(item.name, _info, _attribute.args2, _next_end_str);
                                                } else {
                                                    setValueToSameLevel(item.name, _info, _attribute.args2, _end);
                                                }
                                            }

                                            if (_attribute.args4) {
                                                switch (_attribute.args4) {
                                                    case "times":
                                                        {
                                                            let _times = new Date(_start).getTime() / 1000;
                                                            let _timee = new Date(_end).getTime() / 1000;
                                                            // _info[_attribute.args1] = _times;
                                                            // _info[_attribute.args2] = _timee;
                                                            setValueToSameLevel(item.name, _info, _attribute.args1, _times);
                                                            setValueToSameLevel(item.name, _info, _attribute.args2, _timee);
                                                        }
                                                        break;
                                                    case "timems":
                                                        {
                                                            let _times = new Date(_start).getTime();
                                                            let _timee = new Date(_end).getTime();
                                                            // _info[_attribute.args1] = _times;
                                                            // _info[_attribute.args2] = _timee;
                                                            setValueToSameLevel(item.name, _info, _attribute.args1, _times);
                                                            setValueToSameLevel(item.name, _info, _attribute.args2, _timee);
                                                        }
                                                        break;
                                                }
                                            }
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    break;
                case "outers":
                    {
                        var _dataFrom = item.dataFrom;
                        var elc = `.outers${item.name}`;
                        var lis = $(elc).find('li');
                        var _ids = new Array();
                        if (lis.length > 0) {
                            for (var k = 0; k < lis.length; k++) {
                                var ii = lis[k];
                                if (_dataFrom == 'Int32[]' || _dataFrom == 'Int64[]' || _dataFrom == 'UInt32[]' || _dataFrom == 'UInt64[]') {
                                    _ids.push(Number($(ii).attr('dataid')));
                                } else {
                                    _ids.push($(ii).attr('dataid'));
                                }
                            }
                            if (_dataFrom.indexOf("[]") > 0) {
                                _info[item.name] = _ids;
                            } else {
                                _info[item.name] = _ids.toString();
                            }

                        }
                    }
                    break;
                case "selects":
                case "lselect":
                    {
                        //基于结果进行值拼接! 可能是多个 可能是一个... .. 
                        let handlered = false;
                        var _elcs = $(`[name=${item.name}]`).find('.selected');
                        if (_elcs && _elcs.length > 0) {
                            var _array = new Array();
                            for (var k = 0; k < _elcs.length; k++) {
                                _array.push($(_elcs[k]).attr('value'));
                            }
                            if (item.dataFrom.indexOf("[]") >= 0) {
                                if (item.dataFrom == "Int32[]" || item.dataFrom == "Int64[]" || item.dataFrom == "UInt32[]" || item.dataFrom == "UInt64[]" || item.dataFrom == "number[]") {
                                    var _newarray = new Array();
                                    _array.forEach(_ary => {
                                        _newarray.push(Number(_ary));
                                    });
                                    _info[item.name] = _newarray;
                                } else {
                                    _info[item.name] = _array;
                                }
                                handlered = true;
                            }
                            if (!handlered) {
                                let isnumber = false;
                                if (item.valueType) {
                                    if (item.valueType === "number") {
                                        isnumber = true;
                                    }
                                }
                                if (isnumber) {
                                    if (_array.length == 1) {
                                        _info[item.name] = Number(_array[0]);
                                        handlered = true;
                                    }
                                }
                                if (!handlered) {
                                    var _splitchar = ',';
                                    if (item.attributes) {
                                        for (var _attribute of item.attributes) {
                                            if (_attribute.name == item.dataType) {
                                                if (_attribute.args2) {
                                                    _splitchar = _attribute.args2;
                                                }
                                                break;
                                            }
                                        }
                                    }
                                    _info[item.name] = _array.join(_splitchar);
                                }
                            }
                        }
                    }
                    break;
                case "image":
                    {
                        //这里处理图片
                        if (item.num > 1) {
                            var _read = handlerReadImages(item.name);
                            if (_read) {
                                if (item.dataFrom == "String[]") {
                                    _info[item.name] = _read.split(',');
                                } else {
                                    _info[item.name] = _read;
                                }
                            } else {
                                delete _info[item.name];
                            }
                        } else {
                            if (_info[item.name] == 'null') {
                                delete _info[item.name];
                            }
                        }
                    }
                    break;
                case "object":
                    {
                        // if (item.dataFrom == "Object") {
                        if (_map_values.has(item.name)) {
                            _info[item.name] = _map_values.get(item.name);
                        } else {
                            delete _info[item.name];
                        }
                        // }
                    }
                    break;
                case "objects":
                    {
                        if (_map_values.has(item.name)) {
                            _info[item.name] = _map_values.get(item.name);
                        } else {
                            delete _info[item.name];
                        }
                    }
                    break;
                case "splitarray":
                    {
                        var _split_char = ',';//默认值使用逗号隔开
                        var _split = funcFindAttribute(item.attributes, "splitarray");
                        if (_split) {
                            if (_split.args1) {
                                _split_char = _split.args1;
                            }
                        }
                        if (_info.hasOwnProperty(item.name)) {
                            var _val = _info[item.name];
                            if (_val) {
                                _val = _val.replace(/,/g, _split_char);
                                if (item.dataFrom == "Int32[]" || item.dataFrom == "Int64[]" || item.dataFrom == "UInt32[]" || item.dataFrom == "UInt64[]") {
                                    var strs = _val.split(_split_char);
                                    var arr = new Array();
                                    for (var ia of strs) {
                                        arr.push(Number(ia));
                                    }
                                    _info[item.name] = arr;
                                } else {
                                    _info[item.name] = _val.split(_split_char);
                                }
                            } else {
                                delete _info[item.name];
                            }

                        }
                    }
                    break;
                case "cover":
                    {
                        let _img = $(".coverts .active");
                        if (_img) {
                            item.value = _img.attr("src");
                            _info[item.name] = item.value;
                        }
                        // var imgs = $(".coverts").find("img");
                        // if (imgs.length > 0) {
                        //     var _imgs = new Array();
                        //     for (var i = 0; i < imgs.length; i++) {
                        //         _imgs.push(imgs[i].attr("src"));
                        //     }
                        //     item.value = _imgs;
                        //     var _attribute = funcFindAttribute(item.attributes, "cover");
                        //     if (_attribute) {
                        //         if (_attribute.args2) {
                        //             _info[_attribute.args2] = _imgs[0];
                        //         }
                        //     }
                        // }
                    }
                    break;
                case "sunform":
                    {
                        var _id = "frame_" + item.name;
                        var _frame = document.getElementById(_id);
                        if (_frame) {
                            var _con = _frame.contentWindow;
                            if (_con) {
                                if (typeof _con.funcSubmitForm === 'function') {
                                    var _read = _con.funcSubmitForm();
                                    if (!_read) {
                                        return;
                                    } else {
                                        _info[item.name] = _read;
                                    }
                                }
                            }
                        }
                    }
                    break;
                case "datetime":
                    {
                        var _value = null;
                        if (_info.hasOwnProperty(item.name)) {
                            _value = _info[item.name];
                        }
                        var _attribute = funcFindAttribute(item.attributes, "datetime");
                        if (_attribute) {
                            if (_attribute.args2) {
                                switch (_attribute.args2) {
                                    case "times":
                                        {
                                            if (_value) {
                                                //_value要转换成完整的数据格式!
                                                var _time = parseDate(_value).getTime();
                                                _info[item.name] = _time / 1000;
                                            }
                                        }
                                        break;
                                    case "timems":
                                        {
                                            if (_value) {
                                                var _time = parseDate(_value).getTime();
                                                _info[item.name] = _time;
                                            }
                                        }
                                        break;
                                    default:
                                        {
                                            if (_value) {
                                                var _time = parseDate(_value).Format(_attribute.args2);
                                                _info[item.name] = _time;
                                            }
                                        }
                                        break;
                                }
                            }
                        }
                    }
                    break;
                case "select":
                    {
                        if (item.valueType) {
                            if (item.valueType == "number") {
                                if (_info.hasOwnProperty(item.name)) {
                                    var _value = _info[item.name];
                                    if (typeof (_value) != "number") {
                                        _info[item.name] = Number(_value);
                                    }
                                }
                            }
                        }
                    }
                    break;
            }

            if (item.nullable) {
                var _value = null;
                if (_info.hasOwnProperty(item.name)) {
                    _value = _info[item.name];
                }
                if (!_value) {
                    delete _info[item.name];
                } else {
                    if (_value == 'null') {
                        delete _info[item.name];
                    }
                }
            }

            if (item.dataFrom == "Guid") {
                var _value = null;
                if (_info.hasOwnProperty(item.name)) {
                    _value = _info[item.name];
                }
                if (_value == 'null') {
                    _value = null;
                }
                if (!_value) {
                    delete _info[item.name];
                }
                if (!item.nullable) {
                    if (!_value) {
                        _info[item.name] = "00000000-0000-0000-0000-000000000000";
                    }
                }
            }

            //校验必填项目!!!
            if (item.attributes) {
                //部分非官方的required的校验
                var _required = funcFindAttribute(item.attributes, "required");
                if (_required) {
                    //这里好像有问题啊 如果是group展开收缩呢?
                    if (item.hidden) {
                        continue;
                    }
                    var _hidden = $(`[name=${item.name}]`).closest('.hidden');
                    if (!_hidden || _hidden.length == 0) {
                        // console.log('检验field:',item.name,' 的 required的值!',_info[item.name]);
                        if (!_info[item.name]) {
                            const $target = $(`[name=${item.name}]`);
                            if ($target.is(":hidden")) {
                                // 查找同级的第一个input[type=text]元素
                                const siblingInput = $target.siblings('input[type="text"]').first();
                                if (siblingInput.length) {
                                    // 找到了同级元素,进行后续操作
                                    layer.tips(`数据 ${item.title} 必填,请重新填写`, siblingInput, { tipsMore: true }, 1);
                                } else {
                                    console.log("未找到同级input[type=text]元素");
                                }
                            } else {
                                $(`[name=${item.name}]`).focus();
                                layer.tips(`数据 ${item.title} 必填,请重新填写`, `[name=${item.name}]`, { tipsMore: true }, 1);
                            }
                            layer.msg(`数据 ${item.title} 必填,请重新填写`);
                            //这里有问题,如果是outer的,则应该是同级别中显示的UI提示!
                            return false;
                        }
                    }
                }
            }
        }
    }

    // if (_global_class_attributes) {
    //     for (var _attribute of _global_class_attributes) {
    //         if (_attribute.name == "group") {
    //             if (_attribute.args4) {
    //                 //可能是directsun的模式
    //                 if (_attribute.args4 == "edit") {
    //                     if (_attribute.args1) {
    //                         var _group_name = _attribute.args1.split('__')[0];
    //                         if (!_info.hasOwnProperty(_group_name)) {
    //                             _info[_group_name] = null;//directsun模式,删除了内容,防止提交后后端用默认值填充了
    //                         }
    //                     }
    //                 }
    //             }
    //         }
    //     }
    // }
    // console.log(JSON.stringify(_info));
    // console.log(_info);

    return true;
}

/**
 * 解析时间字符串
 * @param {*} dateStr 
 * @returns 
 */
function parseDate(dateStr) {
    // 如果已经是Date对象,直接返回
    if (dateStr instanceof Date) return dateStr;

    // 如果是数字时间戳
    if (typeof dateStr === 'number') return new Date(dateStr);

    // 如果是字符串
    if (typeof dateStr === 'string') {
        // 处理 yyyyMMddHHmmss 格式 (14位数字)
        if (/^\d{14}$/.test(dateStr)) {
            const year = parseInt(dateStr.substring(0, 4));
            const month = parseInt(dateStr.substring(4, 6)) - 1;
            const day = parseInt(dateStr.substring(6, 8));
            const hours = parseInt(dateStr.substring(8, 10));
            const minutes = parseInt(dateStr.substring(10, 12));
            const seconds = parseInt(dateStr.substring(12, 14));
            return new Date(year, month, day, hours, minutes, seconds);
        }

        // 处理 yyyyMMddHHmm 格式 (12位数字)
        if (/^\d{12}$/.test(dateStr)) {
            const year = parseInt(dateStr.substring(0, 4));
            const month = parseInt(dateStr.substring(4, 6)) - 1;
            const day = parseInt(dateStr.substring(6, 8));
            const hours = parseInt(dateStr.substring(8, 10));
            const minutes = parseInt(dateStr.substring(10, 12));
            return new Date(year, month, day, hours, minutes, 0);
        }

        // 处理 yyyyMMdd 格式 (8位数字)
        if (/^\d{8}$/.test(dateStr)) {
            const year = parseInt(dateStr.substring(0, 4));
            const month = parseInt(dateStr.substring(4, 6)) - 1;
            const day = parseInt(dateStr.substring(6, 8));
            return new Date(year, month, day);
        }

        // 处理 yyyyMM 格式 (6位数字)
        if (/^\d{6}$/.test(dateStr)) {
            const year = parseInt(dateStr.substring(0, 4));
            const month = parseInt(dateStr.substring(4, 6)) - 1;
            return new Date(year, month, 1);
        }

        // 处理常见分隔符格式
        if (/^\d{4}-\d{2}-\d{2}/.test(dateStr)) {
            return new Date(dateStr);
        }

        // 其他格式尝试用Date解析
        const date = new Date(dateStr);
        if (!isNaN(date.getTime())) {
            return date;
        }
    }

    // 如果都无法解析,返回当前时间或抛出错误
    console.warn(`无法解析日期格式: ${dateStr} 默认访问当前的时间!`);
    return new Date();
}

/**
 * 
 * @param {*} name 对比字段 示例age或者info__age 
 * @param {*} target_info 哪个对象
 * @param {*} target_name 给哪个字段赋值,实例name val
 * @param {*} target_value 给字段赋予哪个值
 */
function setValueToSameLevel(name, target_info, target_name, target_value) {
    if (name.indexOf("__") >= 0) {
        let _last = name.lastIndexOf("__");
        let _new_name = name.substring(0, _last) + '__' + target_name;
        target_info[_new_name] = target_value;
    } else {
        target_info[target_name] = target_value;
    }
}

/**
 * 支持参数化url 会从当前得properies中获取value进行宏替换 宏的写法{{:=item.xxx}}
 * TODO 这里有个问题,如果参数化的url中有多个参数,且有些参数没有值,这时候应该怎么处理?目前的做法是直接把这个参数去掉了,
 * 可能会导致接口访问错误,所以后续得优化成如果没有值就替换成空字符串,或者直接替换成null字符串,或者干脆不替换这个参数了,这个需要根据实际情况来定了!
 * 会组合当前url的query,以便给后续使用,如果不要当前的url,则使用handlerMicroString
 * @param {*} _url 
 * @returns 
 */
function handlerBuildDynamicUrl(_url) {

    var newUrl = handlerMicroString(_url);
    const urlParts = newUrl.split('?');
    let queryString = urlParts[1] || '';
    const queryParams = new URLSearchParams(queryString);
    let baseUrl = urlParts[0];//基础
    var query = location.search;
    if (!query || query.indexOf("?") == -1) {
        return newUrl;
    }

    //从当前的url中获取query参数,组合到新的url中
    if (query) {
        const currentQueryParams = new URLSearchParams(query);
        for (const [key, value] of currentQueryParams.entries()) {
            if (!queryParams.has(key)) {
                queryParams.append(key, value);
            }
        }
    }
    const newQueryString = queryParams.toString();
    _url = baseUrl + (newQueryString ? `?${newQueryString}` : '');
    return _url;

}

/**
 * 动态构建信息 
 * 后续用handlerMicroString更合理
 * 基于{{:=item.property}}的宏处理,替换为对应的属性值
 * @param {string} inputStr 示例:<a href="./page/?id={{:=item.id}}" title="{{:=item.name}}">{{:=item.id}}</a>
 * @returns {string} 替换后的字符串
 */
function handlerBuildDynamicData(inputStr) {
    return handlerMicroString(inputStr);
}

/**
 * 动态构建信息 使用global_data_properties 和 当前得Url 中的数据进行替换
 * 基于{{:=item.property}}的宏处理,替换为对应的属性值
 * @param {string} inputStr 示例:<a href="./page/?id={{:=item.id}}" title="{{:=item.name}}">{{:=item.id}}</a>
 * @param {Array} arrModel 数组处理方式,如果不填写使用ids=1&ids=2的模式,如果填写表示用1,2的模式
 * @returns {string} 替换后的字符串
 */
function handlerMicroString(inputStr, arrModel) {
    // 匹配所有{{:=item.property}}模式
    const regex = /{{:=item\.(\w+)}}/g;
    // 存储所有匹配到的变量
    const variables = [];
    let match;
    // 收集所有变量
    while ((match = regex.exec(inputStr)) !== null) {
        variables.push({
            fullMatch: match[0],      // 完整匹配,如:{{:=item.id}}
            propertyName: match[1],   // 属性名,如:id
            index: match.index        // 在字符串中的位置
        });
    }
    // 如果没有找到变量,直接返回原字符串
    if (variables.length === 0) {
        return inputStr;
    }
    // 创建一个副本用于替换
    let result = inputStr;
    // 使用倒序替换,避免索引位置变化问题
    variables.sort((a, b) => b.index - a.index);
    //直接从当前表单读取数据
    var formData = null;//可能当前不是表单页面
    if (typeof readFormDataSkipValidity === 'function') {
        formData = readFormDataSkipValidity();
    }
    //当前url中的query
    let mapVals = handlerReadQueryFromSearch(location.search);
    for (const variable of variables) {
        let found = false;
        let curVal = null;

        // 1. 表单数据
        if (formData && formData.hasOwnProperty(variable.propertyName)) {
            const val = formData[variable.propertyName];
            if (val !== undefined && val !== null) {
                curVal = val;
                found = true;
            }
        }

        // 2. 元数据
        if (!found && _global_data_properties) {
            const property = funcFindPropertry(variable.propertyName);
            if (property && property.value !== undefined && property.value !== null) {
                curVal = property.value;
                found = true;
            }
        }

        // 3. URL参数
        if (!found && mapVals.has(variable.propertyName)) {
            const val = mapVals.get(variable.propertyName);
            if (val !== undefined && val !== null) {
                curVal = val;
                found = true;
            }
        }

        // 4. 替换或删除
        if (found) {
            // 有值:正常替换
            result = privaiteRegexReplace(curVal, arrModel, variable, result);
        } else {
            // 没值:删除整个参数
            result = privateRemoveParamFromUrl(result, variable);
        }
    }
    return result;
}

/**
 * 从URL中删除包含占位符的参数
 * @param {string} url 完整的URL字符串
 * @param {object} variable 变量对象 { fullMatch: '{{:=item.id}}', propertyName: 'id' }
 * @returns {string} 删除参数后的URL
 */
function privateRemoveParamFromUrl(url, variable) {
    // 转义特殊字符
    const escapedMatch = variable.fullMatch.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

    // 匹配几种情况:
    // 1. &id={{:=item.id}}  → 删除 &id=xxx
    // 2. ?id={{:=item.id}}  → 删除 ?id=xxx 或 ?id=xxx&  → 变成 ? 或 空
    // 3. id={{:=item.id}}   → 删除 id=xxx

    // 情况1: 删除 &参数名=占位符 (中间可能有其他参数)
    let result = url.replace(new RegExp(`&${variable.propertyName}=${escapedMatch}`, 'g'), '');

    // 情况2: 删除 ?参数名=占位符 (开头)
    // 如果是 ?id=xxx  → 删除后变成 ''
    // 如果是 ?id=xxx&other=yyy → 删除后变成 ?other=yyy
    result = result.replace(new RegExp(`\\?${variable.propertyName}=${escapedMatch}(&)?`, 'g'), (match, amp) => {
        // 如果有 &,说明后面还有参数,保留 ?
        return amp ? '?' : '';
    });

    // 情况3: 如果占位符不在参数中(比如在path中),直接替换为空
    result = result.replace(new RegExp(escapedMatch, 'g'), '');

    // 清理多余的 ? 和 &
    // 如果 URL 以 ?& 开头,修复为 ?
    result = result.replace(/^\?&/, '?');
    // 如果 URL 以 & 开头,修复为 ?
    result = result.replace(/^&/, '?');
    // 如果 URL 以 ?$ 结尾(只有?没有参数),去掉 ?
    result = result.replace(/\?$/, '');
    // 删除多余的 & 在 ? 后面
    result = result.replace(/\?&/, '?');

    return result;
}

/**
 * 基于正则表达式的替换方法,处理数组和单值的情况
 * @param {*} curVal 
 * @param {*} arrModel 
 * @param {*} variable 
 * @param {*} result 
 * @returns 
 */
function privaiteRegexReplace(curVal, arrModel, variable, result) {
    if (Array.isArray(curVal)) {
        if (arrModel && arrModel.length > 0) {
            curVal = curVal.join(arrModel);
        } else {
            // ids=[1,2,3] → "1&ids=2&ids=3"
            curVal = curVal.map((v, index) => {
                return index === 0 ? v : `${variable.propertyName}=${v}`;
            }).join('&');
        }
    }
    const regexEscaped = variable.fullMatch.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    return result.replace(new RegExp(regexEscaped, 'g'), curVal);
}

/**
 * 读取location.search中的query参数,支持重复参数,并将其存储在一个Map中
 * @param {*} search 
 */
function handlerReadQueryFromSearch(search) {
    // 当前url中的query - 支持重复参数
    let pars = new URLSearchParams(search);
    let mapVals = new Map();
    for (const [key, value] of pars.entries()) {
        // 如果已经存在,改为存储数组
        if (mapVals.has(key)) {
            const existing = mapVals.get(key);
            if (Array.isArray(existing)) {
                existing.push(value);
            } else {
                mapVals.set(key, [existing, value]);
            }
        } else {
            mapVals.set(key, value);
        }
    }
    return mapVals;
}

/**
 * 为输入框添加对长度显示的支持
 */
function funcAppendInputLength() {
    var inputarr = $(".newform").find("input[type=text],textarea,input[type=password]")
    for (let i = 0; i < inputarr.length; i++) {
        if ($(inputarr[i]).attr('maxlength')) {
            if ($(inputarr[i]).css("display") == 'none') {
                continue;
            }
            $(inputarr[i]).parent().css('position', 'relative')
            var str = `<span class="spanlen">${$(inputarr[i]).val().length}/${$(inputarr[i]).attr('maxlength')}</span>`
            $(inputarr[i]).after(str)
            $(inputarr[i]).on("input", function () {
                var numstr = $(this).val().length + '/' + $(this).attr('maxlength')
                $(this).siblings('.spanlen').text(numstr)
            })
        }
    }
}

/**
 * 基于递归方法,把一级数据拆分为多级,name中包含__的分拆一级,如果是__num__的分拆数组
 * @param {*} flattenedData 
 * @returns 
 */
function convertFlattenedToNested(flattenedData) {
    // 判断是否是数组格式(键名中包含数字索引 xx__xx )
    const isArrayFormat = Object.keys(flattenedData).some(key => /^\d+__/.test(key));
    if (isArrayFormat) {
        // 如果是数组格式,初始化结果为数组
        const result = [];
        for (const key in flattenedData) {
            if (flattenedData.hasOwnProperty(key)) {
                const value = flattenedData[key];
                const parts = key.split('__');
                // 递归构建嵌套结构
                buildNestedStructure(result, parts, value);
            }
        }
        //   const _result = result.filter((obj)=>{
        //     return Object.values(obj).length>0;
        //   });
        //   return result;
        return removeEmptyValues(result);
    } else {
        // 否则,初始化结果为对象
        const result = {};
        for (const key in flattenedData) {
            if (flattenedData.hasOwnProperty(key)) {
                const value = flattenedData[key];
                const parts = key.split('__');
                // 递归构建嵌套结构
                buildNestedStructure(result, parts, value);
            }
        }
        //   return result;
        return removeEmptyValues(result);
    }
}

/**
 * 递归去除空值 为撒要去除空值呢?
 * 因为如果有空值提交到后端,
 * 可能会导致后端用默认值填充了,
 * 所以这里直接去掉了,
 * 当然也可以替换成null字符串或者空字符串,
 * 这个需要根据实际情况来定了! 
 * 目前的做法是直接去掉了,
 * 可能会导致接口访问错误,
 * 所以后续得优化成如果没有值就替换成空字符串,
 * 或者直接替换成null字符串,
 * 或者干脆不替换这个参数了,
 * 这个需要根据实际情况来定了!
 * @param {*} obj 
 * @returns 
 */
function removeEmptyValues(obj) {
    if (_config.remove_empty) {
        if (Array.isArray(obj)) {
            // 如果是数组,递归处理每个元素
            return obj
                .map(item => removeEmptyValues(item)) // 递归处理每个元素
                .filter(item => item !== null && item !== undefined && item !== ''); // 过滤掉空值
        } else if (typeof obj === 'object' && obj !== null) {
            // 如果是对象,递归处理每个属性
            const result = {};
            for (const key in obj) {
                if (obj.hasOwnProperty(key)) {
                    const value = removeEmptyValues(obj[key]); // 递归处理属性值
                    // 如果值不是空值,则保留该属性
                    if (value !== undefined && value !== '') {
                        // if (value !== null && value !== undefined && value !== '') {
                        result[key] = value;
                    }
                }
            }
            // 如果对象没有任何属性,返回 undefined(表示移除该对象)
            return Object.keys(result).length > 0 ? result : undefined;
        } else {
            // 如果是基本类型,直接返回
            return obj;
        }
    } else {
        if (Array.isArray(obj)) {
            // 如果是数组,递归处理每个元素
            return obj
                .map(item => removeEmptyValues(item)) // 递归处理每个元素
                .filter(item => item !== null && item !== undefined); // 过滤掉空值
            // .filter(item => item !== null && item !== undefined && item !== ''); // 过滤掉空值
        } else if (typeof obj === 'object' && obj !== null) {
            // 如果是对象,递归处理每个属性
            const result = {};
            for (const key in obj) {
                if (obj.hasOwnProperty(key)) {
                    const value = removeEmptyValues(obj[key]); // 递归处理属性值
                    // 如果值不是空值,则保留该属性
                    if (value !== undefined) {
                        result[key] = value;
                    }
                    //if (value !== null && value !== undefined && value !== '') {
                }
            }
            // 如果对象没有任何属性,返回 undefined(表示移除该对象)
            return Object.keys(result).length > 0 ? result : undefined;
        } else {
            // 如果是基本类型,直接返回
            return obj;
        }
    }
}

/**
 * 递归赋值
 * @param {*} current 
 * @param {*} parts 
 * @param {*} value 
 * @returns 
 */
function buildNestedStructure(current, parts, value) {
    if (current) {
        const part = parts[0]; // 当前处理的键部分

        // 如果是最后一个部分,直接赋值
        if (parts.length === 1) {
            current[part] = value;
            return;
        }

        // 判断下一级是否是数组
        if (!isNaN(parts[1])) {
            const index = parseInt(parts[1]);

            // 如果当前部分不存在,创建一个新的数组
            if (!current[part]) {
                current[part] = [];
            }

            // 获取或创建数组元素
            while (current[part].length <= index) {
                current[part].push({});
            }

            // 递归处理剩余部分
            buildNestedStructure(current[part][index], parts.slice(2), value);
        } else {
            // 如果当前部分不存在,创建一个新的对象
            if (!current[part]) {
                current[part] = {};
            }

            // 递归处理剩余部分
            buildNestedStructure(current[part], parts.slice(1), value);
        }
    }
}


/**
 * 删除objects的某一项
 * @param {*} elc 
 */
function handlerRemoveObjectItem(elc) {
    var _li = $(elc).parents("li");
    var _name = _li.attr('dataname');
    var _id = _li.attr('dataid');
    var objs = _map_values.get(_name);
    if (objs) {
        var _porperty = funcFindPropertry(_name);
        if (_porperty) {
            for (var i = 0; i < objs.length; i++) {
                if (objs[i]["_id"].toString() == _id) {
                    objs.splice(i, 1);
                    break;
                }
            }
        }
    }
    _li.remove();
    return false;
}

/**
 * 使用outer选择外表的ID,和显示对应的友好名称 navigater的升级版
 * 这个是给Form使用的
 * @param {*} elc 
 */
function handler_outer_value(elc) {
    var _name = $(elc).attr('dataname');
    if (_global_data_properties) {
        var find = funcFindPropertry(_name);
        if (find) {
            if (find.dataType == "outer") {
                var _attribute = funcFindAttribute(find.attributes, 'outer');
                if (_attribute) {
                    // if (typeof funcLinkOuterOpenSelect == "function") {
                    funcLinkOuterOpenSelect(`选择${find.title}`, _attribute.args1, '1', (obj) => {
                        if (obj) {
                            $(elc).val(handlerColumnValue(obj, _attribute.args4));
                            //用parent是因为可能是在某一个gourp内部,这样不会影响其他的
                            // $(elc).parent().find(`[name=${_name}]`).val(obj[_attribute.args3]);
                            // //args3可能是多个... .. .
                            // find.value = obj[_attribute.args3];

                            if (_attribute.args3.indexOf(",") > 0) {
                                //多个模式
                                var ids = _attribute.args3.split(",");
                                let zindex = 0;
                                for (let icol of ids) {
                                    zindex++;
                                    if (zindex == 1) {
                                        $(elc).parent().find(`[name=${_name}]`).val(obj[icol]);
                                        find.value = obj[icol];
                                    } else {
                                        $(elc).parent().find(`[name=${icol}]`).val(obj[icol]);
                                    }
                                }
                            } else {
                                //单个模式
                                $(elc).parent().find(`[name=${_name}]`).val(obj[_attribute.args3]);
                                find.value = obj[_attribute.args3];
                            }
                            //扩展到加载对象中,比如extendUser _attribute.args2
                            if (_attribute.args2) {
                                _global_expend_object[_attribute.args2] = obj;
                            }
                            handlerLoaditem(find);
                            if (_config.search_after_selected) {
                                if (typeof readPageData == 'function') {
                                    readPageData(1);
                                }
                            }
                        }
                    });
                }
            }
            if (find.dataType == "outers") {
                var _attribute = funcFindAttribute(find.attributes, 'outers');
                if (_attribute) {
                    funcLinkOuterOpenSelect(`选择${find.title}`, _attribute.args1, '100', (objs) => {
                        handler_display_outers_toui(objs, _attribute, elc);
                        handlerLoaditem(find);
                    });
                }
            }
        }
    }
}

/**
 * 给table的edit模式的outer使用
 * @param {*} elc 
 */
function handler_edit_outer(elc) {
    var _name = $(elc).attr('dataname');
    if (_global_list_properties) {
        var find = funcQueryPropertry(_name);
        if (find) {
            if (find.dataType == "outer") {
                var _attribute = funcFindAttribute(find.attributes, 'outer');
                if (_attribute) {
                    funcLinkOuterOpenSelect(`选择${find.title}`, _attribute.args1, '1', (obj) => {
                        if (obj) {
                            $(elc).val(handlerColumnValue(obj, _attribute.args4));
                            $(elc).parent().find(`[name=${_name}]`).val(obj[_attribute.args3]);
                            find.value = obj[_attribute.args3];
                            //扩展到加载对象中,比如extendUser _attribute.args2
                            if (_attribute.args2) {
                                _global_expend_object[_attribute.args2] = obj;
                            }
                        }
                    });
                }
            }
        }
    }
}


/**
 * 打开选择一个外表的值
 */
function funcLinkOuterOpenSelect(_title, _className, num, callback) {
    var _url = _className;
    if (_url.indexOf('/') == -1) {
        _url = `${handlerPasteFormPath()}index.html?model=select&path=${_className}`;
    }
    _url = handlerBuildDynamicUrl(_url);
    open_select(_title, _url + '&select_num=' + num, "", "", callback);
}

/**
 * 显示外选择的内容到UI
 * @param {*} objs 
 * @param {*} _attribute 
 * @param {*} elc 
 */
function handler_display_outers_toui(objs, _attribute, elc) {
    if (!Array.isArray(objs)) {
        objs = [objs];
    } else {
        // $(elc).parents('.outers').find('.ulouter').empty();//如果数据要从多个页中获取,不能用这个
    }
    for (var obj of objs) {
        if (obj) {
            var _name = handlerColumnValue(obj, _attribute.args4);// (obj[_attribute.args4]);
            var _id = (obj[_attribute.args3]);
            //判断当前列表是否存在,不存在则新增
            var par = $(elc).parents('.outers').find(`[dataid="${_id}"]`);
            if (par.length == 0) {
                var _ul = $(elc).parents('.outers').find('.ulouter');
                if (_ul) {
                    _ul.append(`<li dataid="${_id}">${_name}<span class="outer_close" onclick="$(this).parents('li').remove();">x</span></li>`);
                }
            }
        }
    }

    if (_attribute.args2) {
        _global_expend_object[_attribute.args2] = objs;
    }

}

/**
 * 使用object的模式,进行外部表单的创建,一般用于创建的时候
 * 这里要做页面的map处理,回传的时候基于对象的类型是object格式 还是string格式
 * @param {*} elc 
 */
function handler_object_value(elc) {
    var _name = $(elc).attr('dataname');
    if (_global_data_properties) {
        var find = funcFindPropertry(_name);
        if (find) {
            var _attribute = funcFindAttribute(find.attributes, 'object');
            if (_attribute) {
                funcObjectOpenSelect(`选择${find.title}`, _attribute.args1, find.session_key || '', (obj) => {
                    if (obj) {
                        $(elc).val(handlerColumnValue(obj, _attribute.args4));
                        $(elc).parent().find(`[name=${_name}]`).val(obj[_attribute.args3]);
                        _map_values.set(_name, obj);
                    }
                });
            } else {
                _attribute = funcFindAttribute(find.attributes, 'objects');
                if (_attribute) {
                    funcObjectOpenSelect(`选择${find.title}`, _attribute.args1, find.session_key || '', (obj) => {
                        if (Array.isArray(obj)) {
                            // _map_values.delete(_name);
                            for (var _obj of obj) {
                                displayObjectsToUI(_obj, _name, find);
                            }
                        } else {
                            displayObjectsToUI(obj, _name, find);
                        }
                    });
                }
            }
        }
    }
}

/**
 * 显示Objects的数据到UI
 * @param {*} obj 
 * @param {*} _name 
 * @param {*} find 
 */
function displayObjectsToUI(obj, _name, find) {
    if (obj) {
        var objs = _map_values.get(_name);
        if (!objs) {
            objs = new Array();
        }
        var _find_index = -1;
        var _find_id = handlerColumnValue(obj, find.display_id);
        for (var k = 0; k < objs.length; k++) {
            if (_find_id == objs[k]._id) {
                _find_index = 0;
                break;
            }
        }
        if (_find_index == -1) {
            objs.push(obj);
        } else {
            objs[_find_index] = obj;
        }

        var _ihtml = '';
        objs.forEach(oitem => {
            var _display = handlerColumnValue(oitem, find.display_name);
            var _id = handlerColumnValue(oitem, find.display_id);
            oitem._display = _display;
            oitem._id = _id;
            _ihtml += `<li dataid="${_id}" dataname="${_name}" onclick="handlerEditObject(this);">${_display}<span class="outer_close" onclick="handlerRemoveObjectItem(this);">x</span></li>`;
        });
        $(`.outers${_name}`).html(_ihtml);
        _map_values.set(_name, objs);
    }
}

// /**
//  * 读取linkquery的参数以&xxx=yyy&zzz=www的形式
//  * @returns 
//  */
// function handlerBuildLinkQueryUrl() {
//     var _linkquery = "";
//     if (_global_class_attributes) {
//         _global_class_attributes.forEach(_attribute => {
//             if (_attribute.name == "linkquery") {
//                 if (_attribute.args1) {
//                     var _args = _attribute.args1.split(',');
//                     _args.forEach(arg => {
//                         var _argval = readQueryFromSearch(arg);
//                         if (_argval != null) {
//                             _linkquery += `&${arg}=${_argval}`;
//                         }
//                     });
//                 }
//             }
//         });
//     }
//     return _linkquery;
// }

// /**
//  * 从当前url中获取对应的参数
//  */
// function readQueryFromSearch(key) {
//     // 获取参数
//     var url = window.location.search;
//     // 正则筛选地址栏
//     var reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)");
//     // 匹配目标参数
//     var result = url.substr(1).match(reg);
//     //返回参数值
//     return result ? decodeURIComponent(result[2]) : null;
// }

/**
 * 读取linkquery的参数以&xxx=yyy&zzz=www的形式
 * 25.04.13 适配array模式 注意Object的要自己实现,建议使用sessionStorage的方式
 * @returns {string} 构建好的linkquery字符串
 */
function handlerBuildLinkQueryUrl() {
    let linkquery = [];
    if (Array.isArray(_global_class_attributes)) {
        for (const attribute of _global_class_attributes) {
            if (attribute.name === "linkquery" && attribute.args1) {
                // 如果是 "*",获取所有URL参数
                if (attribute.args1 === "*") {
                    const allParams = getAllUrlParams();
                    for (const [key, values] of Object.entries(allParams)) {
                        for (const value of values) {
                            linkquery.push(`${key}=${value}`);
                        }
                    }
                } else {
                    // 原有的逻辑:只获取指定的参数
                    const args = attribute.args1.split(',');
                    for (const arg of args) {
                        const argvals = readQueryFromSearch(arg);
                        if (argvals.length > 0) {
                            for (const argval of argvals) {
                                linkquery.push(`${arg}=${argval}`);
                            }
                        }
                    }
                }
            }
        }
    }
    return linkquery.length > 0 ? '&' + linkquery.join('&') : '';
}

/**
 * 获取URL中的所有参数
 * @returns {Object} 包含所有参数及其值的对象,格式:{key: [value1, value2]}
 */
function getAllUrlParams() {
    const url = window.location.search;
    const params = {};

    if (url.length <= 1) {
        return params;
    }

    const queryString = url.substring(1); // 去掉 '?'
    const pairs = queryString.split('&');

    for (const pair of pairs) {
        const [key, value] = pair.split('=');
        if (key) {
            const decodedKey = decodeURIComponent(key);
            const decodedValue = value ? decodeURIComponent(value) : '';

            if (!params[decodedKey]) {
                params[decodedKey] = [];
            }
            params[decodedKey].push(decodedValue);
        }
    }

    return params;
}

/**
 * 从当前url中获取对应的参数
 * 25.04.13 适配array模式 注意Object的要自己实现,建议使用sessionStorage的方式
 * @param {string} key - 要获取的参数名
 * @param {string} [urlStr=window.location.search] - 可选的URL字符串,默认为当前页面的查询字符串
 * @returns {Array<string>} 参数值数组,如果未找到则返回空数组
 */
function readQueryFromSearch(key, urlStr) {
    const url = urlStr || window.location.search;
    const reg = new RegExp(`[?&]${key}=([^&]*)`, 'g');
    const results = [];
    let match;
    while ((match = reg.exec(url)) !== null) {
        results.push(decodeURIComponent(match[1]));
    }
    return results;
}

/**
 * 从字符串或者当前地址中获取某一个参数,会返回第一个,如果是需要返回数组用另外一个函数readQueryFromSearch
 * @param {*} key 
 * @param {*} urlStr 
 * @returns 
 */
function readFirstQueryFromSearch(key, urlStr) {
    const url = urlStr || window.location.search;
    const reg = new RegExp(`[?&]${key}=([^&]*)`, 'g');
    const results = [];
    let match;
    while ((match = reg.exec(url)) !== null) {
        results.push(decodeURIComponent(match[1]));
    }
    return results.length == 0 ? null : results[0];
}



/**
 * 基于linkquery的模式,自动整理query
 * @param {*} url 
 * @returns 
 */
function handlerAutoQueryIncludeLinkQuery(url) {
    var _link = {};
    if (_global_class_attributes) {
        _global_class_attributes.forEach(_attribute => {
            if (_attribute.name == "linkquery") {
                if (_attribute.args1) {
                    //var _args = _attribute.args1.split(',');
                    //_args.forEach(arg => {
                    //    var _argval = _apigetquery(arg);
                    //    if (_argval != null) {
                    //        // _linkquery += `&${arg}=${_argval}`;
                    //        _link[arg] = _argval;
                    //    }
                    //});
                    if (_attribute.args1 === "*") {
                        const allParams = getAllUrlParams();
                        for (const [key, values] of Object.entries(allParams)) {
                            for (const value of values) {
                                if (value) {
                                    _link[key] = value;
                                }
                            }
                        }
                    } else {
                        var _args = _attribute.args1.split(',');
                        _args.forEach(arg => {
                            var _argval = _apigetquery(arg);
                            if (_argval != null) {
                                _link[arg] = _argval;
                            }
                        });
                    }
                }
            }
        });
    }
    return appendQueryParams(url, _link);
}

/**
 * 解析 URL 并追加参数(如果参数不存在)
 * @param {string} url - 原始 URL
 * @param {Object} queryMap - 包含需要追加的 query 键值对的对象
 * @returns {string} - 处理后的 URL
 */
function appendQueryParams(url, queryMap) {
    if (typeof url !== 'string' || !url) {
        return url;
    }

    if (!queryMap || typeof queryMap !== 'object' || Array.isArray(queryMap)) {
        return url;
    }

    // 解析 URL 的路径、参数和哈希部分
    const [baseUrl, hash] = url.split('#');
    const [path, queryString] = baseUrl.split('?');

    // 解析现有的查询参数
    const queryParams = new URLSearchParams(queryString || '');

    // 遍历 queryMap,如果参数不存在则追加
    for (const [key, value] of Object.entries(queryMap)) {
        if (value !== undefined && value !== null && !queryParams.has(key)) {
            queryParams.set(key, value);
        }
    }

    // 拼接处理后的 URL
    const newQueryString = queryParams.toString();
    const newUrl = newQueryString ? `${path}?${newQueryString}` : path;

    // 如果有哈希部分,重新追加
    return hash ? `${newUrl}#${hash}` : newUrl;
}


/**
 * 基于表达式获取对象数据,返回字符串的,用于objects的+字段
 * @param {*} find 
 * @param {*} columnstr 
 * @returns 
 */
function handlerColumnValue(find, columnstr) {
    if (columnstr.indexOf("+") > 0) {
        var _strs = columnstr.split('+');
        var _aval = '';
        _strs.forEach(ii => {
            if (find.hasOwnProperty(ii)) {
                _aval += find[ii];
            } else {
                _aval += ii;
            }
        });
        return _aval;
    }
    return find[columnstr];
}

/**
 * 编辑objects的单个内容
 * @param {*} elc 
 */
function handlerEditObject(elc) {
    var _li = $(elc);
    var _name = _li.attr('dataname');
    var _id = _li.attr('dataid');
    var objs = _map_values.get(_name);
    if (objs) {
        var _porperty = funcFindPropertry(_name);
        if (_porperty) {
            var _attribute = funcFindAttribute(_porperty.attributes, "objects");
            if (_attribute) {
                var _current = null;
                for (var i = 0; i < objs.length; i++) {
                    if (objs[i]["_id"].toString() == _id) {
                        _current = objs[i];
                        break;
                    }
                }
                let session_key = `${_porperty.name}_000`;
                if (_current) {
                    //查看object
                    sessionStorage.setItem(session_key, JSON.stringify(_current));
                    funcObjectOpenSelect(`编辑${_current[_porperty.display_name]}`, _attribute.args1, session_key || '', (obj) => {
                        displayObjectsToUI(obj, _name, _porperty);
                    });
                } else {
                    sessionStorage.removeItem(session_key);
                }
            }
        }
    }
}

/**
 * 加载来源参数内容 在form渲染前,所以影响的是Property的信息
 * v25.04.13
 * @param {*} properties 
 */
function LoadQuery(properties) {
    properties.forEach(item => {
        if (item.attributes) {
            item.attributes.forEach(_attribute => {
                if (_attribute.name == 'query') {
                    if (_attribute.args1) {
                        let queryValArray = readQueryFromSearch(_attribute.args1);
                        if (queryValArray.length > 0) {
                            //这里还要处理,比如splitarray的特性等... 
                            switch (item.dataType) {
                                case "Int32": case "UInt32": case "Int64": case "UInt64":
                                    {
                                        item.value = Number(queryValArray[0]);
                                    }
                                    break;
                                case "Int32[]": case "UInt32[]": case "Int64[]": case "UInt64[]":
                                    {
                                        let _varray = new Array();
                                        for (let a of queryValArray) {
                                            _varray.push(Number(a));
                                        }
                                        item.value = _varray;
                                    }
                                    break;
                                default:
                                    {
                                        if (item.dataType.indexOf("Enum") == 0) {
                                            if (item.dataType.indexOf("[]") >= 0) {
                                                let _varray = new Array();
                                                for (let a of queryValArray) {
                                                    _varray.push(Number(a));
                                                }
                                                item.value = _varray;
                                            } else {
                                                item.value = Number(queryValArray[0]);
                                            }
                                        } else {
                                            if (item.dataType.indexOf("[]") >= 0) {
                                                item.value = queryValArray;
                                            } else {
                                                item.value = queryValArray[0];
                                            }
                                        }
                                    }
                                    break;
                            }
                            //如果事objects 我只是想一会提交的时候一并提交呢???
                            if (_attribute.args2) {
                                item.hidden = true;
                            }
                        }
                    }
                }
            });
        }
    });
}

/**
 * 内容嵌入后,执行一些加载绑定等! 
 */
function FormLoaded(properties) {
    properties.forEach(item => {
        if (item.dataType == "daterange") {
            if (item.name) {
                HandlerInitDateRange(item.name, item.value);
            }
        }
        if (item.dataType == "richtext") {
            InitRichEditor(item);//可以有多个富文本 {{name}}editortoolbar {{name}}editorbody window.{{name}}editor
        }
        if (item.dataType == "markdown") {
            InitMarkDownEditor(item);
        }
        if (item.dataType == "score") {
            $(`.raty${item.name}`).ratyli({
                step: false,
                onRated: function (score) {
                    item.value = score;
                }
            });
        }
        // if (item.attributes) {
        //     item.attributes.forEach(_attribute => {
        //         if (_attribute.name == 'query') {
        //             if (_attribute.args1) {
        //                 var _query_val = _apigetquery(_attribute.args1);
        //                 if (_query_val != null && _query_val != undefined) {
        //                     $(`[name=${item.name}]`).val(_query_val);
        //                     if (_attribute.args2) {
        //                         $(`[name=${item.name}]`).parents(".row").hide();
        //                     }
        //                 }
        //             }
        //         }
        //     });
        // }
    });
}

/**
 * 点击删除图片
 * @param {*} elc 
 */
function handlerTapImage(elc) {
    if (!$(elc).hasClass("active")) {
        $(elc).addClass("active").siblings().removeClass("active");
    }
}


/**
 * 更新封面的图片的选择项
 */
function funcUpdateImages() {
    if ($(".coverts").length > 0) {
        let imgs = new Array();
        $('.paste-form-body img').each(function () {
            var src = $(this).attr('src');
            if (src != 'undefined' && src != undefined && src != null && src != '') {
                if (imgs.indexOf(src) == -1) {
                    imgs.push(src);
                }
            }
        });
        var _html = '';
        var _zindex = 0;
        for (let src of imgs) {
            if (_zindex == 0) {
                _html += `<img class="cover_img active" onerror="this.onerror=null; this.src='./lib/default.png';" onclick="handlerTapImage(this);" src="${src}">`;
            } else {
                _html += `<img class="cover_img" onerror="this.onerror=null; this.src='./lib/default.png';" onclick="handlerTapImage(this);" src="${src}">`;
            }
            _zindex++;
        }
        $(".coverts").html(_html);
    }
}

/**
 * 初始化Markdown编辑器
 * @param {*} item 
 */
function InitMarkDownEditor(item) {
    var _editor = `${item.name}mdeditor`;
    var _high = 600;
    var _upload_url = `/${readRootPath()}/Upload/Markdown`;
    var _attribute = funcFindAttribute(item.attributes, "markdown");
    if (_attribute) {
        if (_attribute.args1) {
            var _h = Number(_attribute.args1);
            if (_h) {
                _high = _h;
            }
        }
        //2给另外一个值了 比如richtext回传txt markdown回传 html
        if (_attribute.args3) {
            _upload_url = handlerBuildDynamicUrl(_attribute.args3);
        }
    }

    BtnExpend = editormd.BtnMenu;

    var _mdEditor = editormd(_editor, {
        height: _high,
        saveHTMLToTextarea: true,
        imageUpload: true,
        imageFormats: ["jpeg", "jpg", "gif", "png", "bmp", "webp"],
        imageUploadURL: _upload_url,
        imageUploadHeaders: { token: readToken() },
        markdown: item.value || '',
        path: '../lib/editor.md/lib/',
        // 自定义工具栏图标
        toolbarIcons: function () {
            // 添加自定义图标到默认工具栏
            return editormd.toolbarModes.full.concat(["insertTime"]);
        },

        // 自定义图标样式(使用 Font Awesome)
        toolbarIconsClass: {
            insertTime: "fa-clock-o" // 时钟图标
        },

        // 自定义图标点击事件
        toolbarHandlers: {
            insertTime: function (cm, icon, cursor, selection) {
                // 获取当前时间
                const now = new Date();
                const timeString = now.toLocaleTimeString();

                // 插入时间到编辑器
                // this.insertText(`当前时间: ${timeString}`);

                // 在光标位置插入文本,选中文本会被替换
                // cm.replaceSelection("插入的文本");

                // 示例:插入时间戳
                const time = new Date().toLocaleTimeString();
                cm.replaceSelection(`⏰ ${time}`);

                // global_load_netword_images

                // 可添加其他逻辑,如显示提示
                console.log("插入时间:", timeString);
            }
        }
    });

    if (typeof initPasteDragImg == 'function') {
        initPasteDragImg(_mdEditor);
    }
    item.editor = _mdEditor;
}

/**
 * 获取根路径 示例api/app
 * @returns 
 */
function readRootPath() {
    var root_path = "api/app";
    if (_config) {
        if (_config.root_path) {
            root_path = _config.root_path;
        }
    }
    return root_path;
}

/**
 * 初始化富文本 注意看命名规则 ui的ID的规则,要相互,支持单个页面多个富文本
 * @param {*} item 
 */
function InitRichEditor(item) {
    //注意这里的命名规则需要和ui一致
    var _toolbar = `${item.name}editorbar`;
    var _editor = `${item.name}editor`;

    var _high = 600;
    var _upload_url = `/${readRootPath()}/Upload/UpImage`;
    var _attribute = funcFindAttribute(item.attributes, "richtext");
    if (_attribute) {
        if (_attribute.args1) {
            var _h = Number(_attribute.args1);
            if (_h) {
                _high = _h;
            }
        }
        //2给另外一个值了 比如richtext回传txt markdown回传 html
        if (_attribute.args3) {
            _upload_url = handlerBuildDynamicUrl(_attribute.args3);
        }
    }

    const editor = new E(`#${_toolbar}`, `#${_editor}`) // 传入两个元素
    // 默认情况下,显示所有菜单
    editor.config.menus = [
        'head',
        'bold',
        'fontSize',
        // 'fontName',
        'italic',
        'underline',
        // 'strikeThrough',
        'indent',
        'lineHeight',
        'foreColor',
        // 'backColor',
        'link',
        // 'list',
        'todo',
        'justify',
        'quote',
        // 'emoticon',
        'image',
        // 'video',
        'table',
        'code',
        'splitLine',
        'undo',
        'redo'
    ]
    editor.config.uploadImgServer = _upload_url
    editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 2M
    editor.config.uploadImgAccept = ['jpg', 'jpeg', 'png', 'gif', 'webp']
    editor.config.uploadImgMaxLength = 3 // 一次最多上传 5 个图片
    editor.config.uploadImgHeaders = { token: readToken() }//注意这里要按照实际情况处理 这里估计要搞成配置的

    editor.config.customUploadImg = (files, insert) => {
        const formData = new FormData();
        for (let i = 0; i < files.length; i++) {
            formData.append('file', files[i]);
        }
        fetch(`${auto_root_path()}/Upload/UpImage?type=rich&size=1920*0`, {
            method: 'POST',
            headers: {
                'token': readToken()
            },
            body: formData
        })
            .then(response => {
                console.log(response);
                return response.json();
            })
            .then(result => {
                console.log(result);
                if (result.errno == 0) {
                    var _url = result.data[0].url;
                    // 插入图片到编辑器
                    insert(_url);
                    // 可以在这里添加其他自定义逻辑
                    if (_imageList.indexOf(_url) == -1) {
                        _imageList.push(_url);
                        //如果有coverts,则执行渲染操作
                    }
                    // 例如,记录上传日志
                    console.log('图片上传成功:', _url);
                } else {
                    console.error('图片上传失败:', result);
                }
            })
            .catch(error => {
                console.error('图片上传出错:', error);
            });
    };


    if (item.placeholder) {
        editor.config.placeholder = item.placeholder;
    }
    editor.create();
    if (item.value) {
        editor.txt.html(item.value);
    }
    item.editor = editor;
}
/**
 * 点击删除某一个图片
 * @param {*} elc 
 */
function handlerRemoveImageItem(event, elc) {

    event.preventDefault();  // 阻止默认行为(如 label 触发)
    event.stopPropagation(); // 阻止事件冒泡
    event.stopImmediatePropagation(); // 阻止同一元素上的其他监听器

    var _elcControlls = $(elc).parents(".formControls");
    //单图模式
    if ($(elc).attr('data-num')) {
        $(_elcControlls).find('img').attr('src', '');
        $(elc).hide();
        $(_elcControlls).find('.icon-add').show();
        $(_elcControlls).find('input[type=text]').val('');
        // event.stopImmediatePropagation();
        console.log('执行事件阻断... .. .');
        return;
    }
    //多图模式

    var _name = $(_elcControlls).find("input[type=text]").attr('name');
    $(elc).parents("li").remove();
    handlerReadImages(_name);
    //判断数量,是否显示+按钮
    var _find = funcFindPropertry(_name);
    if (_find != null) {
        if (_find.num > 1) {
            var _imageul = $(_elcControlls).find(".imageul");
            if ($(_imageul).find("li").length > _find.num) {
                $(_imageul).find("li").eq(0).hide();
            } else {
                $(_imageul).find("li").eq(0).show();
            }
        }
    }
    // event.stopImmediatePropagation();
    return false;
}

/**
 * 读取多图模式的值 并给对应的输入框赋值,为了给后面的form读取值
 * @param {*} _name 
 */
function handlerReadImages(_name) {
    var _array = new Array();
    var pars = $(`[name=${_name}]`).parents(".formControls").find("img");
    for (var k = 0; k < pars.length; k++) {
        var _img = pars[k];
        var _img_src = ($(_img).attr('src'));
        _array.push(_img_src);
    }
    if (_array.length == 0) {
        $(`[name=${_name}]`).val('');
        return '';
    } else {
        $(`[name=${_name}]`).val(_array.join(','));
        return _array.join(',');
    }
    //这里可以做数量限制... .. .
}

/**
 * 上传非图片 比如文件等
 */
function handlerUploadOnlyFile(elc) {
    var _url = `${auto_root_path()}/Upload/UpFile`;
    var _dataurl = $(elc).attr('dataurl');
    if (_dataurl) {
        _url = _dataurl;
    }
    var _type = $(elc).attr('datatype');
    if (_type) {
        _url = `${_url}${(_url.indexOf("?") >= 0 ? '&' : '?')}type=${_type}`;
    }
    var _name = $(elc).attr("id");
    var _num = 1;
    if (elc.files && elc.files.length > _num) {
        layer.msg(`选择的文件过多,至多选择${_num}个文件!`);
    }
    if (elc.files.length > 0) {
        var loadid = layer.load();
        var formData = new FormData();
        for (var k = 0; k < elc.files.length; k++) {
            formData.append(elc.files[k].name, elc.files[k]);
        }
        $.ajax({
            url: _url,
            type: 'post',
            contentType: false,
            processData: false,
            async: true,
            data: formData,
            headers: { "token": readToken() },
            success: function (obj) {
                layer.close(loadid);
                $(elc).parents(".formControls").find(`[name=${_name}]`).val(obj.data[0].url);
                elc.value = null;
            },
            error: function (res) {
                if (loadid != 0) {
                    layer.close(loadid);
                }
                elc.value = null;
                layer.msg(res.statusText, { icon: 'error', time: 3000 });
            }
        });
    } else {
        // layer.msg("请选择至少一个有效的文件!");readmemberToken
    }
}

/**
 * 处理图片的上传,这里最好限制下文件格式 这个要看实际需求 基于这个可以改造一个,上传文件的比如xlsx
 */
function handlerUploadFile(elc) {
    var _size = $(elc).attr("datasize");
    var _type = $(elc).attr("datatype");
    var _num = $(elc).attr("datanum");
    var _name = $(elc).attr("id");
    if (!_num) {
        _num = 1;
    }

    var haveNum = $(".drag_" + _name).find("img").length;
    var lessNum = _num - haveNum;
    if (elc.files && elc.files.length > lessNum) {
        layer.msg(`选择的文件过多,至多选择${lessNum}个文件!`);
        //这里还是有问题的 比如最多3个 先选择2个 后面又选择2个... .. . 
        return;
    }
    if (elc.files.length > 0) {
        var loadid = layer.load();
        var formData = new FormData();
        for (var k = 0; k < elc.files.length; k++) {
            formData.append(elc.files[k].name, elc.files[k]);
        }

        var uploadUrl = autoAppendCurrentQueryString(`${auto_root_path()}/Upload/UpImage?type=${_type}&size=${_size}`);

        $.ajax({
            url: uploadUrl,
            type: 'post',
            contentType: false,
            processData: false,
            async: true,
            data: formData,
            headers: { "token": readToken() },
            success: function (obj) {
                // console.log(obj);
                layer.close(loadid);
                appendImageToUI(_num, _name, obj);
                elc.value = null;
            },
            error: function (res) {
                console.log(res);
                if (loadid != 0) {
                    layer.close(loadid);
                }
                elc.value = null;
                layer.msg(res.statusText, { icon: 'error', time: 3000 });
            }
        });
    } else {
        // layer.msg("请选择至少一个有效的文件!");readmemberToken
    }
}

/**
 * 图片上传后 默认情况下地址就是值,有些情况下图片是图片,提交的不是图片,比如mediaid的情况下,这个情况下更新有问题!!!
 * @param {*} _num 
 * @param {*} _name 
 * @param {*} obj 上传的格式 data[] url
 */
function appendImageToUI(_num, _name, obj) {
    // console.log('appendImageToUI', _name, _num, obj);
    var property = funcFindPropertry(_name);
    if (_num == 1) {
        var currentElc = $(`[name=${_name}]`);
        currentElc.parents(".formControls").find(".form-image-head").attr('src', obj.data[0].url);
        currentElc.parents(".formControls").find(".iconadd").hide();
        currentElc.val(obj.data[0].url);
        currentElc.parents(".formControls").find(".icon-close").show();
        if (property) {
            var expend = funcFindAttribute(property.attributes, "imgexpend");
            if (expend) {
                if (expend.args3) {
                    if (obj.data[0].hasOwnProperty(expend.args3)) {
                        currentElc.val(obj.data[0][expend.args3]);
                    }
                }
            }
        }
    } else {
        // var _ahtml = "";
        // obj.data.forEach(img => {
        //     _ahtml += '<li class="draggable-item"><img src="' + img.url + '"  onerror="this.onerror=null; this.src=\'./lib/default.png\';"><i class="Hui-iconfont Hui-iconfont-close2 icon-close"  onclick="handlerRemoveImageItem(event,this)"></i></li>';
        // });
        // // var _imageul = $(elc).parents(".formControls").find(".imageul");//drag_{name}
        // var _imageul = `.drag_${_name}`;
        // $(_imageul).append(_ahtml);

        const fragment = document.createDocumentFragment();
        obj.data.forEach(img => {
            // 创建 li
            const li = document.createElement('li');
            li.className = 'draggable-item';

            // 创建 img
            const imgEl = document.createElement('img');
            imgEl.src = img.url || './lib/default.png';
            imgEl.alt = img.alt;
            imgEl.onerror = function () {
                this.onerror = null;
                this.src = './lib/default.png';
            };

            // 创建删除图标
            const icon = document.createElement('i');
            icon.className = 'Hui-iconfont Hui-iconfont-close2 icon-close';
            icon.onclick = function (e) {
                handlerRemoveImageItem(e, this);
            };

            li.appendChild(imgEl);
            li.appendChild(icon);
            fragment.appendChild(li);
        });

        // 使用 jQuery 或原生方式添加
        $(`.drag_${_name}`).append(fragment);
        // 或者
        // document.querySelector(`.drag_${_name}`).appendChild(fragment);

        //读取所有值到输入框中,作为值
        handlerReadImages(_name);
        //超出数量,隐藏添加按钮!
        if ($(_imageul).find("li").length > _num) {
            $(_imageul).find("li").eq(0).hide();
        } else {
            $(_imageul).find("li").eq(0).show();
        }
        if (_num > 1) {
            //更新UI信息 针对多图的拖拽顺序问题
            // var property = funcFindPropertry(_name);
            if (property) {
                if (property.dragimages) {
                    property.dragimages.initItems();
                }
            }
        }
    }
}

/**
 * 执行reload判断,判断是否要重新加载页面,需要API配合 还有一个类似的叫changeui
 * @param {*} attributes 
 * @param {*} name 
 * @param {*} val 
 */
function handlerReloadReplace(attributes, name, val) {
    if (attributes) {
        var _attribute = funcFindAttribute(attributes, "reload");
        if (_attribute) {
            if (_attribute.args1) {
                name = _attribute.args1;
            }
            handlerBuildNewUrlToLoad(name, val);
        }
    }
}

/**
 * 执行changeui,是否需要变更ui的显示和隐藏,注意默认值和必填项,如果一个项必填,但是UI隐藏了,那是否还是必填???
 */
function handlerChangeUi(attributes, val) {
    if (attributes) {
        // for (let _attribute of attributes) {
        //     if (_attribute.name == "changeui") {
        //         handlerChangeUiAttribute(_attribute, val, true);
        //     }
        // }
        privateChangeUiHandler(attributes, val, true);
    }
}


//-----------------------------------------------------------------
/*
gname:表示一个组
name:表示一个字段
hit:命中次数 大于0保持显示 为0表示要隐藏
obj:gname或者name表示的对象,类型动态的,用于快速定位信息
key:gname+name,用于锁定是否存在,主要为了hit++
*/

/**
 * changeui功能的总入口,因对多个attribute的互斥问题
 * @param {*} attributes 
 * @param {*} val 当前值
 * @param {*} changeUi 
 */
function privateChangeUiHandler(attributes, val, changeUi) {
    if (attributes) {
        var maps = new Map();
        for (let _attribute of attributes) {
            if (_attribute.name == "changeui") {
                privateHandlerChangeUiAttribute(_attribute, val, maps);
            }
        }
        maps.forEach((map, key) => {
            if (map.hit > 0) {
                //去显示
                if (map.name != "") {
                    privateChangeUiItemToShow(map.obj, changeUi);
                }
                if (map.gname != "") {
                    privateChangeUiGroupToShow(map.obj, changeUi);
                }
            } else {
                //去隐藏
                if (map.name != "") {
                    privateChangeUiItemToHide(map.obj, changeUi);
                }
                if (map.gname != "") {
                    privateChangeUiGroupToHide(map.obj, changeUi);
                }
            }
        });
    }
}

/**
 * 
 * @param {*} _item 
 * @param {*} isui 
 */
function privateChangeUiItemToHide(_item, isui) {
    if (!_item.hide) {
        _item.hidden = true;
    }
    if (isui) {
        if (!$(`.item_${_item.name}`).hasClass("hide")) {
            $(`.item_${_item.name}`).addClass("hidden").hide();
        }
    }
}

/**
 * 
 * @param {*} _item 
 * @param {*} isui 
 */
function privateChangeUiItemToShow(_item, isui) {
    if (!_item.hide) {
        _item.hidden = false;
    }
    if (isui) {
        if (!$(`.item_${_item.name}`).hasClass("hide")) {
            $(`.item_${_item.name}`).removeClass("hidden").show();
        }
        if (_item.dataType == "markdown") {
            if (_item.editor) {
                _item.editor.resize();
            }
        }
    }
}

/**
 * 
 * @param {*} _gn 
 * @param {*} isui 
 */
function privateChangeUiGroupToShow(_gn, isui) {
    if (!_gn.hide) {
        _gn.hidden = false;
    }
    if (isui) {
        if (!$(`#group_id_${_gn.gcode}`).hasClass("hide")) {
            $(`#group_id_${_gn.gcode}`).removeClass("hidden").show();
        }
    }
}

/**
 * 
 * @param {*} _gn 
 * @param {*} isui 
 */
function privateChangeUiGroupToHide(_gn, isui) {
    if (!_gn.hide) {
        _gn.hidden = true;
    }
    if (isui) {
        if (!$(`#group_id_${_gn.gcode}`).hasClass("hide")) {
            $(`#group_id_${_gn.gcode}`).addClass("hidden").hide();
        }
    }
}

/**
 * 
 * @param {*} _attribute 
 * @param {*} val 
 * @param {*} maps 
 */
function privateHandlerChangeUiAttribute(_attribute, val, maps) {
    if (_attribute.args1) {
        let match = false;
        if (_attribute.args1.split(',')) {
            for (let _val of _attribute.args1.split(',')) {
                if (_val == val) {
                    match = true;
                    break;
                }
            }
        }
        if (!match) {
            privateChangeUiAutoForeach(_attribute, maps, 0);
        } else {
            privateChangeUiAutoForeach(_attribute, maps, 1);
        }
    }
}

/**
 * 
 * @param {*} _attribute 
 * @param {*} maps 
 * @param {*} strs 
 * @param {*} math 
 */
function privateChangeUiAutoForeach(_attribute, maps, math) {
    if (_attribute.args2) {
        var strs = _attribute.args2.split(',');
        for (var _str of strs) {
            if (_str.indexOf("group:") >= 0) {
                var _gname = _str.substring(6);
                if (_gname.indexOf("regexp:") >= 0) {
                    let _reg = new RegExp(_gname.substring(7));
                    for (const _gn of _ui_data_list) {
                        if (_gn.isgroup) {
                            if (_reg.test(_gn.gcode)) {
                                privateAutoSetMap(maps, _gn.gcode, "", _gn, math);
                            }
                        }
                    }
                } else {
                    for (const _gn of _ui_data_list) {
                        if (_gn.isgroup) {
                            if (_gn.gcode == _gname) {
                                privateAutoSetMap(maps, _gn.gcode, "", _gn, math);
                            }
                        }
                    }
                }
                continue;
            }
            if (_str.indexOf("regexp:") >= 0) {
                let _reg = new RegExp(_str.substring(7));
                for (const _item of _global_data_properties) {
                    if (_reg.test(_item.name)) {
                        privateAutoSetMap(maps, "", _item.name, _item, math);
                    }
                }
                continue;
            }
            for (const _item of _global_data_properties) {
                if (_item.name == _str) {
                    privateAutoSetMap(maps, "", _item.name, _item, math);
                }
            }
        }
    }
}


/**
 * 自动++或者写入
 * @param {*} maps 
 * @param {*} gname 
 * @param {*} name 
 * @param {*} obj 对象,可能是group 也可能是property
 * @param {*} math 命中填写1,未命中填写0
 */
function privateAutoSetMap(maps, gname, name, obj, math) {
    var onlyKey = `g${gname}-i${name}`;
    var find = maps.get(onlyKey);
    if (find) {
        if (math) {
            find.hit++;
        }
    } else {
        maps.set(onlyKey, {
            gname: gname,
            name: name,
            hit: math,
            obj: obj
        });
    }
}

//======================================================================




/**
 * 适应reload
 * @param {*} _name 
 * @param {*} _val 
 */
function handlerBuildNewUrlToLoad(_name, _val) {
    // URLSearchParams 这个兼容性
    var _saerch = location.search.substring(1);//当前模式下必然有?path=xxx等
    var argms = _saerch.split('&');
    var argses = new Array();
    for (var _args of argms) {
        if (_args.indexOf(`${_name}=`) == -1) {
            argses.push(_args);
        }
    }
    argses.push(`${_name}=${_val}`);
    //组合query进行reload
    // URLSearchParams.toString
    var _newUrl = `${location.pathname}?${argses.join('&')}`;
    location.replace(_newUrl);
}

/**
 * 组合带上当前页面的query生成新的url 如果参数已经存在,则不会进行覆盖
 * @param {*} url 
 * @returns 
 */
function autoAppendCurrentQueryString(url) {
    var queryIndex = url.indexOf('?');
    var hasFields = new Array();
    if (queryIndex > 0) {
        var has = url.substring(queryIndex + 1);
        var hasquerys = has.split('&');
        for (var arg of hasquerys) {
            if (arg.indexOf('=') > 0) {
                let na = arg.split('=')[0];
                // let va = arg.split('=')[1];
                hasFields.push(na);
            }
        }
    }
    var _saerch = location.search.substring(1);//当前模式下必然有?path=xxx等
    var argms = _saerch.split('&');
    var appendUrl = new Array();
    for (var _args of argms) {
        if (_args.indexOf('=') > 0) {
            let na = _args.split('=')[0];
            if (hasFields.indexOf(na) == -1) {
                appendUrl.push(_args);
            }
        }
    }
    if (appendUrl.length > 0) {
        var appStr = appendUrl.join('&');
        if (url.indexOf('?') >= 0) {
            url = `${url}&${appStr}`;
        } else {
            url = `${url}?${appStr}`;
        }
    }
    return url;
}

/**
 * 判断select是否要执行reload事件
 * @param {*} elc 
 */
function handlerSectionChange(elc) {
    var _name = $(elc).attr("name");
    var _property = funcFindPropertry(_name);
    if (_property) {
        var _val = $(elc).val();
        handlerReloadReplace(_property.attributes, _name, _val);
        handlerChangeUi(_property.attributes, _val);
        // var _attribute = funcFindAttribute(_property.attributes, "reload");
        // if (_attribute) {
        //     var _val = $(elc).val();
        //     if (_attribute.args1) {
        //         _name = _attribute.args1;
        //     }
        //     handlerBuildNewUrlToLoad(_name, _val);
        // }
        handlerLoaditem(_property);
    }
}

/**
 * 转化数据类型,从数据库的类型转化为UI使用的类型
 * @param {*} properties 
 */
function handlerExchangeDataTypeToUIType(properties) {
    properties.forEach(item => {
        handlerExchangeItemToUIData(item);
        if (_config) {
            if (!_config.dynamic) {
                if (item.name.indexOf("__") >= 0) {
                    _config.dynamic = true;
                }
            }
        }
    });
}

/**
 * 转化数据格式为UI格式
 */
function handlerExchangeItemToUIData(item) {
    item.dataFrom = item.dataType;
    //这里需要处理字段的属性
    if (item.attributes) {
        item.attributes.forEach(_attribute => {
            switch (_attribute.name) {
                case "hidden":
                    {
                        item.hidden = true;
                        if (_attribute.args1) {
                            if (_config.model == _attribute.args1) {
                                item.hidden = false;
                            }
                        }
                    }
                    break;
                case "hide":
                    {
                        item.hide = true;//始终隐藏
                        item.hidden = true;//可以被changeui唤醒
                    }
                    break;
                case "display":
                    {
                        if(_config.is_page_view){
                            item.hide = true;//始终隐藏
                            item.hidden = true;//可以被changeui唤醒
                        }
                    }
                    break;
                case "valuetype":
                    {
                        item.valueType = _attribute.args1;
                        // item.hide = true;//始终隐藏
                        // item.hidden = true;//可以被changeui唤醒
                    }
                    break;
                case "required":
                    {
                        item.required = true;
                    }
                    break;
                case "empty":
                    {
                        item.empty = true;
                    }
                    break;
                case "readonly":
                    {
                        item.readonly = true;
                    }
                    break;
                case "textarea":
                    {
                        item.dataType = "textarea";
                        item.singlerow = true;
                        if (_attribute.args1) {
                            item.areastyle = _attribute.args1;
                        }
                        if (_attribute.args2) {
                            if (_attribute.args2 == "half") {
                                item.singlerow = false;
                            }
                        }
                    }
                    break;
                case "cover":
                    {
                        item.dataType = "cover";
                        if (!item.value) {
                            item.value = new Array();
                        } else {
                            if (!Array.isArray(item.value)) {
                                item.value = new Array(item.value);
                            }
                        }
                    }
                    break;
                case "text":
                    {
                        item.dataType = "text";
                        if (_attribute.args1) {
                            item.singlerow = true;
                        }
                        if (item.maxlength) {
                            if (item.maxlength > 64) {
                                item.singlerow = true;
                            }
                        }
                        if (_attribute.args2) {
                            item.class = _attribute.args2;
                        }
                    }
                    break;
                case "fentoyuan":
                    {
                        if (item.value) {
                            item.value = (parseFloat(item.value) / 100).toFixed(2);//(parseFloat(item.value) / 100).toFixed(2);
                        }
                        item.dataType = "fentoyuan";
                    }
                    break;
                case "file":
                    {
                        item.dataType = 'file';
                        if (_attribute.args1) {
                            item.url = _attribute.args1;
                        }
                        if (_attribute.args2) {
                            item.type = _attribute.args2;
                        }
                        if (_attribute.args3) {
                            item.filehandler = _attribute.args3;
                        }
                        if (!item.filehandler) {
                            if (!_attribute.args1) {
                                item.url = `/${readRootPath()}/Upload/UpFile`;
                            }
                        }
                        if (_attribute.args4) {
                            item.accept = _attribute.args4;
                        } else {
                            item.accept = "*.*";
                        }
                    }
                    break;
                case "image":
                    {
                        item.dataType = 'image';
                        if (_attribute.args1) {
                            item.num = parseInt(_attribute.args1);
                        } else {
                            item.num = 1;
                        }
                        if (_attribute.args2) {
                            item.type = _attribute.args2;
                        }
                        if (_attribute.args3) {
                            item.size = _attribute.args3;
                        }
                        if (item.value && item.value != "null") {
                            if (item.num > 1) {
                                if (item.dataFrom == "String[]") {
                                    item.images = item.value;//多个图片是一个数组,字符串数组的形式
                                    item.value = item.value.join(',');
                                } else {
                                    item.images = item.value.split(',');//多个图片之间使用,隔开
                                }
                            }
                        } else {
                            item.value = null;
                        }
                        if (item.num > 1) {
                            item.singlerow = true;
                        }
                        //如何针对mediaid的情况,也就是需要url+mediaid
                        if (!item.imgid) {
                            item.imgid = item.value;
                        }
                    }
                    break;
                case "imgexpend":
                    {
                        if (_attribute.args1) {
                            item.imgid = _attribute.args1;
                        }
                        if (_attribute.args2) {
                            item.value = _attribute.args2;
                        }
                    }
                    break;
                case "daterange":
                    {
                        item.dataType = "daterange";
                        if (_attribute.args2) {
                            var _target = funcFindExpendPropertry(_attribute.args2, item.name);
                            if (_target) {
                                _target.hidden = true;
                            }
                        }
                        //2个时间合并到一个去 注意要和js的保持一致 比如yyyy-MM-dd  至  yyyy-MM-dd
                        var _start = "";
                        var _end = "";
                        if (_attribute.args1 == item.name) {
                            _start = item.value;
                        } else {
                            if (_attribute.args1) {
                                var _arg1_obj = funcFindExpendPropertry(_attribute.args2, item.name);
                                if (_arg1_obj) {
                                    if (_arg1_obj.value) {
                                        _start = _arg1_obj.value;//默认为yyyy-MM-dd HH:mm:ss格式
                                        //时间可能是时间戳格式
                                        if (_attribute.args4) {
                                            switch (_attribute.args4) {
                                                case "times":
                                                    {
                                                        _start = new Date(_start * 1000).Format('yyyy-MM-dd HH:mm:ss');
                                                    }
                                                    break;
                                                case "timems":
                                                    {
                                                        _start = new Date(_start * 1000).Format('yyyy-MM-dd HH:mm:ss');
                                                    }
                                                    break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (_start && _attribute.args2) {
                            var _arg2_obj = funcFindExpendPropertry(_attribute.args2, item.name);
                            if (_arg2_obj) {
                                if (_arg2_obj.value) {
                                    _end = _arg2_obj.value;
                                    if (_attribute.args4) {
                                        switch (_attribute.args4) {
                                            case "times":
                                                {
                                                    _end = new Date(_end * 1000).Format('yyyy-MM-dd HH:mm:ss');
                                                }
                                                break;
                                            case "timems":
                                                {
                                                    _end = new Date(_end * 1000).Format('yyyy-MM-dd HH:mm:ss');
                                                }
                                                break;
                                        }
                                    }
                                    var _fulldate = `${new Date(_start).Format('yyyy-MM-dd')}  至  ${new Date(_end).Format('yyyy-MM-dd')}`;
                                    item.value = _fulldate;
                                }
                            }
                        }
                    }
                    break;
                case "datalist":
                    {
                        item.dataType = 'datalist';
                        item.datalistid = item.name;
                        if (_attribute.args1) {
                            try {
                                item.selects = JSON.parse(_attribute.args1);
                            } catch (err) {
                                console.log(item.name, "属性 datalist 的值 args1 配置错误", err);
                            }
                        } else {
                            item.datalistid = _attribute.args2;
                            if (_attribute.args3) {
                                try {
                                    eval(_attribute.args3);
                                } catch (err) {
                                }
                            }
                        }
                    }
                    break;
                case "selects":
                case "select":
                case "lselect":
                    {
                        try {
                            item.selects_max = "lsingle";
                            if (_attribute.args4) {
                                if (_attribute.args4 != "1") {
                                    item.selects_max = "lbatch";
                                }
                            }
                            item.selects = JSON.parse(_attribute.args1);
                            if (item.value || item.value == 0) {
                                var _typeof = "number";
                                var valMap = new Map();
                                var _value = item.value;
                                if (Array.isArray(_value)) {
                                    for (const _val of _value) {
                                        _typeof = typeof (_val);
                                        valMap.set(_val, true);
                                    }
                                } else {
                                    _typeof = typeof (item.value);
                                    valMap.set(item.value, true);
                                }
                                if (item.valueType) {
                                    _typeof = item.valueType;
                                } else {
                                    item.valueType = _typeof;
                                }
                                switch (_typeof) {
                                    case "string":
                                        {
                                            var _splitchar = ',';
                                            if (_attribute.args2) {
                                                _splitchar = _attribute.args2;
                                            }
                                            var strs = item.value.split(_splitchar);
                                            item.selects.forEach(ii => {
                                                if (strs.indexOf(ii.value) >= 0) {
                                                    ii.selected = true;
                                                }
                                            });
                                        }
                                        break;
                                    case "number":
                                        {
                                            item.selects.forEach(ii => {
                                                if (valMap.has(ii.value)) {
                                                    ii.selected = true;
                                                }
                                            });
                                        }
                                        break;
                                    case "object":
                                        {
                                            if (Array.isArray(item.value)) {
                                                for (const ii of item.selects) {
                                                    item.dataFrom = `${typeof (ii.value)}[]`;
                                                    if (item.value.indexOf(ii.value) >= 0) {
                                                        ii.selected = true;
                                                        break;
                                                    }
                                                }
                                            } else {
                                                var _vals = item.value.toString();
                                                for (const ii of item.selects) {
                                                    item.dataFrom = `${typeof (ii.value)}[]`;
                                                    if (_vals.indexOf(ii.value.toString()) >= 0) {
                                                        ii.selected = true;
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        break;
                                }
                            }
                            item.dataType = _attribute.name;
                            if (item.selects) {
                                if (_attribute.name == "selects") {
                                    //name value selected
                                    var selectedItems = item.selects.filter(function (o) {
                                        return o.selected;
                                    });
                                    var selNum = selectedItems.length;
                                    if (selNum > 0) {
                                        item.__selected_values = (selNum > 1 ? '(' + selNum + ')' : '') + selectedItems.map(function (o) { return o.name; }).join(' ');
                                    }
                                }
                            }
                        } catch (err) {
                            console.log(item.name, "属性 select 的值 args1 配置错误", err);
                        }
                    }
                    break;
                case "mark":
                    {
                        var _mark = {
                            model: _classPath,
                            value: item.name
                        };
                        if (_attribute.args1) {
                            _mark.model = _attribute.args1;
                        }
                        if (_attribute.args2) {
                            _mark.value = _attribute.args2;
                        }
                        if (_attribute.args3) {
                            _mark.style = _attribute.args3;
                        }
                        item.mark = _mark;
                    }
                    break;
                case "style":
                    {
                        item.style = _attribute.args1;
                    }
                    break;
                case "class":
                    {
                        item.class = _attribute.args1;
                    }
                    break;
                case "button":
                    {
                        item.dataType = "button";
                        if (!item.buttons) {
                            item.buttons = new Array();
                        }
                        var _btn = ({
                            name: _attribute.args1,
                            func: null
                        });
                        if (_attribute.args1) {
                            _btn.value = _attribute.args1;
                        } else {
                            _btn.value = item.value;
                            _btn.name = item.name;
                        }
                        if (_attribute.args2) {
                            _btn.btnfunc = _attribute.args2;
                        }
                        item.buttons.push(_btn);
                    }
                    break;
                case "score":
                    {
                        item.dataType = "score";
                    }
                    break;
                case "singlerow": 
                    {
                        item.singlerow = true;
                    }
                    break;
                case "markdown":
                    {
                        item.dataType = "markdown";
                        item.singlerow = true;
                        _global_need_loadmarkdown = true;
                        if (_attribute.args2) {
                            var _target = funcFindExpendPropertry(_attribute.args2, item.name);
                            if (_target) {
                                _target.hidden = true;
                            }
                        }
                    }
                    break;
                case "richtext":
                    {
                        item.dataType = "richtext";
                        item.singlerow = true;
                        _global_need_loadrichhtml = true;
                    }
                    break;
                case "unit":
                    {
                        item.unit = _attribute.args1;
                    }
                    break;
                case "simg":
                    {
                        // 用于图片选择器,之前旧版是使用unit标注,新版本得使用PasteImageselectAttribute标注
                        var simg = new {
                            url: './images/index.html',
                            query: '?type=imgs'
                        };
                        if (_attribute.args1) {
                            simg.url = _attribute.args1;
                        }
                        if (_attribute.args2) {
                            simg.query = _attribute.args2;
                        }
                        item.simg = simg;
                    }
                    break;
                case "halfrow":
                    {
                        //所以这个要放最后面
                        item.singlerow = false;
                        item.halfrow = true;
                    }
                    break;
                case "object":
                    {
                        item.dataType = 'object';
                        item.session_key = `${item.name}_0000`;
                        if (item.value) {
                            sessionStorage.setItem(item.session_key, JSON.stringify(item.value));
                            //UI上如何显示
                            if (_attribute.args4) {
                                if (item.value.hasOwnProperty(_attribute.args4)) {
                                    item.display = item.value[_attribute.args4];
                                }
                            }
                        } else {
                            sessionStorage.removeItem(item.session_key);
                        }
                        if (!item.hidden) {
                            _has_outer = true;
                        }
                    }
                    break;
                case "objects":
                    {
                        item.dataType = 'objects';
                        if (item.value) {
                            item.objects = item.value;

                        }
                        if (_attribute.args3) {
                            item.display_id = _attribute.args3;
                        } else {
                            item.display_id = "id";
                        }
                        if (_attribute.args4) {
                            item.display_name = _attribute.args4;
                        } else {
                            item.display_name = "name";
                        }
                        if (item.objects) {
                            var _list = new Array();
                            item.objects.forEach(_item => {
                                _item._id = handlerColumnValue(_item, item.display_id);
                                _item._display = handlerColumnValue(_item, item.display_name);
                                _list.push(_item);
                            });
                            _map_values.set(item.name, _list);
                        }
                        _has_outer = true;
                    }
                    break;
                case "outer":
                    {
                        item.dataType = 'outer';
                        let _set_value = true;
                        if (_attribute.args2) {
                            //这里args2有问题,需要对应转化
                            if (item.name.indexOf("__") > 0) {
                                var lastIndex = item.name.lastIndexOf("__") + 2;
                                _attribute.args2 = item.name.substring(0, lastIndex) + _attribute.args2;
                            }
                            var _target = funcFindExpendPropertry(_attribute.args2, item.name);
                            if (_target) {
                                _target.hidden = true;
                                if (_target.value) {
                                    if (typeof _target.value == "object") {
                                        if (_attribute.args4) {
                                            // item.display = _target.value[_attribute.args4];
                                            item.display = handlerColumnValue(_target.value, _attribute.args4);// _target.value[_attribute.args4];
                                            _set_value = false;
                                        }
                                    }
                                }
                            }
                        }
                        if (_set_value) {
                            if (item.value) {
                                item.display = item.value;
                            }
                            item.valueType = typeof (item.value);
                        }
                        _has_outer = true;
                    }
                    break;
                case "outers":
                    {
                        item.dataType = 'outers';
                        if (_attribute.args2) {
                            if (item.name.indexOf("__") > 0) {
                                var lastIndex = item.name.lastIndexOf("__") + 2;
                                _attribute.args2 = item.name.substring(0, lastIndex) + _attribute.args2;
                            }
                            var _target = funcFindExpendPropertry(_attribute.args2, item.name);
                            if (_target) {
                                _target.hidden = true;
                                if (_target.value && _target.value != '') {
                                    item.display = _target.value;
                                    item.display.forEach(_dis => {
                                        _dis._display = handlerColumnValue(_dis, _attribute.args4);
                                    });
                                }
                            }
                        }
                        item.display_id = _attribute.args3;
                        item.display_name = _attribute.args4;
                        _has_outer = true;
                    }
                    break;
                case "splitarray":
                    {
                        item.dataType = "splitarray";
                        if (item.value) {
                            if (_attribute.args1) {
                                item.value = item.value.join(_attribute.args1);//用其他字符分割
                            } else {
                                item.value = item.value.toString();//使用,分割
                            }
                        } else {
                            item.value = "";
                        }
                    }
                    break;
                case "datetime":
                    {

                        var _format = "yyyy-MM-dd HH:mm:ss";
                        if (_attribute.args1) {
                            _format = _attribute.args1;
                        }
                        item.format = _format;
                        if (item.value) {
                            if (_attribute.args2) {
                                switch (_attribute.args2) {
                                    case "times":
                                        {
                                            item.value = parseDate(item.value * 1000).Format(_format);
                                        }
                                        break;
                                    case "timems":
                                        {
                                            item.value = parseDate(item.value).Format(_format);
                                        }
                                        break;
                                    default:
                                        {
                                            item.value = parseDate(item.value).Format(_format);
                                        }
                                        break;
                                }
                            }
                        }
                        if (item.dataType && item.dataType == "daterange") {
                            return;
                        }
                        item.dataType = "datetime";
                    }
                    break;
                case "point":
                    {
                        item.point = true;
                    }
                    break;
                case "sunform":
                    {
                        item.dataType = "sunform";
                        item.singlerow = true;
                        item.frame = {
                            height: 300,
                            url: "",
                            class: ""
                        };
                        var session_key = `${item.name}_00000`;
                        if (item.value) {
                            sessionStorage.setItem(session_key, JSON.stringify(item.value));
                        } else {
                            sessionStorage.removeItem(session_key);
                        }
                        if (_attribute.args3) {
                            item.frame.class = _attribute.args3;
                        }
                        //model=sunobj
                        var _tar_url = handlerBuildDynamicUrl(_attribute.args1);
                        if (_tar_url.indexOf('/') >= 0) {
                            if (_tar_url.indexOf("?") >= 0) {
                                item.frame.url = _tar_url + '&session_key=' + session_key;
                            } else {
                                item.frame.url = _tar_url + '?session_key=' + session_key;
                            }
                        } else {
                            item.frame.url = `${handlerPasteFormPath()}view.html?path=${_tar_url}&model=sunobj&session_key=${session_key}`;
                        }
                        if (_attribute.args2) {
                            item.frame.height = _attribute.args2;
                        }
                    }
                    break;
                case "notice":
                case "password":
                    {
                        item.dataType = _attribute.name;
                    }
                    break;
                case "changeui":
                    {
                        if (_changeui_list) {
                            _changeui_list.push({
                                attribute: _attribute,
                                value: item.value,
                                name: item.name
                            });
                            //基于name排重到时候!!!
                        }
                        //这里有问题 当前值是多少 changeui ... .. .
                    }
                    break;
                case "html":
                    {
                        //在form中,html直接读取字段的值!
                        item.dataType = "html";
                    }
                    break;
                default:
                    break;
            }
        });
    }

    //如果是故意要暴露id的呢?
    if (item.name == "id") {
        if (!item.placeholder) {
            item.hidden = true;
        }
        //编辑模式必须隐藏,防止修改到其他信息去
        if (_config.model == 'edit') {
            item.hidden = true;
        }
        //所以如果id需要自定义的需要特别备注比如 ID 可填可不填
    }

    //Guid的默认处理
    if (item.dataFrom == "Guid") {
        if (item.value == "00000000-0000-0000-0000-000000000000") {
            item.value = "";
            if (item.display == "00000000-0000-0000-0000-000000000000") {
                item.display = "";
            }
        }
    }

    switch (item.dataType) {
        case "Int32":
        case "Int64":
        case "UInt32":
        case "UInt64":
            {
                item.dataType = "number";
                if (item.value == "0") {
                    item.value = "";
                }
            }
            break;
        case "DateTime":
            {
                item.dataType = "datetime";
                if (item.value && item.value == '01/01/0001 00:00:00') {
                    item.value = "";
                }
                if (!item.format) {
                    item.format = "yyyy-MM-dd HH:mm:ss";
                }
            }
            break;
        case "Boolean":
            {
                item.dataType = "switch";
            }
            break;
        case "Double":
        case "Decimal":
            {
                item.step = "0.01";
                if (item.attributes) {
                    item.attributes.forEach(_attribute => {
                        if (_attribute.name == 'double') {
                            item.step = _attribute.args1;
                        }
                    });
                }
            }
            break;
        case "String":
            {
                if (item.value == null) {
                    item.value = "";
                }
                if (item.maxlength == 0) {
                    item.dataType = "richtext";
                    item.singlerow = true;
                    _global_need_loadrichhtml = true;
                }
                if (item.maxlength > 128) {
                    item.dataType = "textarea";
                    item.singlerow = true;
                }
                if (item.maxlength <= 128 && item.maxlength != 0) {
                    item.dataType = "text";
                    if (item.maxlength > 64) {
                        item.singlerow = true;
                    }
                }
                //可能前面标记了
                if (item.halfrow) {
                    item.singlerow = false;
                }
            }
            break;
    }

    if (item.hidden) {
        if (item.required) {
            item.required = false;
        }
    }
    if (item.required) {
        if (item.point) {
            item.point = false;
        }
    }
}

/**
 * 查找组信息 并添加到数据集合 或者是添加子项
 * @param {*} _group_name 
 * @param {*} _ui_data_list 
 * @returns 
 */
function handlerTakeGroupInfo(_group_name, _ui_data_list, item) {
    var _handler = false;
    if (_ui_data_list) {
        for (var ii of _ui_data_list) {
            if (ii.isgroup) {
                if (ii.gcode == _group_name) {
                    ii.groups.push(item);
                    _handler = true;
                    break;
                }
            }
        }
    }

    if (_global_class_attributes && !_handler) {
        for (var ii of _global_class_attributes) {
            if (ii.name == "group") {
                if (ii.args1 == _group_name) {
                    var _info = {
                        isgroup: true,
                        singlerow: true,
                        gcode: _group_name,
                        gname: ii.args2,
                        isopen: true,
                        groups: new Array(),
                        hidden: false
                    };
                    if (ii.args3) {
                        if (ii.args3 != "open") {
                            _info.isopen = false;
                        }
                    }
                    if (_info.isopen) {
                        _info.gclass = "open";
                    } else {
                        _info.gclass = "close";
                    }
                    if (ii.args4) {
                        _info.gmodel = 'edit';
                    }
                    if (ii.args3 == 'hidden') {
                        _info.hidden = true;
                    }
                    _handler = true;
                    _info.groups.push(item);
                    _ui_data_list.push(_info);
                    break;
                }
            }
        }
    }
    //如果没有找到,是否基于当前New一个
    if (!_handler) {
        var ii = funcFindAttribute(item.attributes, "group");
        if (ii) {
            var _info = {
                isgroup: true,
                singlerow: true,
                gcode: _group_name,
                gname: ii.args2,
                isopen: true,
                groups: new Array(),
                hidden: false
            };
            if (ii.args3) {
                if (ii.args3 != "open") {
                    _info.isopen = false;
                }
            }
            if (_info.isopen) {
                _info.gclass = "open";
            } else {
                _info.gclass = "close";
            }
            if (ii.args4) {
                _info.gmodel = 'edit';
            }
            if (ii.args3 == 'hidden') {
                _info.hidden = true;
            }
            _handler = true;
            _info.groups.push(item);
            _ui_data_list.push(_info);
        }
    }
    return null;
}

/**
 * 输入框失去焦点后
 * @param {*} elc 
 */
function handlerBlur(elc) {
    var name = $(elc).attr("name");
    if (name) {
        var find = funcFindPropertry(name);
        if (find) {
            handlerLoaditem(find);
        }
    }
}

/**
 * 执行特性loaditem
 * @param {*} find 当前是某一个字段 
 */
function handlerLoaditem(find) {
    if (!find.attributes) {
        return;
    }
    var _laterread = funcFindAttribute(find.attributes, "loaditem");
    if (_laterread) {
        var _url = _laterread.args1;
        if (_url) {
            var _read_url = handlerBuildDynamicUrl(_url);
            _apiget(_read_url, true, (cc, oo) => {
                if (cc == 200) {
                    var newList = new Array();
                    var mapKeys = new Map();
                    if (Array.isArray(oo)) {
                        for (var _item of oo) {
                            mapKeys.set(_item.name, _item);
                        }
                    } else {
                        mapKeys.set(oo.name, oo);
                    }
                    if (_global_data_properties) {
                        //进行更替
                        _global_data_properties.forEach(_item => {
                            if (mapKeys.has(_item.name)) {
                                newList.push(mapKeys.get(_item.name));
                            } else {
                                newList.push(_item);
                            }
                        });
                        _global_data_properties = newList;
                    }
                    //oo可能是一个集合,先要进行数据更替
                    if (Array.isArray(oo)) {
                        oo.forEach(ooitem => {
                            handler_replace_item(ooitem);
                        });
                    } else {
                        handler_replace_item(oo);
                    }
                }
            });
        }
    }
}

/**
 * 更换UI的某一块 表单中的某一块
 * @param {*} item 
 */
function handler_replace_item(item) {
    if (item.hidden) {
        return;
    }
    handlerExchangeItemToUIData(item);
    //如果是Outer模式呢???
    var _name = item.name;
    var _theml = $("#template_tr_item").html();
    var _vhtml = template(_theml, { item: item });
    if ($(`.item_${_name}`).length > 0) {
        $(`.item_${_name}`).replaceWith(_vhtml);
    } else {
        $(".paste-form-body").append(_vhtml);
    }
}


/**
 * 从父级查找对应的页面,然后吧值更新到页面中,这里针对的是table的行数据新增或者变更!
 * 查找并更新数据行,一般用于表格数据行需要变动的时候
 * @param {*} obj 导入的数据,可能是单行的ListDto也可能是ListDto数组
 * @param {*} urlKey 可选参数,表示url需要匹配这个关键字,一般用path的内容做找寻
 * @returns 
 */
function findAndCallHandler(obj, urlKey) {
    // 定义一个内部查找函数,专门负责在指定的窗口(window)里找 iframe 并调用
    const searchInWindow = (targetWin) => {
        // 1. 优先找 layer 弹窗 (层级通常最高)
        // 注意:layer 的 iframe 类名通常是 layui-layer-iframe
        var iframes = targetWin.document.querySelectorAll('.layui-layer-iframe iframe');

        // 2. 如果没找到,或者想兼容普通容器,再找 .show_iframe
        if (iframes.length === 0) {
            // var containers = targetWin.document.querySelectorAll('.show_iframe');
            // if (containers.length > 0) {
            //     // 找到了容器,从容器里取 iframe
            //     // 这里假设一个容器里只有一个主要 iframe,或者取第一个
            //     iframes = containers[0].querySelectorAll('iframe');
            // }
            iframes = targetWin.document.querySelectorAll('.show_iframe iframe');
        }
        if (iframes.length === 0) {
            console.log('searchInWindow: 没有找到任何 iframe');
            //没有iframe 可能就是当前自己
            return false;
        }
        // 3. 倒序遍历 (reverse),确保最新打开的(显示在上面的)先被调用
        // 这一步替代了复杂的 z-index 计算
        var iframeList = Array.from(iframes).reverse();
        for (let iframe of iframeList) {
            if (!iframe.contentWindow) {
                console.warn('iframe.contentWindow 不存在,跳过', iframe.src);
                continue;
            }
            if (urlKey) {
                var iframeBaseURI = iframe.contentWindow.location.href;
                if (iframeBaseURI.indexOf(urlKey) == -1) {
                    // console.log('callUpdateRow iframe.src不匹配', iframeBaseURI, urlKey);
                    continue;
                }
            }
            try {
                if (iframe.contentWindow && typeof iframe.contentWindow.handlerUpdateRow == 'function') {
                    // console.log('找到并调用 handlerUpdateRow');
                    var result = iframe.contentWindow.handlerUpdateRow(obj);
                    if (result) {
                        return true;
                    }
                }
            } catch (e) {
                // 跨域或错误忽略
                console.log(e);
            }
        }
        return false;
    };

    // ================= 核心逻辑判断 =================
    var find = false;

    //先从顶级页面找
    if (window.top !== window.self) {
        find = searchInWindow(window.top);
        if (find) {
            return true;
        }
    }

    //然后找顶级页面的工作台
    if (window.top !== window.self) {
        const rootWindow = window.top;;
        // 针对/page/index.html中的页面框架的内页 工作台页面找
        const showIframes = rootWindow.document.querySelectorAll('.show_iframe');
        for (let showIframe of showIframes) {
            var handler = callUpdateRow(showIframe, obj, urlKey);
            if (handler) {
                return true;
            }
        }
        find = searchInWindow(window.top);
        if (find) {
            return true;
        }
    }

    //从父级页面找
    if (window.parent !== window.self) {
        find = searchInWindow(window.parent);
        if (find) {
            return true;
        }
    }

    //从父级页面的工作台找
    if (window.parent != window.self) {
        const rootWindow = window.parent;
        // 针对/page/index.html中的页面框架的内页 工作台页面找
        const showIframes = rootWindow.document.querySelectorAll('.show_iframe');
        for (let showIframe of showIframes) {
            var handler = callUpdateRow(showIframe, obj, urlKey);
            if (handler) {
                return true;
            }
        }
        find = searchInWindow(window.top);
        if (find) {
            return true;
        }
    }

    // //都没有找到 可能是父级页面
    // if (window.parent !== window.self) {
    //     var currwin = window.parent;
    //     if (currwin) {
    //         if (typeof currwin.handlerUpdateRow === 'function') {
    //             var result = currwin.handlerUpdateRow(obj);
    //             if (result) {
    //                 return true;
    //             }
    //         }
    //     }
    // }

    var currwin = window;//就是自己当前页面
    if (currwin) {
        if (typeof currwin.handlerUpdateRow === 'function') {
            currwin.handlerUpdateRow(obj);
            return true;
        }
    }

}


/**
 * 主要的作用是从工作台找到对应的页面,然后更新表格的数据行,单行或者多行
 * @param {*} showIframe 
 * @returns 
 */
function callUpdateRow(showIframe, obj, pathName) {
    try {
        // 检查 .show_iframe 是否可见
        const style = window.getComputedStyle(showIframe);
        if (style.display !== 'none' && style.visibility !== 'hidden') {
            // 在显示的 .show_iframe 中查找 iframe
            const iframes = showIframe.querySelectorAll('iframe');
            for (let iframe of iframes) {
                if (pathName) {
                    var iframeBaseURI = iframe.contentWindow.location.href;
                    if (iframeBaseURI.indexOf(pathName) == -1) {
                        console.log('callUpdateRow iframe.src不匹配', iframeBaseURI, pathName);
                        continue;
                    }
                    console.log('callUpdateRow iframe.src匹配', iframeBaseURI, pathName);
                }
                try {
                    const iframeStyle = window.getComputedStyle(iframe);
                    // 检查 iframe 是否可见且已加载
                    if (iframeStyle.display !== 'none' && iframeStyle.visibility !== 'hidden' && iframe.contentWindow) {
                        const iframeWindow = iframe.contentWindow;
                        // 检查是否存在 handlerUpdateRow 函数
                        if (typeof iframeWindow.handlerUpdateRow === 'function') {
                            // 调用 handlerUpdateRow 并传入 obj
                            let result = iframeWindow.handlerUpdateRow(obj);
                            if (result) {
                                return true;
                            }
                        }
                    }
                } catch (error) {
                    // 处理跨域限制等情况
                    console.warn('无法访问 iframe 内容:', error);
                }
            }
        }
    } catch (error) {
        console.warn('无法访问 .show_iframe 元素:', error);
    }
    return false;
}



/*******************************/

/**
 * 读取模型和默认值,值等
 */
function dynamicReadModel(_url) {
    // var _url=`/api/app/dynamicHelper/read${location.search}`;
    // if(location.search.indexOf("datakey")==-1){
    //     _url=`/api/app/dynamicHelper/view${location.search}`;
    // }
    _apiget(_url, true, (c, o) => {
        if (c == 200) {
            loadHeader(o);

            if (o.code) {
                _classPath = o.code;
                _config.className = o.code;
            }

            if (o.title) {
                this.document.title = "更新" + o.title;
            }



            _global_data_properties = new Array();

            //整合数据,整合字段信息用于显示UI
            if (o.data) {
                if (o.properties) {
                    _setting_data_properties = o.properties;
                } else {
                    _setting_data_properties = new Array();
                }
                dynamicBuildPropertyInfo(o.data, "", -1);
            }

            //检查必显项目
            if (o.properties) {
                for (var _pro of o.properties) {
                    if ((_pro.showView && _config.model == "view")) {
                        var _find_pro = false;
                        for (var ii of _global_data_properties) {
                            if (ii.name == _pro.name) {
                                _find_pro = true;
                                break;
                            }
                        }
                        if (!_find_pro) {
                            if (!_pro.matchRegex) {
                                _global_data_properties.push(_pro);
                            }
                        }
                    }
                }
            }

            //组合goup
            if (!o.attributes) {
                o.attributes = new Array();
            }
            //处理分组的问题
            var groups = new Array();
            _global_data_properties.forEach(_property => {
                if (_property.attributes) {
                    for (var _attribute of _property.attributes) {
                        if (_attribute.name == 'group') {
                            if (groups.indexOf(_attribute.args1) == -1) {
                                groups.push(_attribute.args1);
                            }
                        }
                    }
                }
            });
            if (groups.length > 0) {
                groups.forEach(igroup => {
                    var _find = false;
                    for (var _oa of o.attributes) {
                        if (_oa.name == igroup) {
                            _find = true;
                            break;
                        }
                    }
                    if (!_find) {
                        //这里要做成动态的,可能有配置信息
                        o.attributes.push(dynamicBuildGroupAttribute(igroup));
                    }
                });
                _global_class_attributes = o.attributes;
            }

            // //检查必显项目
            // if(o.properties){
            //     for(var _pro of o.properties){
            //         if((_pro.showView && _config.model=="view")){
            //             var _find_pro = false;
            //             for(var ii of _global_data_properties){
            //                 if(ii.name == _pro.name){
            //                     _find_pro=true;
            //                     break;
            //                 }
            //             }
            //             if(!_find_pro){
            //                 if(!_pro.matchRegex){
            //                     _global_data_properties.push(_pro);
            //                 }
            //             }
            //         }
            //     }
            // }

            //使用pasteform模式加载表单内容到UI
            LoadModelProperity(_global_data_properties);

            if (o.table) {
                //paste-btn-submit
                if (o.table.readOnly) {
                    $(".paste-btn-submit").hide();
                }
            }
        }
    });
}

/**
 * 构建分组 
 * @param {*} igroup 
 * @returns 
 */
function dynamicBuildGroupAttribute(igroup) {
    //未完待续,是否结合配置信息
    return {
        name: "group",
        args1: igroup,
        args2: dynamicReadSettingName(igroup)
    };
}

//递归处理数据类型! new Property


/**
 * 基于json数据创建字段信息
 * @param {*} jobj 
 * @param {*} _head 名称前缀
 * @param {*} _index -1表示顶层,0表示第二层
 */
function dynamicBuildPropertyInfo(jobj, _head, _index) {
    // console.log('build obj:', jobj,' head:', _head);
    if (_head.indexOf('__') == 0) {
        _head = _head.substring(2);
    }
    if (jobj) {
        for (var _name in jobj) {
            var _value = jobj[_name];
            var _set_name = dynamicReadSettingName(`${_head}${_name}`);
            var _property = dynamicFindPropertryFromSetting(_set_name);
            //转化一下,引用类型会被干扰
            if (_property) {
                var _pro_str = JSON.stringify(_property);
                _property = JSON.parse(_pro_str);
            }
            //编辑模式必须和配置匹配
            if (!_property) {
                // if (_config.model != "edit" && _config.model != "add") {
                var _new_pro = dynamicBuildNewProperty(`${_head}${_name}`, _value, _index);
                var _need_push = true;
                var _type = typeof (_value);
                switch (_type) {
                    case "number":
                        {
                            _new_pro.dataType = "number";
                            _new_pro.value = _value;
                        }
                        break;
                    case "string":
                        {
                            _new_pro.dataType = "text";
                            _new_pro.value = _value;
                        }
                        break;
                    case "boolean":
                        {
                            _new_pro.dataType = "switch";
                            _new_pro.value = _value;
                        }
                        break;
                    default: {
                        _need_push = false;
                        if (Array.isArray(_value)) {
                            //是一个数组 这里有问题,未完待续
                            // console.log('is array val:',_value,' name:',_name,' jobj:',jobj);

                            //检查内容类型
                            var _item_is_object = true;
                            for (var ii of _value) {
                                if (typeof (ii) == 'object') {
                                    _item_is_object = true;
                                } else {
                                    _item_is_object = false;
                                    _need_push = true;
                                    if (typeof (ii) == 'number') {
                                        _new_pro.dataType = "Int64[]";
                                    }
                                }
                                break;
                            }
                            if (_item_is_object) {
                                for (var k = 0; k < _value.length; k++) {
                                    var ii = _value[k];
                                    // dynamicBuildPropertyInfo(ii, `${_head}__${_name}__${k}__`, k);
                                    dynamicBuildPropertyInfo(ii, `${dynamicBuildName(_head, _name)}__${k}__`, k);
                                }
                            }
                        } else {
                            // console.log('next object name:', _name,' head:',_head, _value);
                            //可能是下一级
                            // dynamicBuildPropertyInfo(_value, `${_head}__${_name}__`, -1);
                            dynamicBuildPropertyInfo(_value, `${dynamicBuildName(_head, _name)}__`, -1);
                        }
                    }
                }
                if (_need_push) {
                    _global_data_properties.push(_new_pro);
                }
                // }
            } else {
                _property.value = _value;
                // if(!_property.needRemove ){
                dynamicAppendGroupAttribute(_property, dynamicBuildName(_head, _name));
                //这里还要做一个过滤,匹配模式,才添加进去!
                _global_data_properties.push(_property);

                // }
            }
        }
    }
}

/**
 * 
 * @param {*} _head 
 * @param {*} _name 
 */
function dynamicBuildName(_head, _name) {
    if (_head.lastIndexOf('__') == _head.length - 2) {
        return `${_head}${_name}`;
    } else {
        return `${_head}__${_name}`;
    }
}

/**
 * 查找这个属性
 */
function dynamicFindPropertryFromSetting(_name) {
    if (_setting_data_properties) {
        for (var one of _setting_data_properties) {
            if (!one.matchRegex) {
                if (one.name == _name) {
                    return one;
                }
            }
        }

        //基于正则方式查找!
        for (var one of _setting_data_properties) {
            if (one.matchRegex) {
                var _reg = new RegExp(one.name);
                if (_reg.test(_name)) {
                    var _item = JSON.stringify(one);
                    var _item_obj = JSON.parse(_item);
                    _item_obj.name = _name;
                    return _item_obj;
                }
            }
        }
    }
    return null;
}

/**
 * 获取配置名称,示例info__0__name为info__name
 * @param {*} _name 
 * @returns 
 */
function dynamicReadSettingName(_name) {
    var _setting_name = _name;
    if (_name.indexOf("__") >= 0) {
        var strs = _name.split('__');
        var _new_strs = new Array();
        for (var i = 0; i < strs.length; i++) {
            var _str = strs[i];
            var _num = Number(_str);
            if (isNaN(_num)) {
                _new_strs.push(_str);
            }
        }
        _setting_name = _new_strs.join('__');
    }
    return _setting_name;
}

/**
 * 生成一个字段信息
 * @param {*} _name 
 * @param {*} _value 
 * @returns 
 */
function dynamicBuildNewProperty(_name, _value, _index) {
    // var _set_name = dynamicReadSettingName(_name);
    var _info = {
        name: _name,
        title: "",
        value: _value,
        dataType: "text"
    };
    dynamicAppendGroupAttribute(_info, _name);
    if (!_info.title) {
        _info.title = _name;
    }
    return _info;
}

/**
 * 添加分组特性 也有可能不添加,name中有__的才添加
 * @param {*} _info 
 * @param {*} _name 
 */
function dynamicAppendGroupAttribute(_info, _name) {
    if (_name.indexOf("__") > 0) {
        var _la = _name.lastIndexOf('__');
        var _group = _name.substring(0, _la);
        if (!_info.attributes) {
            _info.attributes = new Array();
        }
        _info.attributes.push({
            name: "group",
            args1: _group
        });
        if (!_info.title) {
            _info.title = _name.substring(_la + 2);
        }
    }
}



/*******************************/

/**
 * 配置table的菜单列的宽度,最大500 尽量保持2行
 */
function toolResizeTapMenuWidth() {

    setTimeout(() => {
        if ($(".tapmenu").length > 0) {
            var $tapMenu = $(".tapmenu").eq(0);
            var $buttons = $tapMenu.find("a");
            var buttonCount = $buttons.length;

            if (buttonCount === 0) return;

            // 获取所有按钮的实际宽度
            var buttonWidths = [];
            var totalWidth = 0;
            var maxButtonWidth = 0;

            $buttons.each(function () {
                var btnWidth = $(this).outerWidth(true);
                buttonWidths.push(btnWidth);
                totalWidth += btnWidth;
                if (btnWidth > maxButtonWidth) {
                    maxButtonWidth = btnWidth;
                }
            });

            var targetWidth;
            var maxWidth = 280;
            if (_config) {
                if (_config.menu_max_width) {
                    maxWidth = _config.menu_max_width;
                }
            }
            var minWidth = 120;
            var spacing = 15;//间隔大小

            // 计算单行宽度 56+56+15 = 127 + 15*2 = 157
            var singleRowWidth = totalWidth + spacing * (buttonCount - 1) + spacing * 2;

            // 如果单行能放下
            if (singleRowWidth <= maxWidth) {
                targetWidth = Math.max(singleRowWidth, minWidth);
                //127
            } else {
                // 估算两行宽度
                var twoRowWidth;
                if (buttonCount <= 3) {
                    // 3个按钮时,可能是1+2或2+1布局
                    twoRowWidth = Math.max(
                        maxButtonWidth * Math.ceil(buttonCount / 2),
                        totalWidth / 2
                    ) + spacing + spacing * 2;
                } else {
                    // 4个以上按钮,平均分配
                    var buttonsPerRow = Math.ceil(buttonCount / 2);
                    twoRowWidth = Math.max(
                        maxButtonWidth * buttonsPerRow,
                        totalWidth / 2
                    ) + spacing * (buttonsPerRow - 1) + spacing * 2;
                }

                // 两行方案是否可行(不超过最大宽度)
                if (twoRowWidth <= maxWidth) {
                    targetWidth = Math.max(twoRowWidth, minWidth);
                } else {
                    // 两行也放不下,使用最大宽度
                    targetWidth = maxWidth;
                    console.log('使用最大宽度,按钮将自动换行(可能超过2行)');
                }
            }

            // console.log('计算出的目标宽度:', targetWidth);

            function applyWidthToLastTh() {
                var $lastTh = $(".table th:last");
                if ($lastTh.length > 0) {
                    // console.log('找到th:last,应用宽度:', targetWidth);
                    $lastTh.css({
                        "min-width": targetWidth + "px",
                        "width": targetWidth + "px",
                        "max-width": targetWidth + "px"
                    });
                    return true;
                }
                return false;
            }

            // 立即尝试应用
            if (!applyWidthToLastTh()) {
                // 重试机制
                var retryCount = 0;
                var maxRetries = 2; // 更多重试次数

                function retryApply() {
                    retryCount++;
                    console.log('尝试查找动态th:last (第' + retryCount + '次)');

                    if (applyWidthToLastTh()) {
                        console.log('成功应用到动态添加的th');
                    } else if (retryCount < maxRetries) {
                        setTimeout(retryApply, 200); // 每200ms重试一次
                    } else {
                        console.warn('尝试' + maxRetries + '次后仍未找到th:last');
                    }
                }

                setTimeout(retryApply, 200);
            }
        }
    }, 100);

    // setTimeout(() => {
    //     if ($(".tapmenu").length > 0) {
    //         var asize = $(".tapmenu").eq(0).find("a").length;
    //         var to_width = 500;
    //         var tosixe = asize * 80 / 2;
    //         if (tosixe < to_width) {
    //             to_width = tosixe;
    //         }
    //         console.log('计算菜单宽度',to_width);
    //         // $("th:last").width(toWidth);
    //         if (to_width > 100) {
    //             // 使用animate添加动画
    //             // $("th:last").animate({
    //             //     width: toWidth
    //             // }, 50); // 300毫秒的动画时长
    //             // 先设置min-width确保不会被内容撑开
    //             $("th:last").css({
    //                 "min-width": to_width + "px",
    //                 "width": to_width + "px",
    //                 "max-width": to_width + "px"
    //             });
    //             // 再使用animate添加动画
    //             $("th:last").animate({
    //                 width: to_width
    //             }, 50);
    //         }
    //     }
    // }, 100);
}


/**
 * 存储大小美化显示
 * @param {number} bytes - 字节数
 * @param {number} decimals - 小数位数,默认0
 * @returns {string} 美化后的大小字符串
 */
function formatFileSize(bytes, decimals = 0) {
    if (bytes === 0) return '0 B';
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    const base = 1024;
    const exponent = Math.floor(Math.log(bytes) / Math.log(base));
    const unitIndex = Math.min(exponent, units.length - 1);
    const size = (bytes / Math.pow(base, unitIndex)).toFixed(decimals);
    return size + units[unitIndex];
}

/**
 * 将美化后的大小字符串转换回字节数
 * @param {string} sizeString - 美化后的大小字符串,如 "79KB", "1.5MB"
 * @returns {number} 字节数
 */
function parseFileSize(sizeString) {
    if (!sizeString || typeof sizeString !== 'string') return 0;
    const units = {
        'B': 1,
        'KB': 1024,
        'MB': 1024 * 1024,
        'GB': 1024 * 1024 * 1024,
        'TB': 1024 * 1024 * 1024 * 1024
    };
    // 匹配数字和单位
    const match = sizeString.match(/^([\d.]+)\s*([KMGTP]?B)$/i);
    if (!match) return 0;
    const size = parseFloat(match[1]);
    const unit = match[2].toUpperCase();
    // 处理KB特殊情况(K和KB都支持)
    const normalizedUnit = unit === 'K' ? 'KB' : unit;
    if (units[normalizedUnit]) {
        return size * units[normalizedUnit];
    }
    return 0;
}

/**
 * 应对Object.assign会改变类型的问题
 * @param {*} target 
 * @param {*} source 
 * @returns 
 */
function PastedeepMerge(target, source) {
    const result = { ...target };

    for (const key in source) {
        // 如果目标字段是数组,且源字段是字符串,则追加到数组
        if (Array.isArray(target[key]) && typeof source[key] === 'string') {
            result[key] = [...target[key], source[key]];
        }
        // 如果目标字段是数组,且源字段也是数组,则合并
        else if (Array.isArray(target[key]) && Array.isArray(source[key])) {
            result[key] = [...target[key], ...source[key]];
        }
        // 其他情况直接覆盖
        else {
            result[key] = source[key];
        }
    }

    return result;
}

/**
 * 打印特定区域 添加css引入 添加延迟
 */
function printTable() {
    const printWindow = window.open('', '_blank');
    const tableWrap = document.querySelector('.table_wrap');

    // 获取所有样式表
    let styles = '';
    for (let styleSheet of document.styleSheets) {
        try {
            for (let rule of styleSheet.cssRules) {
                styles += rule.cssText + '\n';
            }
        } catch (e) {
            console.warn('无法访问某些样式表(可能是跨域限制)');
        }
    }

    const cssLinks = Array.from(document.querySelectorAll('link[rel="stylesheet"]'))
        .map(link => `<link rel="stylesheet" href="${link.href}">`)
        .join('');

    printWindow.document.write(`
        <html>
            <head>
                <title>打印表格</title>
                ${cssLinks}
                <style>
                    @page {
                        size: A4 landscape;
                        margin: 1cm;
                    }
                    ${styles}
                    /* 添加打印专用样式 */
                    @media print {
                        body { margin: 0; padding: 20px; }
                        .no-print { display: none !important; }
                        table { width: 100% !important; }
                    }
                    /* 加载提示样式 */
                    .loading-message {
                        position: fixed;
                        top: 50%;
                        left: 50%;
                        transform: translate(-50%, -50%);
                        background: rgba(0,0,0,0.8);
                        color: white;
                        padding: 20px;
                        border-radius: 5px;
                        z-index: 9999;
                    }
                </style>
            </head>
            <body>
                <div class="loading-message">正在准备打印,请稍候...</div>
                ${tableWrap.outerHTML}
            </body>
        </html>
    `);

    printWindow.document.close();

    // 显示加载提示
    const loadingMessage = printWindow.document.querySelector('.loading-message');

    // 等待 CSS 加载完成
    setTimeout(() => {
        // 移除加载提示
        if (loadingMessage) {
            loadingMessage.remove();
        }

        // 执行打印
        printWindow.print();

        // 可选:打印后自动关闭窗口
        printWindow.onafterprint = function () {
            printWindow.close();
        };

    }, 1000); // 延迟1秒,确保CSS加载完成
}

/**
 * location.search转化成object
 * @param {*} search 
 * @returns 
 */
function parseSearch(search) {
    const params = new URLSearchParams(search);
    const result = {};

    for (const [key, value] of params) {
        // 解析值
        let parsedValue;

        // 检查是否为布尔值
        if (value === 'true' || value === 'false') {
            parsedValue = value === 'true';
        }
        // 检查是否为整数
        else if (/^-?\d+$/.test(value)) {
            parsedValue = parseInt(value, 10);
        }
        // 检查是否为浮点数
        else if (/^-?\d+\.\d+$/.test(value)) {
            parsedValue = parseFloat(value);
        }
        // 默认为字符串
        else {
            parsedValue = value;
        }
        // 处理重复的键
        if (key in result) {
            // 如果已经存在,转换为数组
            if (Array.isArray(result[key])) {
                result[key].push(parsedValue);
            } else {
                result[key] = [result[key], parsedValue];
            }
        } else {
            result[key] = parsedValue;
        }
    }
    return result;
}

/**
 * 清理当前页面的 列排序缓存
 */
function cleanTableColumnOrder() {
    if (typeof global_table_column_order_handler != "undefined") {
        if (global_table_column_order_handler != null) {
            global_table_column_order_handler.cleanOrderCache();
            layer.msg('当前页面列排序缓存已经重置!');
        }
    } else {
        layer.msg('组件未载入,无法执行列排序缓存清理');
    }
}
​ ​