<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>动态参数</title>
    <!--<link href="../../css/frame.css" rel="stylesheet" />-->
    <link href="css/easyui/easyui.css" rel="stylesheet" />
    <link href="../../../../static/libs/my97/skin/WdatePicker.css" rel="stylesheet">
    <link href="../../../../static/libs/my97/skin/simple/datepicker.css" rel="stylesheet">
    <style type="text/css">
        .textbox-addon-right {
            float: right;
        }

        .treE {
            overflow: hidden
        }

        .treE:hover {
            overflow-y: auto
        }

        .treE::-webkit-scrollbar-track {
            background-color: #2A2C3B;
        }

        .treE::-webkit-scrollbar {
            width: 10px;
            background-color: #F5F5F5;
        }

        .treE::-webkit-scrollbar-thumb {
            /*border-radius: 10px;*/
            background: #286399;
            border: 2px solid rgb(116, 117, 255);
            border-radius: 5px;
        }

        body {
            background: rgba(23, 39, 68, .6);
            height: 400px!important;
            padding: 0 3%!important;
        }
    </style>
</head>

<body>
    <div class="easyui-layout" data-options="fit:true">
        <div data-options="region:'west',split:true" style="width:240px;" >
            <div id="ptree" class="easyui-tree" data-options="fit:true,lines:true,onClick:clickTreeNode,filter:searchTree">
            </div>
        </div>
        <div data-options="region:'center'" style="padding:5px;margin-left: 10px;">
            <div id="pgrid" class="easyui-propertygrid" data-options="showGroup:false,fit:true,fitColumns:true,
                 columns:myColumns,onAfterEdit:onEndEditParameter,onClickRow:onClickPropertyRow">
            </div>
        </div>
        <!--<div data-options="region:'south',border:false" style="height: 40px;padding:8px;">
            <a href="#" id="saveAllChanged" class="settingBtn">保存</a>
        </div>-->
    </div>
    <script src="libs/jquery.min.js"></script>
    <script src="libs/xml.js"></script>
    <script src="libs/jquery.easyui.min.js"></script>
    <script src="libs/jquery.easyui.extension.js"></script>
    <script src="libs/my97/WdatePicker.js"></script>
    <script type="text/javascript">
        var pGridObj;
        var selectedNode; //当前选中的节点
        var changedKeyValues = new Array(); //用于保存已修改的参数集合,在重新加载参数树及提交成功后清空
        var currentRowIndex = null; //当前选中的行
        var edit_xml = null; //保存编辑后的xml信息
        var isDebug = true;

        var myColumns = [
            [{
                field: "name",
                title: "参数名",
                width: 100,
                formatter: function(value, rowData, rowIndex) {
                    return '<span style="display:inline-block;width:96%;overflow: hidden;white-space: nowrap;text-overflow:ellipsis" title="' + value + '">' + value + '</span>';
                }
            }, {
                field: "value",
                title: "值",
                width: 150,
                formatter: parameterValueFormatter,
                styler: parameterStyleFormatter
            }, {
                field: "info",
                title: "说明",
                width: 150,
                formatter: function(value, rowData, rowIndex) {
                    return '<span style="display:inline-block;width:96%;overflow: hidden;white-space: nowrap;text-overflow:ellipsis" title="' + value + '">' + value + '</span>';
                }
            }]
        ];

        $(document).ready(function() {
            pGridObj = $("#pgrid");
            loadParameterTree();
            // $("#saveAllChanged").click(submitAllChanges);
        });

        function clickButton(text) {
            $("#ptree").tree("doFilter", text);
        }
        //
        function searchTree(q, node) {
            return node.text.indexOf(q) > -1;
        }


        //加载参数树
        function loadParameterTree(xmlK, xmlV) {
          let xmlValue = "";
          let xmlKey = "";
          try {
            xmlValue = $.parseXML(xmlV)
            edit_xml = xmlValue;

          } catch (error) {
            console.error("baseconfig,xml结构解析失败请检查格式是否正确")
            console.log("basXML",xmlV)
          }
          try {
            xmlKey = $.parseXML(xmlK);
          } catch (error) {
            console.error("config,xml结构解析失败请检查格式是否正确")
            console.log("configxml",xmlV)
          }

            let jsonData = convertXmlToJson(xmlKey, xmlValue);
            window.xmlStr = ""; //XMLtoString(jsonData);
            $('.datagrid-body').html('')
            $("#ptree").tree("loadData", jsonData);
            // var url = "/do/trafficController/configVal?t=" + new Date().getTime();
            // var dataUrl = "/do/trafficController/configKey?t=" + new Date().getTime();
            // if (isDebug) {
            //     url = "xml/traffic_config_utf8.xml";
            //     dataUrl = "xml/traffic_config_utf8.xml";
            // }

            // $.get(url, null, function(xml) {
            //     //解释XML
            //     var xmlDoc;
            //     try {
            //         xmlDoc = $.parseXML(xml);
            //         edit_xml = xmlDoc;
            //     } catch (e) {
            //         $.messager.alert("错误", "解释参数XML错误!(XML格式不正确)", "error");
            //         return;
            //     }
            //     //加载存储设置值的XML
            //     $.ajax(dataUrl, {
            //         async: true,
            //         dataType: "text",
            //         error: function(jqXHR, status, error) {
            //             $.messager.alert("错误", "获取参数值XML出错!", "error");
            //         },
            //         success: function(data, status, jqXHR) {
            //             try {
            //                 var xmlValueJsonData = $.parseXML(data);
            //             } catch (e) {
            //                 $.messager.alert("错误", "解释参数XML错误!(XML格式不正确)", "error");
            //                 return;
            //             }
            //             var jsonData = convertXmlToJson(xmlDoc, xmlValueJsonData);
            //             console.log(jsonData)
            //             $("#ptree").tree("loadData", jsonData);
            //         }
            //     });

            // }, "text");
        }

        //参数值格式化函数
        function parameterValueFormatter(value, row, index) {

            var valueType = row.type;
            console.log(valueType)
            switch (valueType) {
                case "3":
                    var data = row.editor.options.data;
                    for (var i = 0; i < data.length; i++) {
                        if (data[i].id == value)
                            return data[i].text;
                    }
                    return value;
                    //布尔型,1->开启,0->关闭
                case "4":
                    return parseInt(value) == 1 ? "是" : "否";
                default:
                    return value;
            }
        }

        function parameterStyleFormatter(value, row, index) {
            var valueType = row.type;
            switch (valueType) {
                //布尔型,1->显示为绿色,0->显示为红色
                case "4":
                    return parseInt(value) == 1 ? "color:green" : "color:red";
                default:
                    return "";
            }
        }

        function clickTreeNode(node) {
            selectedNode = node; //保存当前选中的节点
            if (node.gridData) {
                pGridObj.propertygrid("loadData", node.gridData);
            }
        }

        //结果编辑参数
        function onEndEditParameter(index, row, changes) {
            if (changes && changes.value != null && changes.value != undefined) {
                if (window.console)
                    console.log(selectedNode.attr.path + "/" + row.name + "=" + changes.value);
                var key = selectedNode.attr.path + "/" + row.name + "#" + row.type;
                //替换'/'为'\\'
                key = key.replace(/\//g, "\\");
                changedKeyValues[key] = changes.value; //保存参数
                //提交xml
                editor_chgxml(selectedNode.attr.path + "/" + row.name,changes.value);

                //提交路径
                // onchangexmlNode();
            }
        }

        function onchangexmlNode() {
            window.xmlStr = "";
            for (var key in changedKeyValues) {
                var _key = key.split("#")[0];
                window.xmlStr += key + "@" + changedKeyValues[key] + ";";
            }
            // console.log("window.xmlStr="+window.xmlStr);
        }

        //编辑xml
        //编辑xml
        function editor_chgxml(path, value) {
            console.log(path);
            console.log(value);
            var xml_node = path.split("/");
            $root = $(edit_xml).find("root");
            if (xml_node != null && xml_node.length) {
                // $_chil = $root.find(xml_node[1]);
              var $_chil = null;
              var _chilList = $root.children();
              for(var j = 0; j< _chilList.length; j++){
                  if(_chilList[j].nodeName == xml_node[1]){
                    $_chil = _chilList[j]
                  }
              }
			        if ($_chil == null) {
                    $root.appendXml("<" + xml_node[1] + "/>");
                    $_chil = $root.children();//$root.find(xml_node[1]);
                    $_chil = $_chil[$_chil.length-1];
                    for (var i = 2; i < xml_node.length; i++) {
                        $($_chil).appendXml("<" + xml_node[i] + "/>");
                        $_chil = $_chil.lastChild;
                        if (i == xml_node.length - 1) {
                            $_chil.textContent  = value;
                        }
                    }
                } else {
                    var _chil;
                    for (var i = 2; i < xml_node.length; i++) {
                        _chil = $_chil;
                        //$_chil = _chil.get//_chil.find(xml_node[i]);
                        //if ($_chil != null && $_chil.length == 0) {
                        //    _chil.appendXml("<" + xml_node[i] + "/>");
                        //    $_chil = _chil.find(xml_node[i]);
                        //}else {
                          var childrens = $($_chil).children();
                          var isnotself_chi=false;

                          for(var k = 0; k <  childrens.length; k++){
                            if(childrens[k].nodeName == xml_node[i]){
                              isnotself_chi=true;
                              $_chil = childrens[k];
                            }
                          }
                          if(  !isnotself_chi){
                            $(_chil).appendXml("<" + xml_node[i] + "/>");
                            $_chil = _chil.lastChild;
                          }

                        //}
                        if (i == xml_node.length - 1) {
                            $($_chil).val(value);
                            $_chil.textContent  = value;
                        }
                    }
                }
            }
            window.xmlStr = XMLtoString(edit_xml);
            console.log("window.xmlStr=" + window.xmlStr)
        }

        // function editor_xml(path,value){
        //     console.log(path);
        //     console.log(value);
        // 	var xml_node = path.split("/");
        //     $root = $(edit_xml).find("root");
        //     console.log($root);
        // 	if(xml_node != null && xml_node.length){
        //         $_chil = $root.find(xml_node[1]);
        // 		if(xml_node.length == 3){
        // 			$_chil = $_chil.find(xml_node[2]);
        // 		}else if(xml_node.length > 3){
        // 			for(var i = 2 ; i < xml_node.length ; i++){
        //     			$_chil = $_chil.find(xml_node[i]);
        //     		}
        // 		}
        // 		$_AttribDefault = $_chil.find("AttribDefault");
        // 		$_AttribDefault.text(value);
        // 	}

        // window.xmlStr = XMLtoString(edit_xml);
        //          	console.log(xmlStr)
        // }

        //xml转化成string
        function XMLtoString(elem) {
            var serialized;
            try {
                // XMLSerializer exists in current Mozilla browsers
                serializer = new XMLSerializer();
                serialized = serializer.serializeToString(elem);
            } catch (e) {
                // Internet Explorer has a different approach to serializing XML
                serialized = elem.xml;
            }

            return serialized;
        }


        //点击属性表格行
        function onClickPropertyRow(index, row) {
            currentRowIndex = index;
            //开始编辑表格
            $("#pgrid").propertygrid("beginEdit", index);
        }
        //提交所有的修改
        function submitAllChanges() {
            if (currentRowIndex) {
                $("#pgrid").propertygrid("unselectRow", currentRowIndex);
            }
            setTimeout(submitAllChangesToServer, 200);
        }
        //提交修改到服务器
        function submitAllChangesToServer() {
            var dataString = "";

            for (var key in changedKeyValues) {
                if (dataString.length > 0)
                    dataString = dataString + "&" + encodeURIComponent(key) + "=" + changedKeyValues[key];
                else
                    dataString = dataString + encodeURIComponent(key) + "=" + changedKeyValues[key];
            }
            //              console.log(dataString)
            if (dataString.length == 0) {
                $.messager.alert("提示", "无需要保存的修改!", "info");
                return;
            }
            //添加securityToken
            /* var securityToken = document.getElementsByName("-xsrf-");
             if (securityToken.length > 0) {
                 dataString += "&-xsrf-=" + securityToken[0].value;
             } else {
                 alert("securityToken为空!不能提交!");
                 return;
             }*/
            //提交到后台接口进行保存
            //            var saveParameterUrl = "/settings/advanced/save";
            /* var saveParameterUrl = "/do/trafficController/saveConfig";
             $.post(saveParameterUrl, dataString, function(data) {
                 if (!data.error) {
                     $.messager.alert("结果", "保存失败!原因:" + data.feedback.Msg, "error");
                 } else {
                     $.messager.alert("结果", "保存成功!", "info");
                     //保存成功,清空上次修改的参数
                     changedKeyValues = new Array();
                 }
             }, "json");*/
        }

        //解释参数树为Tree组件要求的Json格式
        function convertXmlToJson(xml, xmlValue) {
            var jsonData = [];
            //如果XMl的节点不为空
            var rootNode = $(xml).find("root");
            if (rootNode.length > 0) {
                var idgetter = getIdGetter();
                var treeNode = convertToTreeNode(rootNode[0], idgetter, "");
                bindXmlNodeToTreeNode(treeNode, rootNode[0], idgetter, xmlValue);
                //添加到Json数据
                jsonData = treeNode.children;
            }
            return jsonData;
        }

        //用于获取累加的树结点Id
        function getIdGetter() {
            var id = 1;
            return function() {
                return id++;
            };
        }
        //绑定Xml结点到Tree结点
        function bindXmlNodeToTreeNode(parentTreeNode, xmlNode, idGetter, valueXml) {
            var childNodes = getXmlChildNodes(xmlNode);
            for (var i = 0; i < childNodes.length; i++) {
                var currentNode = childNodes[i];

                //判断结点是否是叶节点(把属于右侧的参数拆分出去)
                var isEndNode = isEndNodeFun(currentNode);
                var treeNode; //当前节点对应的TreeNode
                if (isEndNode) {
                    //把子节点格式化为propertiesGrid的Json格式
                    var nodePath = parentTreeNode.attr.path + "/" + currentNode.nodeName;
                    parentTreeNode.addGridData(getGridData(currentNode, valueXml, nodePath));
                } else {
                    treeNode = convertToTreeNode(currentNode, idGetter, parentTreeNode.attr.path);
                    //循环添加所有的子节点
                    bindXmlNodeToTreeNode(treeNode, currentNode, idGetter, valueXml);
                    parentTreeNode.children.push(treeNode);
                }
            }
        }

        //转换为PropertyGrid需要的格式
        function getGridData(currentNode, valueXml, nodePath) {
            var childNodes = getXmlChildNodes(currentNode);

            var pType = childNodes[0].text ? childNodes[0].text : childNodes[0].textContent;
            var pInfo = childNodes[1].text ? childNodes[1].text : childNodes[1].textContent;
            var pDefault = childNodes[2].text ? childNodes[2].text : childNodes[2].textContent;
            var pValue = getValueFromValueXml(valueXml, nodePath);
            //对数值进行格式化
            pDefault = getValidateValue(pType, pDefault);
            pValue = getValidateValue(pType, pValue);

            pValue = pValue ? pValue : pDefault; //如果当前节点的值没有改变,则取默认值
            // pValue = pDefault;
            var pRange = childNodes[3].text ? childNodes[3].text : childNodes[3].textContent;
            return {
                name: currentNode.nodeName,
                value: pValue,
                defaultValue: pDefault,
                type: pType,
                info: pInfo,
                group: "default",
                editor: getEditor(pType, pRange)
            };
        }

        //从另一个值Xml中获取已经改变的值
        function getValueFromValueXml(valueXml, nodePath) {
            //使用遍历的方式去查找元素
            var isFound = true;
            var nodes = nodePath.split("/");
            var tempNode = valueXml;
            for (var i = 0; i < nodes.length; i++) {
                tempNode = getDirectChildByTagName(tempNode, nodes[i]);
                if (!tempNode) {
                    isFound = false;
                    break;
                }
            }
            if (isFound) {
                let o = tempNode.text || tempNode.textContent
                console.log(o)
                return tempNode.text ? tempNode.text : tempNode.textContent;
            } else
                return null;
        }

        //根据节点的类型,返回合适的编辑器
        /*
            pType:
                0 - Int
                1 - Float
                2 - String
                3 - Enum   枚举值在 Range字段内
                4 - Boolean
                5 - Time
                6 - Undefined
        */
        function getEditor(pType, pRange) {
            var editor = {
                type: null,
                options: {}
            };
            //最小值,最大值
            var min = null;
            var max = null;
            if (pRange) {
                var rangePart = getNumRange(pRange);
                min = rangePart[0];
                max = rangePart[1];
            }
            switch (pType) {
                case "0":
                    editor.type = "numberspinner";
                    if (min)
                        editor.options.min = parseInt(min);
                    if (max)
                        editor.options.max = parseInt(max);
                    editor.options.validType = "range[" + min + "," + max + "]";
                    break;
                case "1":
                    editor.type = "numberbox";
                    if (min)
                        editor.options.min = parseFloat(min);
                    if (max)
                        editor.options.max = parseFloat(max);
                    editor.options.precision = 4; //浮点数默认4位小数
                    editor.options.validType = "range[" + min + "," + max + "]";
                    break;
                case "3":
                    //枚举类型
                    editor.type = "combobox";
                    editor.options = {
                        valueField: "id",
                        textField: "text",
                        required: true,
                        editable: false,
                        data: getComboboxData(pRange)
                    };
                    break;
                case "4":
                    editor.type = "checkbox";
                    editor.options.on = 1;
                    editor.options.off = 0;
                    break;
                case "5":
                    editor.type = "timespinner";
                    editor.options = getTimeOptions(pRange);
                    break;
                case "2":
                case "6":
                default:
                    editor.type = "validatebox";
                    editor.options = getTextOptions(pRange);
                    break;
            }
            return editor;

            function getComboboxData(pRangeString) {
                var enumRegex = /(-?\d+)-(([0-9a-zA-Z\u4e00-\u9faf]+)(&amp;)?)?/g; //枚举类型的正则表达式
                var comboboxData = [];
                var match = enumRegex.exec(pRangeString);
                while (match != null) {
                    comboboxData.push({
                        id: match[1],
                        text: match.length >= 4 ? match[3] : ""
                    });
                    match = enumRegex.exec(pRangeString);
                }
                return comboboxData;
            }

            function getNumRange(pRangeString) {
                var numRangeRegex = /(-?([0-9]+\.)?[0-9]*)-(-?([0-9]+\.)?[0-9]*)/g; // 数字范围类型的正则表达式
                var data = [];
                var match = numRangeRegex.exec(pRangeString);
                if (match != null) {
                    data.push(match[1]);
                    data.push(match[3]);
                }
                return data;
            }

            function getTimeOptions(pRangeString) {
                var options = {};
                var timeRangeParts;
                if (pRange) {
                    timeRangeParts = pRangeString.split("-");
                    if (timeRangeParts.length == 2) {
                        options.max = timeRangeParts[0].split(":")[1].replace(/_/g, ":");
                        options.min = timeRangeParts[1].split(":")[1].replace(/_/g, ":");
                        options.required = true;
                        options.showSeconds = true;
                        options.dateFmt = "HH:mm:ss";
                    }
                }
                return options;
            }
            // 构造Text组件的参数
            function getTextOptions(pRangeString) {
                return {
                    validType: "maxLength[" + pRangeString + "]"
                };
            }
        }

        //格式Xml中的值为合法的格式
        function getValidateValue(type, value) {
            if (value) {
                switch (type) {
                    case "5":
                        value = value.split(":")[1].replace(/_/g, ":");
                        break;
                    default:
                }
            }
            return value;
        }

        //是否是参数树的叶节点
        function isEndNodeFun(currentNode) {
            var childNodes = getXmlChildNodes(currentNode);

            if (currentNode && childNodes && childNodes.length > 0 &&
                childNodes[0].nodeName == "AttribType") {
                return true;
            } else {
                return false;
            }
        }
        //获取直系子节点
        function getDirectChildByTagName(node, tagName) {
            var nodes = getXmlChildNodes(node);
            for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].nodeName == tagName)
                    return nodes[i];
            }
            return null;
        }
        //获取XML节点的子节点列表,兼容IE及非IE
        function getXmlChildNodes(xmlNode) {
            //IE下是childNodes,非IE下是children
            if (xmlNode.childNodes) {
                var currentNode;
                //遍历所有的子节点
                var validateNodeArray = new Array();
                for (var i = 0; i < xmlNode.childNodes.length; i++) {
                    currentNode = xmlNode.childNodes[i];
                    if (currentNode.nodeName == "#text") {
                        continue;
                    }
                    validateNodeArray.push(currentNode);
                }
                return validateNodeArray;
            } else {
                return xmlNode.children;
            }
        }
        //把一个XMl结点转为TreeNode
        function convertToTreeNode(xmlNode, idGetter, parentName) {
            return {
                id: idGetter(),
                text: xmlNode.nodeName,
                children: [],
                attr: {
                    path: function() {
                        if (parentName)
                            return parentName + "/" + xmlNode.nodeName; //保存根节点到当前节点的路径
                        else {
                            return xmlNode.nodeName;
                        }
                    }()
                },
                gridData: {
                    total: 0,
                    rows: []
                },
                addGridData: function(data) {
                    this.gridData.total++;
                    this.gridData.rows.push(data);
                }
            };
        }

        function submit(params) {
            try {
                $('#pgrid').datagrid('endEdit', currentRowIndex)
            } catch (error) {

            }
        }
    </script>
</body>

</html>