12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253 |
- /**
- * 表达式编辑器的环境编辑公共类
- * @author hjh
- */
- (function () {
- /**判断当前页面是否是HRS运行界面 */
- function IsRunningPage() {
- let win = window;
- do {
- if (win.HrsPage != null) {
- return true;
- } else {
- win = win.parent;
- }
- } while (win !== window.top);
- return false;
- }
- function getQueryVariable(variable) {
- let query = decodeURI(window.location.search.substring(1));
- let vars = query.split("&");
- for (let i = 0; i < vars.length; i++) {
- let pair = vars[i].split("=");
- if (pair[0].toUpperCase() == variable.toUpperCase()) { return decodeURIComponent(pair[1]); }
- }
- return ('');
- }
- var g_needLoadzlExpressEditor = getQueryVariable("g_needLoadzlExpressEditor") == "true";
- //是否是运行界面,仅当非运行界面才加载monaco editor
- if (!IsRunningPage() || (typeof g_needLoadzlExpressEditor != 'undefined' && g_needLoadzlExpressEditor == true)) {
- //获取绝对路径
- let curWwwPath = window.document.location.href;
- let pathName = window.document.location.pathname;
- let pos = curWwwPath.indexOf(pathName);
- window.top.localhostPaht = curWwwPath.substring(0, pos);
- //引入monaco编辑器
- require.config({ paths: { vs: window.top.localhostPaht + '/lib/zlExpressEditor/monaco-editor/min/vs' } });
- require(['vs/editor/editor.main'], function () {
- delete define.amd;
- });
- }
- })();
- /**
- * 环境解析帮助JS
- * */
- class EnvironmentHelper {
- //资源节点类型
- static ResourceNodeType = {
- Path: "path",
- Group: "group",
- Property: "property",
- Method: "method",
- Class: "class"
- };
- /**
- * 属性的类型
- * */
- static PropertyType = {
- Number: "number",
- String: "string",
- Boolean: "boolean",
- Enum: "enum",
- Any: "any"
- };
- /**
- * 根据JS文件路径获取JS文件的内容
- * @param {any} url js文件的路径
- * @param {string} name 扩展的名字,名字不能与已有的重复,不然会后者覆盖前者
- * @param {string} parseCode 是否解析代码并返回节点JSON
- */
- static LoadExtraJsSource(url, name = 'global.js', parseCode = true) {
- let functionJson = null;
- $.ajax({
- type: "GET",
- dataType: "text",
- url: url,
- async: false,
- success: (res) => {
- //添加依赖库
- monaco.languages.typescript.javascriptDefaults.addExtraLib(res, name);
- if (parseCode) {
- let children = new JavaScriptCodeHelper(res).Parse();
- if (children != null && children.length > 0) {
- children = children.sort((a, b) => {
- return b.nodetype.localeCompare(a.nodetype);
- });
- //添加函数到资源树
- functionJson = { id: name, name: name, children: children, iconSkin: "namespace_icon" };
- }
- }
- }
- });
- return functionJson;
- }
- /**
- * 通过实例获取对象含有的方法与属性
- * @param {any} instance
- * @returns {Array, Array} {methods, properties}
- */
- static GetMethedsAndPropertiesWithInstance(instance) {
- var x = instance; // 子类的实例
- var methods = []; // 用于存储所有方法的数组
- var properties = []; // 用于存储所有方法的数组
- while (x) { // 循环直到 x 为 null
- var props = Object.getOwnPropertyNames(x); // 获取 x 上的所有属性名
- for (var prop of props) { // 遍历属性名
- try {
- if (typeof x[prop] === "function") { // 检查属性值是否是函数类型
- if (prop != "constructor" && methods.indexOf(prop) == -1) {
- methods.push(prop); // 添加到方法数组中
- }
- continue;
- }
- } catch (e) { }
- if (properties.indexOf(prop) == -1) {
- properties.push(prop);
- }
- }
- x = Object.getPrototypeOf(x); // 获取 x 的原型对象
- if (x.hasOwnProperty("__lookupGetter__") && x.hasOwnProperty("__lookupSetter__")) {
- break;
- }
- }
- methods = methods.sort();
- properties = properties.sort();
- return { methods, properties };
- }
- /**
- * 解析资源信息
- * @param {JSON} resource
- */
- static ParseResource(resource) {
- //解析资源信息,转为固定的对象
- let info = BaseResourceInfo.ParseResourceInfo(resource);
- return info;
- }
- /**
- * 提取叶子节点
- * @param {any} info
- */
- static ExtractLeafNodes(info) {
- let leafNodes = [];
- if (info.children != null) {
- for (let child of info.children) {
- leafNodes.push(...EnvironmentHelper.ExtractLeafNodes(child));
- }
- } else {
- leafNodes.push(info);
- }
- return leafNodes;
- }
- /**
- * 将资源信息转为JS代码
- * @param {any} resourceInfo
- */
- static ChangeToJsLib(resourceInfo) {
- let jscode = "";
- for (let r of resourceInfo) {
- //分组直接跳过
- if (r.nodetype === EnvironmentHelper.ResourceNodeType.Group) {
- jscode += EnvironmentHelper.ChangeToJsLib(r.children);
- } else {
- let lib = r.ChangeToJsLib();
- jscode += `let ${r.name} = ${lib.substr(r.name.length + 2)};`;
- }
- }
- return jscode;
- }
- /**
- * 将ID串的代码转为显示值[setValue的时候调用,匹配的ID是初始的,替换后的ID是合理化以后的]
- * @param {any} jsCode
- * @param {any} leafNodes
- */
- static ChangeCodeToDisplay(jsCode, leafNodes, _enumSettings) {
- if (jsCode == null) {
- jsCode = "";
- }
- //匹配选项内容
- let regex = /^\/\/选项内容_.*\n(.*)/gm;
- let match;
- let index = 0;
- while ((match = regex.exec(jsCode)) !== null) {
- //改变原Code[+1的原因是去掉\n]
- index = index + match[0].length + 1;
- let enumSetting = new EnumSetting();
- //选项的实际内容
- let code = match[1];
- let nameString = code.split("=")[0];
- enumSetting.name = nameString.substring(4).trim().substring(5);
- //除了“let name =”以后的内容
- code = code.substring(nameString.length + 1).trim();
- //对应的属性
- let property = null;
- if (code.indexOf(".includes(") > -1) {
- //包含与不包含
- if (code[0] == "!") {
- //是否是非包含
- enumSetting.selectedCondition = 3;
- code = code.substring(1);
- } else {
- enumSetting.selectedCondition = 2;
- }
- let splitResult = code.split(".includes(");
- //选中值
- enumSetting.items = JSON.parse(splitResult[0]);
- property = leafNodes.find(p => p._path_avaliableId == splitResult[1].substring(0, splitResult[1].length - 2));
- } else {
- let splitResult = [];
- //等于或不等于
- if (code.indexOf("==") > - 1) {
- enumSetting.selectedCondition = 0;
- splitResult = code.split("==");
- } else if (code.indexOf("!=") > - 1){
- enumSetting.selectedCondition = 1;
- splitResult = code.split("!=");
- } else {
- enumSetting.selectedCondition = 0;
- splitResult = code.split("//");
- splitResult = [splitResult[1], splitResult[0]];
- }
- property = leafNodes.find(p => p._path_avaliableId == splitResult[0].trim());
- //获取items
- //JSON.parse会自动去掉引号
- var selectedValue = JSON.parse(splitResult[1].trim().substring(0, splitResult[1].trim().length - 1));
- enumSetting.items.push(selectedValue);
- }
- //设置属性ID
- enumSetting.propertyId = property.id;
- _enumSettings[enumSetting.name] = enumSetting;
- }
- jsCode = jsCode.substr(index);
- for (let node of leafNodes) {
- //是否含有对应ID
- let index = jsCode.indexOf(node._path_avaliableId);
- if (index > -1) {
- //判断ID前面是否含有'.'
- if (index != 0) {
- //若前方是".",则说明匹配不完整,直接跳过
- if (jsCode[index - 1] == ".") {
- continue;
- }
- //若前方是一个有效的名称字符,则判断该匹配不完整,直接跳过
- if (EnvironmentHelper.IsValidChar(jsCode[index - 1])) {
- continue;
- }
- }
- if ((index + node._path_avaliableId.length) < jsCode.length - 1) {
- //若后方是一个连续的可用命名字符,则匹配不完整,跳过
- if (EnvironmentHelper.IsValidChar(jsCode[index + node._path_avaliableId.length])) {
- continue;
- }
- }
- jsCode = jsCode.replaceAll(node._path_avaliableId, node._path);
- } else if (node.nodetype == this.ResourceNodeType.Method) {
- //兼容以前的组件的中文方法名
- if (node._path_avaliableId.lastIndexOf(".") > 0) {
- var tempPath = node._path_avaliableId.substring(0, node._path_avaliableId.lastIndexOf(".")) + "." + this.NameFormatting(node.name);
- let index = jsCode.indexOf(tempPath);
- if (index > -1) {
- //判断ID前面是否含有'.'
- if (index != 0) {
- //若前方是".",则说明匹配不完整,直接跳过
- if (jsCode[index - 1] == ".") {
- continue;
- }
- //若前方是一个有效的名称字符,则判断该匹配不完整,直接跳过
- if (EnvironmentHelper.IsValidChar(jsCode[index - 1])) {
- continue;
- }
- }
- if ((index + tempPath.length) < jsCode.length - 1) {
- //若后方是一个连续的可用命名字符,则匹配不完整,跳过
- if (EnvironmentHelper.IsValidChar(jsCode[index + tempPath.length])) {
- continue;
- }
- }
- jsCode = jsCode.replaceAll(tempPath, node._path);
- }
- }
- }
- }
- return jsCode;
- }
- /**
- * 将代码的显示值转为ID代码串[GetValue的时候调用,匹配的ID是合理化以后的,返回的ID是初始的]
- * @param {any} jsCode
- * @param {any} leafNodes
- */
- static ChangeDisplayToCode(jsCode, leafNodes, _enumSettings) {
- if (jsCode == null) {
- return "";
- }
- //最初始的Jscode
- let preJscode = jsCode;
- for (let node of leafNodes) {
- let index = -1;
- while (true) {
- index += 1;
- //jsCode内是否含有该节点
- index = jsCode.indexOf(node._path, index);
- if (index > -1) {
- //判断该path是否处于引号内
- if (EnvironmentHelper.IsInsideQuote(jsCode, index)) {
- //处于引号内,则忽略
- continue;
- }
- //判断ID前面是否含有'.'
- if (index != 0) {
- //若前方是".",则说明匹配不完整,直接跳过
- if (jsCode[index - 1] == ".") {
- continue;
- }
- //若前方是一个有效的名称字符,则判断该匹配不完整,直接跳过
- if (EnvironmentHelper.IsValidChar(jsCode[index - 1])) {
- continue;
- }
- }
- //若后方是一个有效的名称字符,则判断该匹配不完整,直接跳过
- if (EnvironmentHelper.IsValidChar(jsCode[index + node._path.length])) {
- continue;
- }
- //替换一次
- jsCode = EnvironmentHelper.ReplaceString(jsCode, index, node._path, node._path_avaliableId);
- //含有则替换对应的Display与Id链
- //jsCode = jsCode.replaceAll(node._path, node._path_avaliableId);
- } else {
- //未找到对应的变量名,直接退出循环
- break;
- }
- }
- }
- try {
- if (_enumSettings != null) {
- for (var setting of Object.values(_enumSettings)) {
- if (preJscode.indexOf(`选项内容_${setting.name}`) > -1) {
- let propertyNode = leafNodes.find(p => p.id == setting.propertyId);
- let enumCode = EnvironmentHelper.GetEnumTruethCode(setting, leafNodes, propertyNode);
-
- jsCode = `//选项内容_${setting.name}\n${enumCode}\n${jsCode}`;
- }
- }
- }
- } catch (e) {
- console.error("ChangeDisplayToCode时,转选项内容的时候报错!");
- }
- return jsCode;
- }
- /**
- * 在指定的下标后,替换对应的字符串一次
- * @param {any} str
- * @param {any} index
- * @param {any} replacement
- * @returns
- */
- static ReplaceString(str, index, match, replacement) {
- const newStr = str.slice(0, index) + str.slice(index).replace(match, replacement);
- return newStr;
- }
- /**
- * 判断给定的索引是否在字符串的引号内。
- * @param {string} str - 要检查的字符串。
- * @param {number} index - 要检查的索引。
- * @returns {boolean} - 如果索引在引号内,则为true,否则为false。
- * @throws {Error} - 如果索引超出范围。
- */
- static IsInsideQuote(str, index) {
- if (index < 0 || index >= str.length) {
- throw new Error('索引超出范围');
- }
- const before = str.slice(0, index);
- let inside = false;
- let singleQuoteCount = 0;
- let doubleQuoteCount = 0;
- for (let i = 0; i < before.length; i++) {
- if (before[i] === '"' && before[i - 1] !== '\\') {
- doubleQuoteCount++;
- } else if (before[i] === "'" && before[i - 1] !== '\\') {
- singleQuoteCount++;
- }
- }
- if (singleQuoteCount % 2 !== 0 || doubleQuoteCount % 2 !== 0) {
- inside = true;
- }
- return inside;
- }
- /**
- * 判断一个字符是否是中文、数字、字母和下划线
- * @param {any} char
- */
- static IsValidChar(char) {
- if (char == null) {
- return false;
- }
- const reg = /^[\u4e00-\u9fa5_a-zA-Z0-9]+$/;
- return reg.test(char);
- }
- /**
- * 名称格式化,主要是要格式化成符合Js变量规则
- * @author 黄建华
- * @param {string} name
- * @returns {string}
- */
- static NameFormatting(name) {
- if (name === null || name === undefined) {
- return name;
- }
- //替换横杠到斜线
- let result = name.replace(/[\-@#%^&*()()!!~??<>《》/ ]/g, '_');
- if (/[0-9]/.test(name[0])) {
- //如果是以数字开头,则添加一个下划线
- result = "_" + result;
- }
- return result;
- }
- /**
- * 启用选项输入插件
- * 针对HRS的选项类型的输入
- * @param {any} editor
- */
- static EnableEnumInputPlugin(editor) {
- //用于监听双击事件,editor没有默认的双击事件
- var lastClick = 0;
- editor.onMouseDown(function (e) {
- var currentTime = new Date().getTime();
- var diffTime = currentTime - lastClick;
- if (diffTime < 200) { // 200毫秒内的两次点击被认为是双击
- var position = e.target.position;
- var model = editor.getModel();
- var word = model.getWordAtPosition(position);
- if (word) {
- if (word.word.startsWith("选项内容_")) {
- let name = word.word.substr(5, word.word.length - 5);
- if (enumSettings.hasOwnProperty(name)) {
- EnvironmentHelper.ShowEnumEditor(enumSettings[name], function (resultSetting) {
- enumSettings[resultSetting.name] = resultSetting;
- //如果名字改了
- if (resultSetting.name != name) {
- // 创建一个 Range 对象
- let range = editor.getSelection();
- // 新内容
- let text = "选项内容_" + resultSetting.name;
- // 创建一个操作对象
- let operation = {
- identifier: { major: 1, minor: 1 },
- range: range,
- text: text,
- forceMoveMarkers: true
- };
- // 执行替换操作
- model.pushEditOperations([], [operation], () => null);
- let decoration = EnvironmentHelper.lightingRange(
- editor,
- new monaco.Range(range.startLineNumber, range.startColumn, range.startLineNumber, range.startColumn + text.length),
- resultSetting.name
- );
- enumSettings[resultSetting.name].decoration = decoration;
- delete enumSettings[name];
- }
- });
- }
- }
- }
- //避免三击连续触发
- lastClick = 0;
- } else {
- lastClick = currentTime;
- }
- });
- //光标变化事件,当光标处于选项中的时候,不允许直接编辑
- editor.onDidChangeCursorPosition(function (e) {
- var word = editor.getModel().getWordAtPosition(e.position);
- //当光标位于选项内容最后的时候,不只读
- if (word && word.word.startsWith("选项内容_")) {
- editor.updateOptions({ readOnly: true });
- } else {
- editor.updateOptions({ readOnly: false });
- }
- });
- //选项内容的整体删除
- editor.onKeyDown(function (e) {
- if (e.code === 'Backspace' || e.code === 'Delete') {
- //当前焦点的位置
- var position = editor.getPosition();
- var model = editor.getModel();
- //获取当前焦点位置对应的词语
- var word = model.getWordAtPosition(position);
- if (word && word.word.startsWith("选项内容_")) {
- //对应的选项名称
- let name = word.word.substr(5, word.word.length - 5);
- editor.updateOptions({ readOnly: false });
- //如果是删除键,则整体删除
- var range = new monaco.Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);
- var id = { major: 1, minor: 1 };
- var text = '';
- var op = { identifier: id, range: range, text: text, forceMoveMarkers: true };
- editor.executeEdits("my-source", [op]);
- e.preventDefault();
- //删除对应的Decoration颜色
- editor.getModel().deltaDecorations(enumSettings[name].decoration, []);
- //删除对应的选项配置
- delete enumSettings[name];
- }
- }
- });
- }
- /**
- * 显示枚举编辑器
- * @param {any} setting
- * @param {any} callback
- */
- static ShowEnumEditor(setting, callback) {
- var property = allLeafNodes.find(p => p.id == setting.propertyId);
- setting.options = property.propertyValue;
- setting.selItemMode = property.selItemMode;
- setting.showMode = property.showMode;
- layer.open({
- title: `选项编辑器-${property._path}`,
- btn: ["确定", "取消"],
- //area: ['400px', '520px'],//宽高
- type: 2,
- moveOut: true,
- content: './subview/enum_editor.html',
- success: function (layero, index) {
- //获取表达式编辑器窗体对象
- let iframeWin = window[layero.find('iframe')[0]['name']];
- //初始化编辑器
- iframeWin.Init(setting, enumSettings);
- this.iframeAuto(layero, index)
- },
- iframeAuto: function (layero, idnex) {
- let iframe_h = layer.getChildFrame("html", idnex).outerHeight()
- , n = $("#layui-layer" + idnex)
- , title_h = n.find(".layui-layer-title").outerHeight() || 0
- , btn_h = n.find(".layui-layer-btn").outerHeight() || 0;
- //外层layer高度等于容器高度加上头尾
- let layer_h = iframe_h + title_h + btn_h;
- let max_h = $(document).height();
- //如果高度超过max_h就设置为max_h,容器高度因为有头和尾,需要减去
- if (layer_h > max_h) {
- iframe_h = `calc(95vh - ${title_h + btn_h}px)`;
- layer_h = '95vh'
- }
- n.css({
- height: layer_h
- });
- n.find("iframe").css({
- height: iframe_h
- });
- this.reset(layero);
- },
- //重置layer的位置
- reset: function (layero) {
- var e = {};
- e.config = this;
- e.layero = layero;
- var g = $(window);
- var t = e.config,
- i = e.layero,
- n = [i.outerWidth(), i.outerHeight()],
- a = "object" == typeof t.offset;
- e.offsetTop = (g.height() - n[1]) / 2,
- e.offsetLeft = (g.width() - n[0]) / 2,
- a ? (e.offsetTop = t.offset[0], e.offsetLeft = t.offset[1] || e.offsetLeft) : "auto" !== t.offset && ("t" === t.offset ? e.offsetTop = 0 : "r" === t.offset ? e.offsetLeft = g.width() - n[0] : "b" === t.offset ? e.offsetTop = g.height() - n[1] : "l" === t.offset ? e.offsetLeft = 0 : "lt" === t.offset ? (e.offsetTop = 0, e.offsetLeft = 0) : "lb" === t.offset ? (e.offsetTop = g.height() - n[1], e.offsetLeft = 0) : "rt" === t.offset ? (e.offsetTop = 0, e.offsetLeft = g.width() - n[0]) : "rb" === t.offset ? (e.offsetTop = g.height() - n[1], e.offsetLeft = g.width() - n[0]) : e.offsetTop = t.offset),
- t.fixed || (e.offsetTop = /%$/.test(e.offsetTop) ? g.height() * parseFloat(e.offsetTop) / 100 : parseFloat(e.offsetTop), e.offsetLeft = /%$/.test(e.offsetLeft) ? g.width() * parseFloat(e.offsetLeft) / 100 : parseFloat(e.offsetLeft), e.offsetTop += g.scrollTop(), e.offsetLeft += g.scrollLeft()),
- "min" === i.data("maxminStatus") && (e.offsetTop = g.height() - (i.find(u[1]).outerHeight() || 0), e.offsetLeft = i.css("left")),
- i.css({
- top: e.offsetTop,
- left: e.offsetLeft
- });
- },
- yes: function (index, layero) {
- let iframeWin = window[layero.find('iframe')[0]['name']];
- var enumSetting = iframeWin.GetEnumSetting();
- if (enumSetting) {
- callback(enumSetting);
- layer.close(index);
- }
- }
- });
- }
- /**
- * 高亮显示对应range的文本
- * @param {any} editor
- * @param {any} range
- * @returns ownerId
- */
- static lightingRange(editor, range) {
- return [];
- let decoration = editor.deltaDecorations(
- editor.getModel().getAllDecorations(),
- [{
- range: range,
- options: {
- isWholeLine: false,
- className: 'enum-content'
- }
- }]
- );
- return decoration;
- }
- /**
- * 将对应的选项转为可执行的代码Code
- * @param {any} setting enumSetting
- */
- static GetEnumTruethCode(setting, leafNodes, propertyNode) {
- if (!setting) {
- throw `选项设置不能为空!`;
- }
- //待组装的Code
- let code = `let 选项内容_${setting.name} = `;
- if (propertyNode.showMode === "选项值域选择") {
- if (propertyNode.selItemMode === "value") {
- code += JSON.stringify(setting.items[0]) + `;//${propertyNode._path_avaliableId}`;
- } else {
- code += JSON.stringify(setting.name) + `;//${propertyNode._path_avaliableId}`;
- }
- } else {
- switch (setting.selectedCondition) {
- case 0:
- //等于与不等于只有单选
- code += propertyNode._path_avaliableId + " == " + JSON.stringify(setting.items[0]) + ";";
- break;
- case 1:
- code += propertyNode._path_avaliableId + " != " + JSON.stringify(setting.items[0]) + ";";
- break;
- case 2:
- //包含与不包含对于数组而言
- code += `${JSON.stringify(setting.items)}.includes(${propertyNode._path_avaliableId});`
- break;
- case 3:
- code += `!${JSON.stringify(setting.items)}.includes(${propertyNode._path_avaliableId});`
- break;
- }
- }
- return code;
- }
- }
- /**
- * JavaScript的帮助类,主要是解析JavaScript代码,并提取其中的函数、变量、类等
- */
- class JavaScriptCodeHelper {
- /**
- * 传入的待解析的代码
- */
- SourceCode;
- /**
- * source中所有的注释
- */
- #Comments = [];
- /**
- * 当前解析的进度
- */
- #Index = 0;
- constructor(sourceCode) {
- this.SourceCode = sourceCode;
- if (window.acorn == null) {
- //引入acorn
- $.ajax({
- type: "GET",
- url: "./extra/acorn/acorn.min.js",
- async: false
- });
- }
- }
- /**
- * 解析JavaScript代码,并将内部的资源转为结构化的JSON
- */
- Parse() {
- if (this.SourceCode == null) {
- return;
- }
- //待返回的资源JSON
- let recource = [];
- //将代码转为ast
- let ast = window.acorn.parse(this.SourceCode, { ecmaVersion: "latest", onComment: this.#Comments });
- //遍历AST树
- ast.body.forEach(node => {
- if (node.type === "ClassDeclaration") {
- //解析Class
- let classJson = this.#AnalyzeClassAst(node);
- if (classJson != null) {
- recource.push(classJson);
- }
- } else if (node.type === "FunctionDeclaration") {
- //解析全局函数
- recource.push({
- id: node.id.name,
- name: node.id.name,
- _path: node.id.name,
- title: this.#GetNodeSource(node),
- iconSkin: "method_icon",
- nodetype: EnvironmentHelper.ResourceNodeType.Method
- });
- } else if (node.type === "VariableDeclaration") {
- node.declarations.forEach((declaration) => {
- //解析变量
- recource.push({
- id: declaration.id.name,
- name: declaration.id.name,
- _path: declaration.id.name,
- title: this.#GetNodeSource(declaration),
- iconSkin: "property_icon",
- nodetype: EnvironmentHelper.ResourceNodeType.Property
- });
- });
- }
- });
- return recource;
- }
- /**
- * 解析Class的AST树
- * @param {any} node class的ast节点
- */
- #AnalyzeClassAst(node) {
- let className = node.id.name;
- let classJson = { id: className, name: className, children: [], iconSkin: "class_icon", nodetype: EnvironmentHelper.ResourceNodeType.Class };
- for (const method of node.body.body) {
- //必须是静态非私有方法
- if (method.type === "MethodDefinition" && method.static === true && method.key.type !== "PrivateIdentifier") {
- let tempNode = {
- id: method.key.name,
- name: method.key.name,
- title: this.#GetNodeSource(method),
- _path: `${className}.${method.key.name}`,
- iconSkin: "method_icon",
- nodetype: EnvironmentHelper.ResourceNodeType.Method
- };
- //属性的Get方法是属性
- if (method.kind === "get") {
- tempNode.iconSkin = "property_icon";
- tempNode.nodetype = EnvironmentHelper.ResourceNodeType.Property;
- }
- classJson.children.push(tempNode);
- } else
- //必须是静态非私有的属性
- if (method.type === "PropertyDefinition" && method.static === true && method.key.type !== "PrivateIdentifier") {
- classJson.children.push({
- id: method.key.name,
- name: method.key.name,
- _path: `${className}.${method.key.name}`,
- title: this.#GetNodeSource(method),
- iconSkin: "property_icon",
- nodetype: EnvironmentHelper.ResourceNodeType.Property
- });
- }
- }
- //若是没有下级则直接隐藏
- if (classJson.children.length === 0) {
- return null;
- } else {
- classJson.children = classJson.children.sort((a, b) => {
- return b.nodetype.localeCompare(a.nodetype);
- });
- return classJson;
- }
- }
- /**
- * 获取节点的所有原文内容,包含头部注释,主要用于Title提示
- * @param {any} node
- */
- #GetNodeSource(node) {
- //1、判断该node是否存在头部注释
- let start = node.start;
- let end = node.end;
- //2、end去掉函数的实际内容
- let content = this.SourceCode.slice(node.start, node.end);
- end = start + content.indexOf("{");
- //当前节点所在行数
- let line = window.acorn.getLineInfo(this.SourceCode, node.start).line;
- //获取该节点之前所有的注释
- let comment = this.#Comments.filter(p => p.end < node.start);
- if (comment.length > 0) {
- //注释结束与哪一行
- let commentLine = window.acorn.getLineInfo(this.SourceCode, comment[comment.length - 1].end);
- //判断该注释是否在该节点的正上方
- if (line === commentLine.line + 1) {
- start = comment[comment.length - 1].start;
- }
- }
- return this.SourceCode.slice(start, end);
- }
- }
- /**
- * 资源父类
- */
- class BaseResourceInfo {
- id;
- //JS可用的变量ID,已经过格式化
- avaliableId;
- name;
- nodetype;
- title;
- children;
- //用于ztree的图标
- iconSkin;
- //用于显示的路径[name的路径]
- _path;
- //用于实际存储的路径
- _path_id;
- //转换后的合理化的ID路径
- _path_avaliableId;
- /**
- * 构造函数
- * @param {any} info
- * @param {any} parent
- */
- constructor(info, parent) {
- if (info.name === null || info.name === undefined) {
- throw `${info.id}的name为null或undefined!`;
- }
- this.name = EnvironmentHelper.NameFormatting(info.name);
- //ID为空的时候,以name作为ID
- if (info.id != null) {
- this.id = info.id;
- } else {
- this.id = this.name;
- }
- //ID格式化,主要为了符合JS的变量标准
- this.avaliableId = EnvironmentHelper.NameFormatting(this.id);
- this.nodetype = info.nodetype;
- this.title = info.note;
- this._path = parent?._path ?? "";
- this._path_id = parent?._path_id ?? "";
- this._path_avaliableId = parent?._path_avaliableId ?? "";
- if (this.nodetype != EnvironmentHelper.ResourceNodeType.Group) {
- if (this._path == "") {
- this._path = this.name;
- this._path_id = this.id;
- this._path_avaliableId = this.avaliableId;
- } else {
- this._path += `.${this.name}`;
- this._path_id += `.${this.id}`;
- this._path_avaliableId += `.${this.avaliableId}`;
- }
- }
- if (info.nodes != null && info.nodes.length > 0) {
- //下级节点
- this.children = BaseResourceInfo.ParseResourceInfo(info.nodes, this);
- }
- }
- /**
- * 解析资源信息
- * @param {any} resourceInfo
- * @param {any} parent
- * @returns
- */
- static ParseResourceInfo(resourceInfo, parent = null) {
- let resultResources = [];
- for (let i of resourceInfo) {
- let info = null;
- switch (i.nodetype) {
- case EnvironmentHelper.ResourceNodeType.Path:
- info = new PathResourceInfo(i, parent);
- break;
- case EnvironmentHelper.ResourceNodeType.Group:
- info = new GroupResourceInfo(i, parent);
- break;
- case EnvironmentHelper.ResourceNodeType.Property:
- info = new PropertyResourceInfo(i, parent);
- break;
- case EnvironmentHelper.ResourceNodeType.Method:
- info = new MethodResourceInfo(i, parent);
- break;
- }
- resultResources.push(info);
- }
- return resultResources;
- }
- /**
- * 转换为可运行的JS
- * */
- ChangeSubNodesToJsLib() {
- let lib = "";
- if (this.children != null) {
- for (let i of this.children) {
- lib += i.ChangeToJsLib() + ",";
- }
- }
- //去除最后一个逗号
- lib = lib.substr(0, lib.length - 1);
- return lib;
- }
- /**
- * 根据类型获取虚拟默认值
- * @param {any} type
- */
- GetDefaultValueByType(type) {
- switch (type) {
- case EnvironmentHelper.PropertyType.Any:
- case EnvironmentHelper.PropertyType.String:
- return "0";
- case EnvironmentHelper.PropertyType.Boolean:
- return false;
- case EnvironmentHelper.PropertyType.Number:
- return 0;
- default:
- return "0";
- }
- }
- /**
- * 获取value的显示字符串
- * @param {any} value
- * @param {any} type
- */
- GetValueDisplayString(value, type) {
- switch (type) {
- case EnvironmentHelper.PropertyType.Boolean:
- case EnvironmentHelper.PropertyType.Number:
- if (value === null || value === "") {
- return "null";
- }
- return value;
- default:
- return `"${BaseResourceInfo.EscapedString(value + "")}"`;
- }
- }
- /**
- * 转义字符串
- * @param {any} str
- * @returns
- */
- static EscapedString(str) {
- if (str == null) {
- return;
- }
- str = str.replaceAll("\"", "\\\"");
- str = str.replaceAll("'", "\\\'");
- return str;
- }
- /**
- * 获取ID链
- * */
- GetIdChain() {
- let id = "";
- if (this._parent != null) {
- id += this._parent.GetIdChain();
- }
- //仅当不是Group的时候参与路径计算
- if (this.nodetype != EnvironmentHelper.ResourceNodeType.Group) {
- if (id.length > 0) {
- id += ".";
- }
- id += this.id;
- }
- return id;
- }
- }
- /**
- * 分组资源
- */
- class GroupResourceInfo extends BaseResourceInfo {
- /**
- * 构造函数
- * @param {any} info
- * @param {any} parent
- */
- constructor(info, parent) {
- super(info, parent);
- this.iconSkin = "namespace_icon";
- }
- ChangeToJsLib() {
- return super.ChangeSubNodesToJsLib();
- }
- }
- /**
- * 路径资源
- */
- class PathResourceInfo extends BaseResourceInfo {
- constructor(info, parent) {
- //拼接路径
- super(info, parent);
- this.iconSkin = "class_icon";
- }
- ChangeToJsLib() {
- return `${this.name} : {${super.ChangeSubNodesToJsLib()}}`;
- }
- }
- /**
- * 属性资源
- */
- class PropertyResourceInfo extends PathResourceInfo {
- propertyType;
- propertyValue;
- selItemMode; //选择“选项明细”返回值的模式:value、 display
- showMode = "表达式编辑";
- /**
- * 构造函数
- * @param {JSON} info json
- * @param {BaseResourceInfo} parent 上级节点
- */
- constructor(info, parent) {
- super(info, parent);
- if (info.description) {
- this.propertyValue = info.description.value;
- this.propertyType = info.description.type;
- this.selItemMode = info.description.selItemMode;
- this.showMode = info.description.showMode;
- switch (this.propertyType) {
- case EnvironmentHelper.PropertyType.Boolean:
- this.iconSkin = "property_bool_icon";
- break;
- case EnvironmentHelper.PropertyType.Number:
- this.iconSkin = "property_number_icon";
- break;
- case EnvironmentHelper.PropertyType.Enum:
- this.iconSkin = "property_enum_icon";
- break;
- case EnvironmentHelper.PropertyType.String:
- this.iconSkin = "property_text_icon";
- break;
- default:
- this.iconSkin = "property_icon";
- break;
- }
- //没有传入默认值的情况下,根据类型虚拟一个默认值
- if (this.propertyValue == null) {
- this.propertyValue = this.GetDefaultValueByType(this.propertyType);
- }
- }
- }
- ChangeToJsLib() {
- return `${this.name} : ${this.GetValueDisplayString(this.propertyValue, this.propertyType)}`;
- }
- }
- /**
- * 方法类型的资源管理
- * */
- class MethodResourceInfo extends PathResourceInfo {
- returnValue;
- returnType;
- selItemMode; //选择“选项明细”返回值的模式:value、 display
- showMode = "表达式编辑";
- argsInfo;
- //方法执行的主体,是个委托
- content;
- constructor(info, parent) {
- super(info, parent);
- if (info.description) {
- this.returnValue = info.description.returnValue;
- this.returnType = info.description.returnType;
- this.selItemMode = info.description.selItemMode;
- this.showMode = info.description.showMode;
- if (this.returnValue == null) {
- this.GetDefaultValueByType(this.returnType);
- }
- this.argsInfo = info.description.argsInfo;
- this.content = info.description.content;
- this.iconSkin = "method_icon";
- }
- }
- ChangeToJsLib() {
- let argsString = "";
- let argsComment = "";
- if (this.argsInfo != null) {
- argsString = this.argsInfo.map(p => p["argName"]).join(",");
- for (let arg of this.argsInfo) {
- argsComment += `* @param {${arg.argType}} ${arg.argName} ${arg.argNote};
- `;
- }
- }
- //let value = this.returnValue;
- //if (this.returnType == PropertyType.String) {
- // value = `"${value}"`;
- //}
- let functionContent = "";
- if (this.content != null) {
- functionContent = this.content.toLocaleString();
- if (functionContent.startsWith("function")) {
- functionContent = functionContent.substr(8, functionContent.length - 8);
- }
- }
- return `
- /**
- * ${this.title}
- ${argsComment}*/
- ${this.name}${functionContent}`;
- }
- }
- class EnumSetting {
- //选项配置的名称
- name;
- //对比方式[0:"==",1:"!=",2:"includes",3:"!includes"]
- selectedCondition;
- //对应的属性的id
- propertyId;
- //选项
- items = [];
- //编辑器的装饰颜色
- decoration;
- //选项的值取"value"还是"display"
- selItemMode = "display";
- //选项值域显示界面的显示模式:表达式编辑、选项值域选择
- showMode = "表达式编辑";
- }
|