<!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]+)(&)?)?/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>