86 changed files with 5779 additions and 4441 deletions
@ -0,0 +1,10 @@ |
|||
package io.sc.engine.rule.core.enums; |
|||
|
|||
/** |
|||
* 枚举元数据项值类型枚举 |
|||
*/ |
|||
public enum EnumDictionaryItemValueType { |
|||
STRING, //字符串
|
|||
INTEGER, //整数
|
|||
DECIMAL; //小数
|
|||
} |
@ -1,52 +1,72 @@ |
|||
package io.sc.engine.rule.core.po.dictionary; |
|||
|
|||
import io.sc.engine.rule.core.enums.EnumDictionaryItemValueType; |
|||
|
|||
/** |
|||
* 枚举项 |
|||
* @author wangshaoping |
|||
* |
|||
*/ |
|||
public class EnumItem { |
|||
protected String id; //ID
|
|||
protected String code; //代码
|
|||
protected String name; //名称
|
|||
protected EnumDictionaryItemValueType valueType;//值类型
|
|||
protected String value; //值
|
|||
protected String title; //标题
|
|||
protected String description; //描述
|
|||
protected Integer order; //排序
|
|||
protected String config; //配置
|
|||
|
|||
|
|||
public String getId() { |
|||
return id; |
|||
} |
|||
|
|||
public void setId(String id) { |
|||
this.id = id; |
|||
} |
|||
|
|||
public String getCode() { |
|||
return code; |
|||
} |
|||
|
|||
public void setCode(String code) { |
|||
this.code = code; |
|||
} |
|||
|
|||
public String getName() { |
|||
return name; |
|||
} |
|||
|
|||
public void setName(String name) { |
|||
this.name = name; |
|||
} |
|||
|
|||
public EnumDictionaryItemValueType getValueType() { |
|||
return valueType; |
|||
} |
|||
|
|||
public void setValueType(EnumDictionaryItemValueType valueType) { |
|||
this.valueType = valueType; |
|||
} |
|||
|
|||
public String getValue() { |
|||
return value; |
|||
} |
|||
|
|||
public void setValue(String value) { |
|||
this.value = value; |
|||
} |
|||
public String getTitle() { |
|||
return title; |
|||
} |
|||
public void setTitle(String title) { |
|||
this.title = title; |
|||
} |
|||
|
|||
public String getDescription() { |
|||
return description; |
|||
} |
|||
|
|||
public void setDescription(String description) { |
|||
this.description = description; |
|||
} |
|||
|
|||
public Integer getOrder() { |
|||
return order; |
|||
} |
|||
|
|||
public void setOrder(Integer order) { |
|||
this.order = order; |
|||
} |
|||
public String getConfig() { |
|||
return config; |
|||
} |
|||
public void setConfig(String config) { |
|||
this.config = config; |
|||
} |
|||
} |
|||
|
@ -0,0 +1,174 @@ |
|||
package io.sc.engine.rule.core.util; |
|||
|
|||
import io.sc.platform.util.CollectionUtil; |
|||
import io.sc.platform.util.support.PlaceholderExpression; |
|||
import io.sc.platform.util.support.PlaceholderExpressionPart; |
|||
import io.sc.platform.util.support.StringLengthDescComparator; |
|||
import org.springframework.util.StringUtils; |
|||
|
|||
import java.util.*; |
|||
import java.util.regex.Matcher; |
|||
import java.util.regex.Pattern; |
|||
|
|||
/** |
|||
* 占位符表达式工具类 |
|||
*/ |
|||
public class PlaceHolderEnumExpressionUtil { |
|||
// 占位符表达式的模式匹配
|
|||
// 可匹配以下模式
|
|||
// 1. #{aaa}
|
|||
// 2. #{bbb}[1]
|
|||
// 3. #{ccc}[1].#{ddd}
|
|||
// 4. #{eee}[1].#{fff}[2]
|
|||
// 5. #{ggg}[1].#{hhh}[2].#{iii}
|
|||
private static final String PH_EXPRESSION_REG_PATTERN_STR = "(# \\{ (.+?) \\})(\\[ (.+?) \\])?((\\[ (.+?) \\])?(\\.? (# \\{ (.+?) \\})(\\[ (.+?) \\])?)+?)*"; |
|||
// --- --- ----- --- --- ----- --- --- ----- --- --- --- --- ----- --- --- ----- ---
|
|||
// (# { xxx } )([ nnn ] )?(([ nnn ] )?(.? (# { xxx } )([ nnn ] )?)+?)*
|
|||
// (#{xxx} )([nnn] )?(([nnn] )?(.? (#{xxx} )([nnn ] )?)+?)*
|
|||
// (#{xxx})([nnn])?(([nnn])?(.?(#{xxx})([nnn])?)+?)*
|
|||
// -------- ------- ? ------- - ------ -------
|
|||
// (变量)([下标])?(([下标])?(.?(变量)([下标])?)+?)*
|
|||
private static final Pattern PH_EXPRESSION_REG_PATTERN =Pattern.compile(StringUtils.trimAllWhitespace(PH_EXPRESSION_REG_PATTERN_STR)); |
|||
private static final String PH_EXPRESSION_PART_REG_PATTERN_STR = "(# \\{ (.+?) \\})(\\[ (.+?) \\])?"; |
|||
// --- --- ----- --- --- ----- --- --- ----- --- --- --- --- ----- --- --- ----- ---
|
|||
// (# { xxx } )([ nnn ] )?
|
|||
// (#{xxx})([nnn])?
|
|||
private static final Pattern PH_EXPRESSION_PART_REG_PATTERN =Pattern.compile(StringUtils.trimAllWhitespace(PH_EXPRESSION_PART_REG_PATTERN_STR)); |
|||
private static final Pattern PH_VARIABLE_REG_PATTERN =Pattern.compile("#\\{(.+?)\\}"); |
|||
private static final Pattern PH_VARIABLE_ARRAY_INDEX_REG_PATTERN =Pattern.compile("\\[(.+?)\\]"); |
|||
|
|||
/** |
|||
* 将占位符表达式替换为非占位符表达式,示例: |
|||
* PlaceHolderExpressionUtil.replace("(#{aaa} + #{bbb}[1] - #{ccc}['some.key'].#{xxx}) / (#{ddd}[1].#{eee}[2] + #{fff}[1].#{ggg}[2].#{hhh})","",""); |
|||
* 替换结果为: (aaa + bbb[1] - ccc['some.key'].xxx) / (ddd[1].eee[2] + fff[1].ggg[2].hhh) |
|||
* PlaceHolderExpressionUtil.replace("(#{aaa} + #{bbb}[1] - #{ccc}['some.key'].#{xxx}) / (#{ddd}[1].#{eee}[2] + #{fff}[1].#{ggg}[2].#{hhh})","arg."); |
|||
* 替换结果为: (arg.aaa + arg.bbb[1] - arg.ccc['some.key'].xxx) / (arg.ddd[1].eee[2] + arg.fff[1].ggg[2].hhh) |
|||
* PlaceHolderExpressionUtil.replace("(#{aaa} + #{bbb}[1] - #{ccc}['some.key'].#{xxx}) / (#{ddd}[1].#{eee}[2] + #{fff}[1].#{ggg}[2].#{hhh})","#{arg.","}"); |
|||
* 替换结果为: (#{arg.aaa} + #{arg.bbb[1]} - #{arg.ccc['some.key'].xxx}) / (#{arg.ddd[1].eee[2]} + #{arg.fff[1].ggg[2].hhh}) |
|||
* @param content 字符串 |
|||
* @param prefix 前缀 |
|||
* @param suffix 后缀 |
|||
* @returns 替换后的字符串 |
|||
*/ |
|||
public static String replace(String content,String prefix,String suffix) { |
|||
if (!StringUtils.hasText(content)) { |
|||
return content; |
|||
} |
|||
List<PlaceholderExpression> expressions =parse(content); |
|||
if(!CollectionUtil.hasElements(expressions)){ |
|||
return content; |
|||
} |
|||
// 在替换时, 需要先替换长度较长的, 避免替换错误
|
|||
Map<String,String> sortedCache =new TreeMap<>(new StringLengthDescComparator()); |
|||
String result =content; |
|||
for(PlaceholderExpression expression : expressions){ |
|||
List<PlaceholderExpressionPart> parts =expression.getParts(); |
|||
StringBuilder sb =new StringBuilder(); |
|||
sb.append(prefix); |
|||
int size =parts.size(); |
|||
for(int i=0;i<size;i++){ |
|||
PlaceholderExpressionPart part =parts.get(i); |
|||
if(StringUtils.hasText(part.getArrayIndex())){ |
|||
sb.append(part.getName()).append("[").append(part.getArrayIndex()).append("]"); |
|||
}else{ |
|||
sb.append(part.getName()); |
|||
} |
|||
if(i<size-1){ |
|||
sb.append("."); |
|||
} |
|||
} |
|||
sb.append(suffix); |
|||
sortedCache.put(expression.getExpression(),sb.toString()); |
|||
} |
|||
for(String key : sortedCache.keySet()){ |
|||
result =result.replace(key,sortedCache.get(key)); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 解析占位符表达式 |
|||
* PlaceHolderExpressionUtil.parse("(#{aaa} + #{bbb}[1] - #{ccc}['some.key'].#{xxx}) / (#{ddd}[1].#{eee}[2] + #{fff}[1].#{ggg}[2].#{hhh})","",""); |
|||
* 解析结果如下: |
|||
* [{ |
|||
* "expression" : "#{aaa}", |
|||
* "parts" : [ { "name" : "aaa", "arrayIndex" : null } ] |
|||
* }, { |
|||
* "expression" : "#{bbb}[1]", |
|||
* "parts" : [ { "name" : "bbb", "arrayIndex" : "1" } ] |
|||
* }, { |
|||
* "expression" : "#{ccc}['some.key'].#{xxx}", |
|||
* "parts" : [ |
|||
* { "name" : "ccc", "arrayIndex" : "'some.key'" }, |
|||
* { "name" : "xxx", "arrayIndex" : null } |
|||
* ] |
|||
* }, { |
|||
* "expression" : "#{ddd}[1].#{eee}[2]", |
|||
* "parts" : [ |
|||
* { "name" : "ddd", "arrayIndex" : "1" }, |
|||
* { "name" : "eee", "arrayIndex" : "2" } |
|||
* ] |
|||
* }, { |
|||
* "expression" : "#{fff}[1].#{ggg}[2].#{hhh}", |
|||
* "parts" : [ |
|||
* { "name" : "fff", "arrayIndex" : "1" }, |
|||
* { "name" : "ggg", "arrayIndex" : "2" }, |
|||
* { "name" : "hhh", "arrayIndex" : null } |
|||
* ] |
|||
* }] |
|||
* @param content 表达式字符串内容 |
|||
* @return 解析后的占位符表达式列表 |
|||
*/ |
|||
public static List<PlaceholderExpression> parse(String content) { |
|||
Set<PlaceholderExpression> expressions =new TreeSet<>(new Comparator<PlaceholderExpression>() { |
|||
@Override |
|||
public int compare(PlaceholderExpression o1, PlaceholderExpression o2) { |
|||
return o2.getExpression().compareTo(o1.getExpression()); |
|||
} |
|||
}); |
|||
Matcher matcher =PH_EXPRESSION_REG_PATTERN.matcher(content); |
|||
while(matcher.find()){ |
|||
String group =matcher.group(); |
|||
PlaceholderExpression expression =parseExpression(group); |
|||
if(!expression.isEmpty()) { |
|||
expressions.add(expression); |
|||
} |
|||
} |
|||
return CollectionUtil.set2List(expressions); |
|||
} |
|||
|
|||
/** |
|||
* PlaceHolderExpressionUtil.parseExpression("#{fff}[1].#{ggg}[2].#{hhh})"); |
|||
* 解析结果如下: |
|||
* { |
|||
* "expression" : "#{fff}[1].#{ggg}[2].#{hhh}", |
|||
* "parts" : [ |
|||
* { "name" : "fff", "arrayIndex" : "1" }, |
|||
* { "name" : "ggg", "arrayIndex" : "2" }, |
|||
* { "name" : "hhh", "arrayIndex" : null } |
|||
* ] |
|||
* } |
|||
* 解析占位符表达式 |
|||
* @param content 表达式 |
|||
* @return 解析后的表达式对象 |
|||
*/ |
|||
public static PlaceholderExpression parseExpression(String content){ |
|||
PlaceholderExpression expression =new PlaceholderExpression(); |
|||
expression.setExpression(content); |
|||
Matcher matcher =PH_EXPRESSION_PART_REG_PATTERN.matcher(content); |
|||
while(matcher.find()){ |
|||
String group =matcher.group(); |
|||
Matcher variableMatcher =PH_VARIABLE_REG_PATTERN.matcher(group); |
|||
if(variableMatcher.find()){ |
|||
PlaceholderExpressionPart part =new PlaceholderExpressionPart(); |
|||
part.setName(variableMatcher.group(1)); |
|||
Matcher variableArrayIndexMatcher =PH_VARIABLE_ARRAY_INDEX_REG_PATTERN.matcher(group); |
|||
if(variableArrayIndexMatcher.find()){ |
|||
part.setArrayIndex(variableArrayIndexMatcher.group(1)); |
|||
} |
|||
expression.addPart(part); |
|||
} |
|||
} |
|||
return expression; |
|||
} |
|||
} |
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
@ -0,0 +1,226 @@ |
|||
import { axios, Tools } from '@/platform'; |
|||
|
|||
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 options: any[] = []; |
|||
Object.values(this.parameters).forEach((parameter: any) => { |
|||
const option = this.getOptionItem(parameter); |
|||
if (option) { |
|||
options.push(option); |
|||
} |
|||
}); |
|||
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; |
|||
if (parameter.type === 'parameter') { |
|||
if (parameter.valueTypeIsList) { |
|||
return { label: parameter.name, type: 'variable', apply: '${' + parameter.name + '}[0]', info: info }; |
|||
} else { |
|||
return { label: parameter.name, type: 'variable', apply: '${' + parameter.name + '}', info: info }; |
|||
} |
|||
} else if (parameter.type === 'enum') { |
|||
return { label: parameter.name, type: 'enum', apply: '#{' + parameter.name + '}', 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 enumRegReverse = /(\.(\](.+?)\[)?\}(.+?)\{#)+/g; //匹配 '.]n[}xxx{#' 模式
|
|||
// -- -- --- -- -- --- ----
|
|||
// . ] n [ } xxx {#
|
|||
let matcheds: any = matchedTextReverse.match(enumRegReverse); |
|||
if (Tools.isUndefinedOrNull(matcheds) || matcheds.length <= 0) { |
|||
const regReverse = /(\.(\](.+?)\[)?\}(.+?)\{\$)+/g; //匹配 '.]n[}xxx{$' 模式
|
|||
// -- -- --- -- -- --- ----
|
|||
// . ] n [ } xxx {$
|
|||
matcheds = matchedTextReverse.match(regReverse); |
|||
if (Tools.isUndefinedOrNull(matcheds) || matcheds.length <= 0) { |
|||
return null; |
|||
} |
|||
} |
|||
const matched = Tools.reverseString(matcheds[0]); |
|||
let parameterName = matched.replace(/#\{(.+?)\}(\[(.+?)\])?/g, '$1'); |
|||
// ---- --- -- -- --- --
|
|||
// $ { xxx } [ n ]
|
|||
if (Tools.isUndefinedOrNull(parameterName)) { |
|||
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 { |
|||
console.log('>>>>'); |
|||
const beforeMatched = context.matchBefore(/(.+?)/g); |
|||
console.log(beforeMatched); |
|||
|
|||
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) => { |
|||
this.setParameters(response.data?.parameters); |
|||
this.setValueTypes(response.data?.valueTypes); |
|||
}); |
|||
} |
|||
|
|||
public autoCompletion(): any { |
|||
console.log('????'); |
|||
return (context: any) => { |
|||
return this.doAutoCompletion(context); |
|||
}; |
|||
} |
|||
} |
|||
|
|||
export { AutoCompletionManager }; |
@ -0,0 +1,18 @@ |
|||
import { Tools } from '@/platform'; |
|||
|
|||
class PlaceHolder { |
|||
static #parameterPrefix: string = '<span class="p-0.5"><span class="p-0.5 border border-gray-800 rounded-md">'; |
|||
static #enumPrefix: string = '<span class="p-0.5"><span class="p-0.5 border border-orange-400 rounded-md">'; |
|||
static #suffix: string = '</span></span>'; |
|||
|
|||
public static replace(str: string) { |
|||
if (Tools.isString(str)) { |
|||
str = str.replace('<', '<'); |
|||
str = str.replace(/#\{(.+?)\}/g, PlaceHolder.#enumPrefix + '$1' + PlaceHolder.#suffix); |
|||
str = str.replace(/\$\{(.+?)\}/g, PlaceHolder.#parameterPrefix + '$1' + PlaceHolder.#suffix); |
|||
} |
|||
return str; |
|||
} |
|||
} |
|||
|
|||
export { PlaceHolder }; |
@ -0,0 +1,23 @@ |
|||
import { ref } from 'vue'; |
|||
import { axios, Environment, Tools } from '@/platform'; |
|||
|
|||
class UserDefinedFunctionsManager { |
|||
#functions: any; |
|||
|
|||
constructor() { |
|||
this.#functions = ref([]); |
|||
} |
|||
|
|||
public userDefinedFunctions(): any { |
|||
return this.#functions; |
|||
} |
|||
|
|||
public async load() { |
|||
const response = await axios.get(Environment.apiContextPath('/api/re/function?pageable=false&sortBy=name')); |
|||
this.#functions.value = Tools.objects2Objects(response.data?.content, null, (obj: any) => { |
|||
return obj.enable; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
export { UserDefinedFunctionsManager }; |
@ -0,0 +1,226 @@ |
|||
import { axios, Tools } from '@/platform'; |
|||
|
|||
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 options: any[] = []; |
|||
Object.values(this.parameters).forEach((parameter: any) => { |
|||
const option = this.getOptionItem(parameter); |
|||
if (option) { |
|||
options.push(option); |
|||
} |
|||
}); |
|||
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; |
|||
if (parameter.type === 'parameter') { |
|||
if (parameter.valueTypeIsList) { |
|||
return { label: parameter.name, type: 'variable', apply: '${' + parameter.name + '}[0]', info: info }; |
|||
} else { |
|||
return { label: parameter.name, type: 'variable', apply: '${' + parameter.name + '}', info: info }; |
|||
} |
|||
} else if (parameter.type === 'enum') { |
|||
return { label: parameter.name, type: 'enum', apply: '#{' + parameter.name + '}', 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 enumRegReverse = /(\.(\](.+?)\[)?\}(.+?)\{#)+/g; //匹配 '.]n[}xxx{#' 模式
|
|||
// -- -- --- -- -- --- ----
|
|||
// . ] n [ } xxx {#
|
|||
let matcheds: any = matchedTextReverse.match(enumRegReverse); |
|||
if (Tools.isUndefinedOrNull(matcheds) || matcheds.length <= 0) { |
|||
const regReverse = /(\.(\](.+?)\[)?\}(.+?)\{\$)+/g; //匹配 '.]n[}xxx{$' 模式
|
|||
// -- -- --- -- -- --- ----
|
|||
// . ] n [ } xxx {$
|
|||
matcheds = matchedTextReverse.match(regReverse); |
|||
if (Tools.isUndefinedOrNull(matcheds) || matcheds.length <= 0) { |
|||
return null; |
|||
} |
|||
} |
|||
const matched = Tools.reverseString(matcheds[0]); |
|||
let parameterName = matched.replace(/#\{(.+?)\}(\[(.+?)\])?/g, '$1'); |
|||
// ---- --- -- -- --- --
|
|||
// $ { xxx } [ n ]
|
|||
if (Tools.isUndefinedOrNull(parameterName)) { |
|||
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 { |
|||
console.log('>>>>'); |
|||
const beforeMatched = context.matchBefore(/(.+?)/g); |
|||
console.log(beforeMatched); |
|||
|
|||
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) => { |
|||
this.setParameters(response.data?.parameters); |
|||
this.setValueTypes(response.data?.valueTypes); |
|||
}); |
|||
} |
|||
|
|||
public autoCompletion(): any { |
|||
console.log('????'); |
|||
return (context: any) => { |
|||
return this.doAutoCompletion(context); |
|||
}; |
|||
} |
|||
} |
|||
|
|||
export { AutoCompletionManager }; |
@ -0,0 +1,18 @@ |
|||
import { Tools } from '@/platform'; |
|||
|
|||
class PlaceHolder { |
|||
static #parameterPrefix: string = '<span class="p-0.5"><span class="p-0.5 border border-gray-800 rounded-md">'; |
|||
static #enumPrefix: string = '<span class="p-0.5"><span class="p-0.5 border border-orange-400 rounded-md">'; |
|||
static #suffix: string = '</span></span>'; |
|||
|
|||
public static replace(str: string) { |
|||
if (Tools.isString(str)) { |
|||
str = str.replace('<', '<'); |
|||
str = str.replace(/#\{(.+?)\}/g, PlaceHolder.#enumPrefix + '$1' + PlaceHolder.#suffix); |
|||
str = str.replace(/\$\{(.+?)\}/g, PlaceHolder.#parameterPrefix + '$1' + PlaceHolder.#suffix); |
|||
} |
|||
return str; |
|||
} |
|||
} |
|||
|
|||
export { PlaceHolder }; |
@ -0,0 +1,23 @@ |
|||
import { ref } from 'vue'; |
|||
import { axios, Environment, Tools } from '@/platform'; |
|||
|
|||
class UserDefinedFunctionsManager { |
|||
#functions: any; |
|||
|
|||
constructor() { |
|||
this.#functions = ref([]); |
|||
} |
|||
|
|||
public userDefinedFunctions(): any { |
|||
return this.#functions; |
|||
} |
|||
|
|||
public async load() { |
|||
const response = await axios.get(Environment.apiContextPath('/api/re/function?pageable=false&sortBy=name')); |
|||
this.#functions.value = Tools.objects2Objects(response.data?.content, null, (obj: any) => { |
|||
return obj.enable; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
export { UserDefinedFunctionsManager }; |
Loading…
Reference in new issue