import { axios, Tools } from 'platform-core'; class ParameterMapping { /** * 显示顺序映射 */ static #Boost = { //指标类型 INTERFACE: 100, //接口 INDICATOR: 100 - 1, //指标 // 参数类型 CONSTANT: 100, //常量 IN: 100 - 1, //输入 IN_OPTION: 100 - 1, //输入(选项) IN_SUB_OUT: 100 - 1, //输入(子模型输出) INTERMEDIATE: 100 - 2, //中间值 OUT: 100 - 2, //输出 // 元数据类型 ENUM: 0, //枚举 UD_JAVA_CLASS: 200 - 1, //自定义Java类 }; /** * 获取变量替换符前缀 * @param type 类型 * @returns 变量替换符前缀 */ public static getPlaceholderPrefix(type: string) { if (type === 'ENUM') { return '#'; } else { return '$'; } } /** * 获取自动完成项的优先级, 数值越大越优先 * @param type 类型 * @returns 自动完成项的优先级 */ public static getBoost(type: string) { return ParameterMapping.#Boost[type]; } /** * 获取自动完成项的类型 * @param type 类型 * @returns 自动完成项的类型 */ public static getAutoCompletionType(type: string) { if (type === 'ENUM') { return 'enum'; } else if (type === 'CONSTANT') { return 'constant'; } else if (type === 'INDICATOR' || type === 'INTERMEDIATE' || type === 'OUT') { return 'variable'; } else { return 'interface'; } } } class AutoCompletionManager { parameters: any; valueTypes: any; constructor() { this.parameters = {}; this.valueTypes = {}; } public setParameters(parameters: any) { this.parameters = parameters; } public setValueTypes(valueTypes: any) { this.valueTypes = valueTypes; } public getOptions(path: string): any { // 如果没有路径, 返回参数列表 if (!path) { return this.getParameterOptions(); } // 以 . 结束表示对象属性 if (path.endsWith('.')) { path = path.substring(0, path.length - 1); } const names = path.split('.'); if (!names) { return this.getParameterOptions(); } //查找参数 const parameter = this.findParmeterByName(names[0]); if (!parameter) { return null; } let valueType = this.findValueType(parameter.valueType, parameter.valueTypeVersion); if (!valueType || !valueType.properties || valueType.properties.length <= 0) { return null; } let index = 1; while (index < names.length) { valueType = this.findValueTypeByPropertyName(valueType.code, valueType.version, names[index++]); } const options: any[] = []; for (const property of valueType.properties) { const option = this.getOptionItem(property); if (option) { options.push(option); } } return options; } public findParmeterByCode(parameterCode: string) { return this.parameters[parameterCode]; } public findParmeterByName(parameterName: string) { const values = Object.values(this.parameters); for (const value of values) { if (value.name === parameterName) { return value; } } return null; } public findValueType(valueType: string, valueTypeVersion: number): any { if (Tools.isNill(valueType)) { return null; } const key = valueType + (Tools.isNill(valueTypeVersion) ? '' : ':' + valueTypeVersion); return this.valueTypes[key]; } public findValueTypeByPropertyName(valueTypeString: string, valueTypeVersion: number, propertyName: string) { const valueType = this.findValueType(valueTypeString, valueTypeVersion); if (!valueType || !valueType.properties || valueType.properties.length <= 0) { return null; } for (const property of valueType.properties) { if (property.name === propertyName) { return this.findValueType(property.valueType, property.valueTypeVersion); } } return null; } public findValueTypeByPropertyCode(valueTypeString: string, valueTypeVersion: number, propertyCode: string) { const valueType = this.findValueType(valueTypeString, valueTypeVersion); if (!valueType || !valueType.properties || valueType.properties.length <= 0) { return null; } for (const property of valueType.properties) { if (property.code === propertyCode) { return this.findValueType(property.valueType, property.valueTypeVersion); } } return null; } public getParameterOptions(): any { const cache = {}; const options: any[] = []; Object.values(this.parameters).forEach((parameter: any) => { const option = this.getOptionItem(parameter); if (option) { if (!cache[option.label]) { cache[option.label] = option; options.push(option); } } }); for (const option of options) { option.boost = ParameterMapping.getBoost(option.category); } return options; } public getOptionItem(parameter: any) { const valueType = this.findValueType(parameter.valueType, parameter.valueTypeVersion); if (!Tools.isNill(valueType)) { const version = valueType.version ? valueType.name + '(V' + valueType.version + ')' : valueType.name; const info = parameter.valueTypeIsList ? 'List<' + version + '>' : version; return { category: parameter.type, type: ParameterMapping.getAutoCompletionType(parameter.type), label: parameter.name, apply: ParameterMapping.getPlaceholderPrefix(parameter.type) + '{' + parameter.name + '}' + (parameter.valueTypeIsList ? '[0]' : ''), info: info, }; } return null; } public autoCompletionParameters(to: any, matchedText?: any): any { return { from: to, options: this.getParameterOptions(), validFor: /(.*)?/, }; } public autoCompletionProperties(to: any, matchedText?: any): any { const matchedTextReverse = Tools.reverseString(matchedText); const regReverse = /(\.(\](.+?)\[)?\}(.+?)\{[$#])+/g; //匹配 '.]n[}xxx{$#' 模式 // -- -- --- -- -- --- ---- // . ] n [ } xxx {$# const matcheds: any = matchedTextReverse.match(regReverse); if (Tools.isUndefinedOrNull(matcheds) || matcheds.length <= 0) { return null; } const matched = Tools.reverseString(matcheds[0]); const parameterName = matched.replace(/[#$]\{(.+?)\}(\[(.+?)\])?/g, '$1'); if (Tools.isUndefinedOrNull(parameterName)) { return null; } const options = this.getOptions(parameterName); if (Tools.isUndefinedOrNull(options)) { return null; } return { from: to, options: options, validFor: /^(.*)?$/, }; } public doAutoCompletion(context: any): any { const beforeMatched = context.matchBefore(/(.+?)/g); if (Tools.isUndefinedOrNull(beforeMatched)) { return null; } const beforeText = beforeMatched.text || ''; if (beforeText.endsWith('.')) { //匹配属性 return this.autoCompletionProperties(beforeMatched.to, beforeText); } else if (beforeText.endsWith(' ')) { //匹配参数 return this.autoCompletionParameters(beforeMatched.to); } else { return null; } } public load(url: string) { axios.get(url).then((response: any) => { this.setParameters(response.data?.parameters); this.setValueTypes(response.data?.valueTypes); }); } public autoCompletion(): any { return (context: any) => { return this.doAutoCompletion(context); }; } } export { AutoCompletionManager };