Browse Source

update

main
wangshaoping 8 months ago
parent
commit
ae386c0d6f
  1. 2
      erm.frontend/package.json
  2. 2
      gradle.properties
  3. 2
      io.sc.engine.mv.frontend/package.json
  4. 16
      io.sc.engine.rule.client.spring/src/main/resources/META-INF/platform/plugins/messages.json
  5. 61
      io.sc.engine.rule.client.spring/src/main/resources/META-INF/platform/plugins/parameters.json
  6. 17
      io.sc.engine.rule.client.spring/src/main/resources/io/sc/engine/rule/client/spring/i18n/parameters.properties
  7. 17
      io.sc.engine.rule.client.spring/src/main/resources/io/sc/engine/rule/client/spring/i18n/parameters_zh_CN.properties
  8. 1
      io.sc.engine.rule.client/src/main/java/io/sc/engine/rule/client/remote/RemoteLoader.java
  9. 73
      io.sc.engine.rule.client/src/test/java/io/sc/engine/rule/client/test/Test.java
  10. 4
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/code/impl/GroovySourceCodeGenerator.java
  11. 1
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/enums/ProcessorType.java
  12. 33
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/dictionary/dictionary.ftl
  13. 99
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/groovy.ftl
  14. 111
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/lib/lib.ftl
  15. 197
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/lib_groovy.ftl
  16. 153
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/model/argument.ftl
  17. 224
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/model/model.ftl
  18. 25
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/model/sub-model.ftl
  19. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/ARITHMETIC.ftl
  20. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/CONDITION_RANGE.ftl
  21. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TABLE.ftl
  22. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TABLE_2C.ftl
  23. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TREE.ftl
  24. 13
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TREE_FUNCTION.ftl
  25. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/EXECUTION_FLOW.ftl
  26. 13
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/EXECUTION_FLOW_FUNCTION.ftl
  27. 3
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/GROOVY_SCRIPT.ftl
  28. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/NUMBER_RANGE.ftl
  29. 34
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/OPTION_VALUE.ftl
  30. 3
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/PMML.ftl
  31. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/RULE.ftl
  32. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/SINGLE_RULE.ftl
  33. 17
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/SQL.ftl
  34. 4
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/TERNARY.ftl
  35. 12
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/WHEN_THEN.ftl
  36. 11
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/resource_groovy.ftl
  37. 89
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/scorecard/argument.ftl
  38. 147
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/scorecard/score_card.ftl
  39. 2
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/i18n/enums.properties
  40. 2
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/i18n/enums_tw_CN.properties
  41. 2
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/i18n/enums_zh_CN.properties
  42. 2
      io.sc.engine.rule.frontend/package.json
  43. 2
      io.sc.engine.rule.frontend/src/components/index.ts
  44. 36
      io.sc.engine.rule.frontend/src/i18n/messages.json
  45. 50
      io.sc.engine.rule.frontend/src/i18n/messages_tw_CN.json
  46. 50
      io.sc.engine.rule.frontend/src/i18n/messages_zh_CN.json
  47. 16
      io.sc.engine.rule.frontend/src/routes/routes.json
  48. 16
      io.sc.engine.rule.frontend/src/views/authorization/Authorization.vue
  49. 86
      io.sc.engine.rule.frontend/src/views/dictionary/dictionary.vue
  50. 71
      io.sc.engine.rule.frontend/src/views/lib/IndicatorGrid.vue
  51. 17
      io.sc.engine.rule.frontend/src/views/lib/Lib.vue
  52. 29
      io.sc.engine.rule.frontend/src/views/lib/LibGrid.vue
  53. 440
      io.sc.engine.rule.frontend/src/views/lib/ProcessorGrid.vue
  54. 5
      io.sc.engine.rule.frontend/src/views/lib/TestCase.vue
  55. 24
      io.sc.engine.rule.frontend/src/views/lib/TestCaseParameter.vue
  56. 2
      io.sc.engine.rule.frontend/src/views/lib/ValidatorGrid.vue
  57. 63
      io.sc.engine.rule.frontend/src/views/resources/Resources.vue
  58. 26
      io.sc.engine.rule.frontend/src/views/resources/designer/DesignerDialog.vue
  59. 6
      io.sc.engine.rule.frontend/src/views/resources/designer/GroovyFunctions.ts
  60. 52
      io.sc.engine.rule.frontend/src/views/resources/designer/Model.vue
  61. 30
      io.sc.engine.rule.frontend/src/views/resources/designer/Option.vue
  62. 117
      io.sc.engine.rule.frontend/src/views/resources/designer/Parameter.vue
  63. 55
      io.sc.engine.rule.frontend/src/views/resources/designer/Processor.vue
  64. 29
      io.sc.engine.rule.frontend/src/views/resources/designer/TestCaseParameter.vue
  65. 25
      io.sc.engine.rule.frontend/src/views/resources/designer/Testcase.vue
  66. 30
      io.sc.engine.rule.frontend/src/views/resources/designer/Validator.vue
  67. 111
      io.sc.engine.rule.frontend/src/views/shared/IndicatorManager.ts
  68. 14
      io.sc.engine.rule.frontend/src/views/shared/ResourceDeployStatusTag.vue
  69. 184
      io.sc.engine.rule.frontend/src/views/shared/SelectIndicatorDialog.vue
  70. 73
      io.sc.engine.rule.frontend/src/views/testcase/Testcase.vue
  71. 15
      io.sc.engine.rule.frontend/src/views/workflow/Workflow.vue
  72. 9
      io.sc.engine.rule.sample/src/main/resources/META-INF/platform/plugins/rule-engine-sample-resource.json
  73. 3047
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(元数据).json
  74. 172917
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(模型).json
  75. 9238
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(特征库).json
  76. 4
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages.properties
  77. 4
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages_tw_CN.properties
  78. 4
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages_zh_CN.properties
  79. 2
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/common/initializer/RuleEngineWorkFlowInitializer.java
  80. 34
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/dictionary/controller/UserDefinedJavaClassFieldWebController.java
  81. 7
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/dictionary/service/impl/DictionaryServiceImpl.java
  82. 5
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/dictionary/service/impl/UserDefinedJavaClassFieldServiceImpl.java
  83. 2
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/jpa/listener/handler/LibEntityEventHandler.java
  84. 34
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/controller/IndicatorProcessorWebController.java
  85. 5
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/controller/LibWebController.java
  86. 4
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/entity/IndicatorEntity.java
  87. 2
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/repository/IndicatorRepository.java
  88. 11
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/impl/LibServiceImpl.java
  89. 2
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/controller/ModelWebController.java
  90. 2
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/controller/ParameterWebController.java
  91. 1
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/entity/ParameterProcessorEntity.java
  92. 58
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/entity/processor/MathFormulaParameterProcessorEntity.java
  93. 4
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/ParameterService.java
  94. 1
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/impl/ModelServiceImpl.java
  95. 11
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/impl/ParameterServiceImpl.java
  96. 26
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/vo/processor/MathFormulaParameterProcessorVo.java
  97. 9
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/controller/ResourceWebController.java
  98. 5
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/entity/FolderResourceEntity.java
  99. 7
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/service/impl/ResourceServiceImpl.java
  100. 3
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/vo/ModelResourceVo.java

2
erm.frontend/package.json

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1",
"mockjs": "1.1.0",
"pinia": "2.1.7",
"platform-core": "8.1.245",
"platform-core": "8.1.246",
"quasar": "2.15.3",
"tailwindcss": "3.4.3",
"vue": "3.4.24",

2
gradle.properties

@ -38,7 +38,7 @@ application_version=1.0.0
platform_group=io.sc
platform_version=8.1.44
platform_plugin_version=8.1.44
platform_core_frontend_version=8.1.245
platform_core_frontend_version=8.1.246
###########################################################
# dependencies version

2
io.sc.engine.mv.frontend/package.json

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1",
"mockjs": "1.1.0",
"pinia": "2.1.7",
"platform-core": "8.1.245",
"platform-core": "8.1.246",
"quasar": "2.15.3",
"tailwindcss": "3.4.3",
"vue": "3.4.24",

16
io.sc.engine.rule.client.spring/src/main/resources/META-INF/platform/plugins/messages.json

@ -0,0 +1,16 @@
/*
*
* :
* 使:
* includes:
* excludes:
* : includes excludes , excludes ,
*/
{
"includes":[
"io/sc/engine/rule/client/spring/i18n/parameters"
],
"excludes":[]
}

61
io.sc.engine.rule.client.spring/src/main/resources/META-INF/platform/plugins/parameters.json

@ -0,0 +1,61 @@
/*
*
* :
* 使:
* id:
* parentId: ,
* code: ,
* defaultValue:
* order:
*/
[
//
{"id":"parameter.re.client","order":1010},
///
{
"id" :"parameter.re.client.executorMode",
"parentId" :"parameter.re.client",
"code" :"parameter.re.client.executorMode",
"defaultValue" :"Local",
"order" : 0,
"options" :{
"Local" : "parameter.re.client.executorMode.Local",
"Remote" : "parameter.re.client.executorMode.Remote"
}
},
///
{
"id" :"parameter.re.client.loaderMode",
"parentId" :"parameter.re.client",
"code" :"parameter.re.client.loaderMode",
"defaultValue" :"Local",
"order" : 10,
"options" :{
"Local" : "parameter.re.client.loaderMode.Local",
"Remote" : "parameter.re.client.loaderMode.Remote"
}
},
/// API URL
{
"id" :"parameter.re.client.remoteApiUrl",
"parentId" :"parameter.re.client",
"code" :"parameter.re.client.remoteApiUrl",
"defaultValue" :"http://localhost:8080/api/re/resource",
"order" : 20
},
///
{
"id" :"parameter.re.client.autoCompile",
"parentId" :"parameter.re.client",
"code" :"parameter.re.client.autoCompile",
"defaultValue" :"none",
"order" : 30,
"options" :{
"none" : "parameter.re.client.autoCompile.none", /* */
"deployed" : "parameter.re.client.autoCompile.deployed", /* [] */
"last" : "parameter.re.client.autoCompile.last", /* [] */
"deployed-and-last" : "parameter.re.client.autoCompile.deployed_and_last" /* [] */
}
}
]

17
io.sc.engine.rule.client.spring/src/main/resources/io/sc/engine/rule/client/spring/i18n/parameters.properties

@ -0,0 +1,17 @@
parameter.re.client=Rule Engine(Client)
parameter.re.client.executorMode=Executor Mode
parameter.re.client.executorMode.Local=Local
parameter.re.client.executorMode.Remote=Remote
parameter.re.client.loaderMode=Loader Mode
parameter.re.client.loaderMode.Local=Local
parameter.re.client.loaderMode.Remote=Remote
parameter.re.client.remoteApiUrl=Remote Server API URL
parameter.re.client.autoCompile=Auto Compile Resource Model after System Launched
parameter.re.client.autoCompile.none=None
parameter.re.client.autoCompile.deployed=Deployed
parameter.re.client.autoCompile.last=Last
parameter.re.client.autoCompile.deployed_and_last=Deployed And Last

17
io.sc.engine.rule.client.spring/src/main/resources/io/sc/engine/rule/client/spring/i18n/parameters_zh_CN.properties

@ -0,0 +1,17 @@
parameter.re.client=\u51b3\u7b56\u5f15\u64ce(\u5ba2\u6237\u7aef)
parameter.re.client.executorMode=\u6267\u884c\u5668\u6267\u884c\u6a21\u5f0f
parameter.re.client.executorMode.Local=\u672c\u5730
parameter.re.client.executorMode.Remote=\u8fdc\u7a0b
parameter.re.client.loaderMode=\u8d44\u6e90\u5b9a\u4e49\u52a0\u8f7d\u5668\u6267\u884c\u6a21\u5f0f
parameter.re.client.loaderMode.Local=\u672c\u5730
parameter.re.client.loaderMode.Remote=\u8fdc\u7a0b
parameter.re.client.remoteApiUrl=\u8fdc\u7a0b\u51b3\u7b56\u5f15\u64ce API URL\u5730\u5740
parameter.re.client.autoCompile=\u7cfb\u7edf\u542f\u52a8\u65f6\u81ea\u52a8\u7f16\u8bd1\u6a21\u5f0f
parameter.re.client.autoCompile.none=\u4e0d\u81ea\u52a8\u7f16\u8bd1
parameter.re.client.autoCompile.deployed=\u81ea\u52a8\u7f16\u8bd1[\u5df2\u53d1\u5e03]\u7684\u8d44\u6e90
parameter.re.client.autoCompile.last=\u81ea\u52a8\u7f16\u8bd1[\u6700\u65b0\u7248\u672c]\u7684\u8d44\u6e90
parameter.re.client.autoCompile.deployed_and_last=\u81ea\u52a8\u7f16\u8bd1[\u5df2\u53d1\u5e03\u548c\u6700\u65b0\u7248\u672c]\u7684\u8d44\u6e90

1
io.sc.engine.rule.client/src/main/java/io/sc/engine/rule/client/remote/RemoteLoader.java

@ -4,6 +4,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import io.sc.platform.core.response.ResponseWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.sc.engine.rule.client.Loader;

73
io.sc.engine.rule.client/src/test/java/io/sc/engine/rule/client/test/Test.java

@ -0,0 +1,73 @@
package io.sc.engine.rule.client.test;
import io.sc.engine.rule.client.Executor;
import io.sc.engine.rule.client.ExecutorBuilder;
import io.sc.engine.rule.client.ExecutorFactory;
import io.sc.engine.rule.client.enums.ExecutorMode;
import io.sc.engine.rule.client.enums.LoaderMode;
import io.sc.engine.rule.core.code.impl.support.ParameterResult;
import io.sc.engine.rule.core.code.impl.support.ResourceResult;
import io.sc.engine.rule.core.util.TimeTracer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
private static final String MODEL_API_URL ="http://localhost:8080/api/re/resource"; //远程模型引擎 API URL 地址
private static final String EXECUTOR_NAME ="executor"; //执行器名称
private static final String MODEL_CODE ="M1628257024598"; //需要执行的模型代码
private static final Integer MODEL_VERSION =null; //需要执行的模型版本
private static final int COUNT =1; //需要执行的次数
private static TimeTracer tracer =TimeTracer.getInstance("tracer"); //创建一个时间跟踪器,用于跟踪执行时间,在生产环境中不要这样做
public static void main(String[] args) throws Exception{
init();
testLocalExecutorRemoteLoader_map();
}
public static void init() throws Exception{
//创建执行器(本地执行,远程获取模型定义)
Executor executor =new ExecutorBuilder().build(ExecutorMode.LOCAL, LoaderMode.REMOTE, MODEL_API_URL);
//注册执行器,便于之后获取,如果每次都构建一个新的执行器,将显著影响性能
ExecutorFactory.register(EXECUTOR_NAME, executor);
//第一次执行,消除缓存对性能对比测试的影响
//executor.executeByCode(MODEL_CODE, MODEL_VERSION,JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(prepareData()));
ResourceResult result =executor.executeByCode(MODEL_CODE, MODEL_VERSION,prepareData());
List<ParameterResult> parameters =result.getData();
for(ParameterResult parameter : parameters) {
System.out.println(parameter);
}
//tracer.log("初始化完毕====================================");
}
/**
* 测试本地执行器,远程模型定义加载器,输入参数为 map 对象
* @throws Exception 违例
*/
public static void testLocalExecutorRemoteLoader_map() throws Exception{
//从注册器中获取执行器
Executor executor =ExecutorFactory.getExecutor(EXECUTOR_NAME);
tracer.log("开始执行(采用 map 对象作为参数)====================================");
for(int i=0;i<COUNT;i++) {
//准备执行的数据(输入参数)
Map<String,Object> data =prepareData();
//executor.getLoader().getResourceByCode(MODEL_CODE, MODEL_VERSION);
executor.executeByCode(MODEL_CODE, MODEL_VERSION,data);
}
tracer.log("执行完毕(采用 map 对象作为参数)");
tracer.log("采用 map 对象作为输入参数将执行效率提高 20+ 倍!!!");
}
private static Map<String,Object> prepareData() throws Exception{
Map<String,Object> map =new HashMap<String,Object>();
map.put("P1628257063367", 10);//得分,整数
return map;
}
}

4
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/code/impl/GroovySourceCodeGenerator.java

@ -56,8 +56,8 @@ public class GroovySourceCodeGenerator implements CodeGenerator{
}
private SourceCode _generateSourceCode(ResourceWrapper wrapper) throws Exception{
Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
cfg.setTemplateLoader(new ClassTemplateLoader(GroovySourceCodeGenerator.class,"/org/wsp/engine/rule/core/code/template/groovy"));
Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
cfg.setTemplateLoader(new ClassTemplateLoader(GroovySourceCodeGenerator.class,"/io/sc/engine/rule/core/code/template/groovy"));
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);

1
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/enums/ProcessorType.java

@ -6,6 +6,7 @@ package io.sc.engine.rule.core.enums;
public enum ProcessorType {
EMPTY, //空操作
OPTION_VALUE, //选项值
MATH_FORMULA, //数学公式
ARITHMETIC, //算数运算
TERNARY, //三元操作
WHEN_THEN, //When then 运算

33
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/dictionary/dictionary.ftl

@ -0,0 +1,33 @@
<#assign dictionaries=($wrapper.dictionaries)!>
<#list (dictionaries)! as dictionary>
/**
* 数据字典类
* @author auto generated by engine
*/
@JsonIgnoreProperties(ignoreUnknown=true)
class ${CodeReplacer.className(dictionary.code)}_V${dictionary.version}{
<#list (dictionary.getFields())! as field>
<#if field.defaultValue??>
<#if "java.lang.String"==(field.valueType)!>
String ${CodeReplacer.fieldName(field.code)} ="${field.defaultValue}";//${field.name}
<#else>
${ValueType.getSimpleJavaType(field.valueType)} ${CodeReplacer.fieldName(field.code)} =${field.defaultValue};//${field.name}
</#if>
<#else>
<#if (field.valueTypeIsList)!>
List<${ValueType.getSimpleJavaType(field.valueType)}> ${CodeReplacer.fieldName(field.code)};//${field.name}
<#else>
${ValueType.getSimpleJavaType(field.valueType)} ${CodeReplacer.fieldName(field.code)};//${field.name}
</#if>
</#if>
</#list>
public void init(){
<#list (dictionary.getFields())! as field>
<#if field?? && field.valueCalculation?? && field.valueCalculation!="">
${CodeReplacer.fieldName(field.code)} =(${ExpressionReplacer.groovyWithNoArgumentName(field.valueCalculation,null)});
</#if>
</#list>
}
}
</#list>

99
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/groovy.ftl

@ -0,0 +1,99 @@
<#ftl strip_whitespace=true>
package io.sc.engine.rule.core.code;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.type.TypeReference;
import groovy.transform.Canonical;
import java.math.*;
import java.util.Random;
import java.util.Map;
import io.sc.engine.rule.core.classes.RuleResult;
import io.sc.engine.rule.core.classes.SingleRuleResult;
import io.sc.engine.rule.core.classes.ResourceAbstract;
import io.sc.engine.rule.core.code.impl.support.ResourceResult;
import io.sc.engine.rule.core.code.impl.support.ParameterResult;
import io.sc.engine.rule.core.code.impl.support.FieldValidator;
import io.sc.engine.rule.core.code.impl.support.ValidateResult;
import io.sc.engine.rule.core.enums.ParameterType;
import io.sc.engine.rule.core.enums.RuntimeInputParameterType;
import io.sc.engine.rule.core.util.DateUtil;
import io.sc.engine.rule.core.util.DataTypeConvertor;
import io.sc.engine.rule.core.util.ESql;
import io.sc.engine.rule.core.util.JacksonObjectMapper;
import io.sc.engine.rule.core.util.CodeReplacer;
import io.sc.engine.rule.core.util.Strings;
import io.sc.engine.rule.client.Executor;
import static java.lang.Math.PI;
import static java.lang.Math.E;
import static java.lang.Math.abs;
import static java.lang.Math.acos;
import static java.lang.Math.asin;
import static java.lang.Math.atan;
import static java.lang.Math.atan2;
import static java.lang.Math.cbrt;
import static java.lang.Math.ceil;
import static java.lang.Math.cos;
import static java.lang.Math.cosh;
import static java.lang.Math.exp;
import static java.lang.Math.expm1;
import static java.lang.Math.floor;
import static java.lang.Math.IEEEremainder;
import static java.lang.Math.log;
import static java.lang.Math.pow;
import static java.lang.Math.random;
import static java.lang.Math.rint;
import static java.lang.Math.round;
import static java.lang.Math.sin;
import static java.lang.Math.sinh;
import static java.lang.Math.sqrt;
import static java.lang.Math.tan;
import static java.lang.Math.tanh;
import static java.lang.Math.toDegrees;
import static java.lang.Math.toRadians;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.sc.engine.rule.core.function.JpmmlEvaluator;
import static io.sc.engine.rule.core.function.ArithmeticFunction.randomInt;
import static io.sc.engine.rule.core.function.ArithmeticFunction.max;
import static io.sc.engine.rule.core.function.ArithmeticFunction.min;
import static io.sc.engine.rule.core.function.ArithmeticFunction.sum;
import static io.sc.engine.rule.core.function.ArithmeticFunction.transformSequencing;
import static io.sc.engine.rule.core.function.DateFunction.now;
import static io.sc.engine.rule.core.function.DateFunction.yyyyMMdd;
import static io.sc.engine.rule.core.function.DateFunction.yyyy_MM_dd;
import static io.sc.engine.rule.core.function.StringFunction.join;
import static io.sc.engine.rule.core.function.NormalDistributionFunction.normalDistributioin;
import static io.sc.engine.rule.core.function.NormalDistributionFunction.inverseNormalDistributioin;
import static io.sc.engine.rule.core.util.NumberFormater.decimal;
import static io.sc.engine.rule.core.util.NumberFormater.decimal1;
import static io.sc.engine.rule.core.util.NumberFormater.decimal2;
import static io.sc.engine.rule.core.util.NumberFormater.decimal3;
import static io.sc.engine.rule.core.util.NumberFormater.decimal4;
import static io.sc.engine.rule.core.util.NumberFormater.decimal5;
import static io.sc.engine.rule.core.util.NumberFormater.decimal6;
import static io.sc.engine.rule.core.util.NumberFormater.money;
import static io.sc.engine.rule.core.util.NumberFormater.money2;
import static io.sc.engine.rule.core.util.NumberFormater.rmb;
import static io.sc.engine.rule.core.util.NumberFormater.rmb2;
import static io.sc.engine.rule.core.util.NumberFormater.percent;
import static io.sc.engine.rule.core.util.NumberFormater.percent2;
<#if $wrapper.type=="RESOURCE">
<#include "/resource_groovy.ftl"/>
<#elseif $wrapper.type=="LIB">
<#include "/lib_groovy.ftl"/>
</#if>

111
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/lib/lib.ftl

@ -0,0 +1,111 @@
<#assign libs=($wrapper.libs)!>
<#list (libs)! as lib>
/**
* 库类
* @author auto generated by engine
*/
@JsonIgnoreProperties(ignoreUnknown=true)
class ${CodeReplacer.className(lib.code,lib.version)}{
private static final Logger log =LoggerFactory.getLogger(${CodeReplacer.className(lib.code,lib.version)}.class);
<#list (lib.indicators)! as indicator>
${indicator.forArgumentField($wrapper)}
</#list>
//通过输入参数构建指标库对象
public void convertArgument(Map<String,Object> map){
Object obj =null;
<#list (lib.indicators)! as indicator>
${indicator.forConvertArgumentFromMap($wrapper,"this")}
</#list>
}
public void convertArgument(String json){
${CodeReplacer.className(lib.code)}_V${lib.version} result =JacksonObjectMapper.getDefaultObjectMapper().readValue(json, ${CodeReplacer.className(lib.code,lib.version)}.class);
<#list (lib.indicators)! as indicator>
<#if "INTERFACE"==(indicator.type)!>
this.${CodeReplacer.fieldName(indicator.code)} =result.${CodeReplacer.fieldName(indicator.code)};
<#if ValueType.isBaseType(indicator.valueType)>
<#else>
this.${CodeReplacer.fieldName(indicator.code)}.init();
</#if>
</#if>
</#list>
}
public void execute() throws Exception{
<#-- 处理指标值 -->
<#list (lib.indicators)! as indicator>
<#if "INDICATOR"==(indicator.type)!>
${CodeReplacer.fieldName(indicator.code)}();//${indicator.name},${indicator.type}
</#if>
</#list>
}
public void validate(ValidateResult result) {
<#list (lib.indicators)! as indicator>
<#list (indicator.validators)! as validator>
<#if "EMPTY"==(validator.type)!>
FieldValidator.empty("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "NOT_EMPTY"==(validator.type)!>
FieldValidator.notEmpty("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "TRUE"==(validator.type)!>
FieldValidator.trueValue("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "FALSE"==(validator.type)!>
FieldValidator.falseValue("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "INTEGER_RANGE"==(validator.type)!>
FieldValidator.integerRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>${validator.minValue}<#else>null</#if>,<#if validator.maxValue??>${validator.maxValue}<#else>null</#if>,result);
<#elseif "DECIMAL_RANGE"==(validator.type)!>
FieldValidator.decimalRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>new Double(${validator.minValue})<#else>null</#if>,<#if validator.maxValue??>new Double(${validator.maxValue})<#else>null</#if>,result);
<#elseif "LENGTH_RANGE"==(validator.type)!>
FieldValidator.lengthRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>${validator.minValue}<#else>null</#if>,<#if validator.maxValue??>${validator.maxValue}<#else>null</#if>,result);
<#elseif "DATE_RANGE"==(validator.type)!>
FieldValidator.dateRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>DateUtil.parseDate("${validator.minValue?string("yyyy-MM-dd HH:mm:ss")}")<#else>null</#if>,<#if validator.maxValue??>DateUtil.parseDate("${validator.maxValue?string("yyyy-MM-dd HH:mm:ss")}")<#else>null</#if>,result);
<#elseif "EMAIL"==(validator.type)!>
FieldValidator.mail("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "PATTERN"==(validator.type)!>
FieldValidator.pattern("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},"${validator.pattern}",result);
</#if>
</#list>
</#list>
}
<#list (lib.indicators)! as indicator>
<#if "INDICATOR"==(indicator.type)!>
<#assign parameter=indicator>
public void ${CodeReplacer.fieldName(indicator.code)}(){
${CodeReplacer.className(lib.code)}_V${lib.version} arg =this;
<#list (indicator.processors)! as processor>
if(log.isDebugEnabled()){log.debug(" {}","${parameter.name}(${parameter.type})");}
<#if "OPTION_VALUE"==(processor.type)!>
<#include "/processor/OPTION_VALUE.ftl"/>
<#elseif "ARITHMETIC"==(processor.type)!>
<#include "/processor/ARITHMETIC.ftl"/>
<#elseif "TERNARY"==(processor.type)!>
<#include "/processor/TERNARY.ftl"/>
<#elseif "WHEN_THEN"==(processor.type)!>
<#include "/processor/WHEN_THEN.ftl"/>
<#elseif "NUMBER_RANGE"==(processor.type)!>
<#include "/processor/NUMBER_RANGE.ftl"/>
<#elseif "CONDITION_RANGE"==(processor.type)!>
<#include "/processor/CONDITION_RANGE.ftl"/>
<#elseif "DECISION_TABLE_2C"==(processor.type)!>
<#include "/processor/DECISION_TABLE_2C.ftl"/>
<#elseif "DECISION_TABLE"==(processor.type)!>
<#include "/processor/DECISION_TABLE.ftl"/>
<#elseif "DECISION_TREE"==(processor.type)!>
<#include "/processor/DECISION_TREE.ftl"/>
<#elseif "EXECUTION_FLOW"==(processor.type)!>
<#include "/processor/EXECUTION_FLOW.ftl"/>
<#elseif "PMML"==(processor.type)!>
<#include "/processor/PMML.ftl"/>
<#elseif "GROOVY_SCRIPT"==(processor.type)!>
<#include "/processor/GROOVY_SCRIPT.ftl"/>
<#elseif "SQL"==(processor.type)!>
<#include "/processor/SQL.ftl"/>
</#if>
</#list>
}
</#if>
</#list>
}
</#list>

197
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/lib_groovy.ftl

@ -0,0 +1,197 @@
<#assign lib=$wrapper.lib>
/**
* 指标库类(name:${lib.name}, code:${lib.code}, version:${lib.version})
* ${(lib.description)!}
* @author auto generated by engine
*/
class ${CodeReplacer.className(lib.code,lib.version)}{
private static final Logger log =LoggerFactory.getLogger(${CodeReplacer.className(lib.code,lib.version)}.class);
/**
* 执行方法(Map作为输入参数,该 Map 封装了调用模型的参数)
* @param map 输入参数封装器
* @return 执行结果
*/
public static ResourceResult execute(Map<String,Object> map) throws Exception{
return execute(map["executor"],map["subModelCode"],map["argument"]);
}
<#-- 执行方法(Map作为输入参数) -->
/**
* 执行方法
* @param executor 执行器对象
* @param subModelCode 子模型代码
* @param data 输入参数
* @return 执行结果
*/
public static ResourceResult execute(Executor executor,String subModelCode,Object data) throws Exception{
if(log.isDebugEnabled()){log.debug("开始执行指标库 : ${CodeReplacer.className(lib.code,lib.version)}");}
if(data instanceof Map){
if(log.isDebugEnabled()){log.debug("显示输入参数(Map)=================================================\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(data));}
}else if(data instanceof String){
if(log.isDebugEnabled()){log.debug("显示输入参数(Json字符串)=================================================\n{}",data);}
}
//初始化模型参数
if(log.isDebugEnabled()){log.debug("初始化指标库参数");}
Argument argument =Argument.convertArgument(data);
//输入参数合法性检查(指标库)
ValidateResult validateResult =new ValidateResult();
//输入参数合法性检查(模型)
if(log.isDebugEnabled()){log.debug("开始检查指标库输入参数数据合法性");}
argument.validate(validateResult);
if(validateResult.hasError()){
if(log.isDebugEnabled()){log.debug("\t检查结果: 失败!");}
ResourceResult result =new ResourceResult();
result.setValidateResult(validateResult);
return result;
}
if(log.isDebugEnabled()){log.debug("\t检查结果: 成功!");}
//执行指标库中的所有指标
<#list (lib.indicators)! as indicator>
<#if "INDICATOR"==(indicator.type)!>
${CodeReplacer.methodName(indicator.code)}(executor,argument);//${indicator.name},${indicator.type}
</#if>
</#list>
//返回结果
ResourceResult result =argument.toResult();
if(log.isDebugEnabled()){log.debug("指标库调用成功,返回结果:\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(result));}
return result;
}
<#list (lib.indicators)! as indicator>
<#if "INDICATOR"==(indicator.type)!>
public static void ${CodeReplacer.methodName(indicator.code)}(Executor executor,Argument arg){
<#list (indicator.processors)! as processor>
<#assign parameter=indicator>
if(log.isDebugEnabled()){log.debug(" {}","${parameter.name}(${parameter.type})");}
<#if "OPTION_VALUE"==(processor.type)!>
<#include "/processor/OPTION_VALUE.ftl"/>
<#elseif "ARITHMETIC"==(processor.type)!>
<#include "/processor/ARITHMETIC.ftl"/>
<#elseif "TERNARY"==(processor.type)!>
<#include "/processor/TERNARY.ftl"/>
<#elseif "WHEN_THEN"==(processor.type)!>
<#include "/processor/WHEN_THEN.ftl"/>
<#elseif "NUMBER_RANGE"==(processor.type)!>
<#include "/processor/NUMBER_RANGE.ftl"/>
<#elseif "CONDITION_RANGE"==(processor.type)!>
<#include "/processor/CONDITION_RANGE.ftl"/>
<#elseif "DECISION_TABLE_2C"==(processor.type)!>
<#include "/processor/DECISION_TABLE_2C.ftl"/>
<#elseif "DECISION_TABLE"==(processor.type)!>
<#include "/processor/DECISION_TABLE.ftl"/>
<#elseif "DECISION_TREE"==(processor.type)!>
<#include "/processor/DECISION_TREE.ftl"/>
<#elseif "EXECUTION_FLOW"==(processor.type)!>
<#include "/processor/EXECUTION_FLOW.ftl"/>
<#elseif "PMML"==(processor.type)!>
<#include "/processor/PMML.ftl"/>
<#elseif "GROOVY_SCRIPT"==(processor.type)!>
<#include "/processor/GROOVY_SCRIPT.ftl"/>
<#elseif "SQL"==(processor.type)!>
<#include "/processor/SQL.ftl"/>
</#if>
</#list>
}
</#if>
</#list>
}
/**
* 模型参数类
* @author auto generated by engine
*/
@JsonIgnoreProperties(ignoreUnknown=true)
class Argument{
<#list (lib.indicators)! as indicator>
${indicator.forArgumentField($wrapper)}
</#list>
<#-- 参数转换 -->
public static Argument convertArgument(Map<String,Object> map){
if(map!=null){
Argument argument =new Argument();
Object obj =null;
<#list (lib.indicators)! as indicator>
${indicator.forConvertArgumentFromMap($wrapper,"argument")}
</#list>
return argument;
}
return null;
}
<#-- 参数转换 -->
public static Argument convertArgument(String json){
if(json!=null && !"".equals(json.trim())){
Argument argument =JacksonObjectMapper.getDefaultObjectMapper().readValue(json, Argument.class);
<#list (lib.indicators)! as indicator>
${indicator.forConvertArgumentFromJson($wrapper,"argument")}
</#list>
return argument;
}
return null;
}
public void validate(ValidateResult result) {
<#list (lib.indicators)! as indicator>
<#list (indicator.validators)! as validator>
<#if "EMPTY"==(validator.type)!>
FieldValidator.empty("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "NOT_EMPTY"==(validator.type)!>
FieldValidator.notEmpty("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "TRUE"==(validator.type)!>
FieldValidator.trueValue("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "FALSE"==(validator.type)!>
FieldValidator.falseValue("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "INTEGER_RANGE"==(validator.type)!>
FieldValidator.integerRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>${validator.minValue}<#else>null</#if>,<#if validator.maxValue??>${validator.maxValue}<#else>null</#if>,result);
<#elseif "DECIMAL_RANGE"==(validator.type)!>
FieldValidator.decimalRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>new Double(${validator.minValue})<#else>null</#if>,<#if validator.maxValue??>new Double(${validator.maxValue})<#else>null</#if>,result);
<#elseif "LENGTH_RANGE"==(validator.type)!>
FieldValidator.lengthRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>${validator.minValue}<#else>null</#if>,<#if validator.maxValue??>${validator.maxValue}<#else>null</#if>,result);
<#elseif "DATE_RANGE"==(validator.type)!>
FieldValidator.dateRange("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},<#if validator.minValue??>DateUtil.parseDate("${validator.minValue?string("yyyy-MM-dd HH:mm:ss")}")<#else>null</#if>,<#if validator.maxValue??>DateUtil.parseDate("${validator.maxValue?string("yyyy-MM-dd HH:mm:ss")}")<#else>null</#if>,result);
<#elseif "EMAIL"==(validator.type)!>
FieldValidator.mail("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},result);
<#elseif "PATTERN"==(validator.type)!>
FieldValidator.pattern("${indicator.code}",'''${indicator.name}''',this.${CodeReplacer.fieldName(indicator.code)},"${validator.pattern}",result);
</#if>
</#list>
</#list>
}
public ResourceResult toResult(){
ResourceResult result =new ResourceResult();
<#list (lib.indicators)! as indicator>
<#if "INDICATOR"==(indicator.type)!>
<#if indicator.valueType==ValueType.Decimal.getJavaType()>
result.addParameterResult(new ParameterResult("${indicator.code}","${indicator.name}",ParameterType.${indicator.type},"${indicator.valueType}",${indicator.valueScale!"8"},RoundingMode.${indicator.valueRoundingMode!"HALF_UP"},this.${CodeReplacer.fieldName(indicator.code)}==null?null:${CodeReplacer.fieldName(indicator.code)}.setScale(${indicator.valueScale!"8"},RoundingMode.${indicator.valueRoundingMode!"HALF_UP"}).toString()));
<#elseif
indicator.valueType==ValueType.Boolean.getJavaType()
|| indicator.valueType==ValueType.Long.getJavaType()
|| indicator.valueType==ValueType.String.getJavaType()
|| indicator.valueType==ValueType.Date.getJavaType()
>
result.addParameterResult(new ParameterResult("${indicator.code}","""${indicator.name}""",ParameterType.${indicator.type},"${indicator.valueType}",${indicator.valueScale!"null"},<#if indicator.valueRoundingMode??>RoundingMode.${indicator.valueRoundingMode}<#else>null</#if>,this.${CodeReplacer.fieldName(indicator.code)}==null?null:this.${CodeReplacer.fieldName(indicator.code)}.toString()));
<#else>
result.addParameterResult(new ParameterResult("${indicator.code}","""${indicator.name}""",ParameterType.${indicator.type},"${indicator.valueType}",${indicator.valueScale!"null"},<#if indicator.valueRoundingMode??>RoundingMode.${indicator.valueRoundingMode}<#else>null</#if>,this.${CodeReplacer.fieldName(indicator.code)}==null?null:JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(this.${CodeReplacer.fieldName(indicator.code)})));
</#if>
</#if>
</#list>
return result;
}
}
<#-- 数据字典类 -->
<#include "/dictionary/dictionary.ftl"/>
//执行并返回
${CodeReplacer.className(lib.code)}_V${lib.version}.execute(INPUT_PARAMETER);

153
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/model/argument.ftl

@ -0,0 +1,153 @@
/**
* 模型参数类
* @author auto generated by engine
*/
@JsonIgnoreProperties(ignoreUnknown=true)
class Argument{
<#list (model.getAllParameters())! as parameter>
${parameter.forArgumentField($wrapper)}
</#list>
<#-- 参数转换 -->
public static Argument convertArgument(Map<String,Object> map){
if(map!=null){
Argument argument =new Argument();
Object obj =null;
<#list (model.getAllParameters())! as parameter>
${parameter.forConvertArgumentFromMap($wrapper,"argument")}
</#list>
return argument;
}
return null;
}
<#-- 参数转换 -->
public static Argument convertArgument(String json){
if(json!=null && !"".equals(json.trim())){
Argument argument =JacksonObjectMapper.getDefaultObjectMapper().readValue(json, Argument.class);
<#list (model.getAllParameters())! as parameter>
${parameter.forConvertArgumentFromJson($wrapper,"argument")}
</#list>
return argument;
}
return null;
}
public void validate(ValidateResult result) {
<#list (model.getAllParameters())! as parameter>
<#list (parameter.getValidators())! as validator>
${validator.type!}
<#if "EMPTY"==(validator.type)!>
FieldValidator.empty("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},result);
<#elseif "NOT_EMPTY"==(validator.type)!>
FieldValidator.notEmpty("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},result);
<#elseif "TRUE"==(validator.type)!>
FieldValidator.trueValue("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},result);
<#elseif "FALSE"==(validator.type)!>
FieldValidator.falseValue("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},result);
<#elseif "INTEGER_RANGE"==(validator.type)!>
FieldValidator.integerRange("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},<#if validator.minValue??>${validator.minValue}<#else>null</#if>,<#if validator.maxValue??>${validator.maxValue}<#else>null</#if>,result);
<#elseif "DECIMAL_RANGE"==(validator.type)!>
FieldValidator.decimalRange("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},<#if validator.minValue??>new Double(${validator.minValue})<#else>null</#if>,<#if validator.maxValue??>new Double(${validator.maxValue})<#else>null</#if>,result);
<#elseif "LENGTH_RANGE"==(validator.type)!>
FieldValidator.lengthRange("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},<#if validator.minValue??>${validator.minValue}<#else>null</#if>,<#if validator.maxValue??>${validator.maxValue}<#else>null</#if>,result);
<#elseif "DATE_RANGE"==(validator.type)!>
FieldValidator.dateRange("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},<#if validator.minValue??>DateUtil.parseDate("${validator.minValue?string("yyyy-MM-dd HH:mm:ss")}")<#else>null</#if>,<#if validator.maxValue??>DateUtil.parseDate("${validator.maxValue?string("yyyy-MM-dd HH:mm:ss")}")<#else>null</#if>,result);
<#elseif "EMAIL"==(validator.type)!>
FieldValidator.mail("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},result);
<#elseif "PATTERN"==(validator.type)!>
FieldValidator.pattern("${parameter.code}",'''${parameter.name}''',this.${CodeReplacer.fieldName(parameter.code)},"${validator.pattern}",result);
</#if>
</#list>
</#list>
}
public void mergeParameterValueFromIndicatorLib(Map<String,Object> libs){
<#list (model.getAllParameters())! as parameter>
<#if "INDICATOR"==(parameter.type)!>
<#-- 如果直接给模型参数(类型为指标)设置过非空值,则直接采用设置过的值,否则采用指标库计算结果值 -->
<#if $wrapper.isExecuteTestCase>
if(this.${CodeReplacer.fieldName(parameter.code)}==null){this.${CodeReplacer.fieldName(parameter.code)} =libs.get("${CodeReplacer.varName(parameter.libCode,parameter.libVersion)}").${CodeReplacer.fieldName(parameter.indicatorCode)};}//${parameter.name}
<#else>
this.${CodeReplacer.fieldName(parameter.code)} =libs.get("${CodeReplacer.varName(parameter.libCode,parameter.libVersion)}").${CodeReplacer.fieldName(parameter.indicatorCode)};//${parameter.name}
</#if>
</#if>
</#list>
}
public ResourceResult toResult(){
ResourceResult result =new ResourceResult();
<#list model.getAllParameters() as parameter>
<#if 'OUT'==(parameter.type)! || 'INTERMEDIATE'==(parameter.type)!>
<#if parameter.valueType==ValueType.Decimal.getJavaType()>
result.addParameterResult(new ParameterResult("${parameter.code}","${parameter.name}",ParameterType.${parameter.type},"${parameter.valueType}",${parameter.valueScale!"8"},RoundingMode.${parameter.valueRoundingMode!"HALF_UP"},this.${CodeReplacer.fieldName(parameter.code)}==null?null:${CodeReplacer.fieldName(parameter.code)}.setScale(${parameter.valueScale!"8"},RoundingMode.${parameter.valueRoundingMode!"HALF_UP"}).toString()));
<#elseif
parameter.valueType==ValueType.Boolean.getJavaType()
|| parameter.valueType==ValueType.Long.getJavaType()
|| parameter.valueType==ValueType.String.getJavaType()
|| parameter.valueType==ValueType.Date.getJavaType()
>
result.addParameterResult(new ParameterResult("${parameter.code}","${parameter.name}",ParameterType.${parameter.type},"${parameter.valueType}",null,null,this.${CodeReplacer.fieldName(parameter.code)}==null?null:this.${CodeReplacer.fieldName(parameter.code)}.toString()));
<#else>
result.addParameterResult(new ParameterResult("${parameter.code}","${parameter.name}",ParameterType.${parameter.type},"${parameter.valueType}",null,null,this.${CodeReplacer.fieldName(parameter.code)}==null?null:JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(this.${CodeReplacer.fieldName(parameter.code)})));
</#if>
<#elseif 'INDICATOR'==(parameter.type)!>
<#assign indicator=LibUtil.findIndicator($wrapper.libs,parameter.libCode,parameter.libVersion,parameter.indicatorCode)>
<#if "INDICATOR"==(indicator.type)!>
<#if parameter.valueType==ValueType.Decimal.getJavaType()>
result.addParameterResult(new ParameterResult("${indicator.code}","${indicator.name}",ParameterType.${parameter.type},"${parameter.valueType}",${parameter.valueScale!"8"},RoundingMode.${parameter.valueRoundingMode!"HALF_UP"},this.${CodeReplacer.fieldName(parameter.code)}==null?null:${CodeReplacer.fieldName(parameter.code)}.setScale(${parameter.valueScale!"8"},RoundingMode.${parameter.valueRoundingMode!"HALF_UP"}).toString()));
<#elseif
parameter.valueType==ValueType.Boolean.getJavaType()
|| parameter.valueType==ValueType.Long.getJavaType()
|| parameter.valueType==ValueType.String.getJavaType()
|| parameter.valueType==ValueType.Date.getJavaType()
>
result.addParameterResult(new ParameterResult("${indicator.code}","${indicator.name}",ParameterType.${parameter.type},"${parameter.valueType}",null,null,this.${CodeReplacer.fieldName(parameter.code)}==null?null:this.${CodeReplacer.fieldName(parameter.code)}.toString()));
<#else>
result.addParameterResult(new ParameterResult("${indicator.code}","${indicator.name}",ParameterType.${parameter.type},"${parameter.valueType}",null,null,this.${CodeReplacer.fieldName(parameter.code)}==null?null:JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(this.${CodeReplacer.fieldName(parameter.code)})));
</#if>
</#if>
<#elseif 'RULE_RESULT'==(parameter.type)!>
result.addParameterResult(new ParameterResult("${parameter.code}","${parameter.name}",ParameterType.${parameter.type},this.${CodeReplacer.fieldName(parameter.code)}));
<#elseif 'SINGLE_RULE_RESULT'==(parameter.type)!>
result.addParameterResult(new ParameterResult("${parameter.code}","${parameter.name}",ParameterType.${parameter.type},this.${CodeReplacer.fieldName(parameter.code)}));
</#if>
</#list>
return result;
}
public Map<String,Object> toMap(){
Map<String,Object> map =new HashMap<String,Object>();
<#list model.getAllParameters() as parameter>
map.put("${parameter.code}",this.${CodeReplacer.fieldName(parameter.code)});//${parameter.type}, ${parameter.name}
</#list>
return map;
}
public void mergeResult(ResourceResult result){
if(result!=null){
<#list model.getAllParameters() as parameter>
<#if
parameter.valueType==ValueType.Boolean.getJavaType()
|| parameter.valueType==ValueType.Long.getJavaType()
|| parameter.valueType==ValueType.Decimal.getJavaType()
|| parameter.valueType==ValueType.String.getJavaType()
|| parameter.valueType==ValueType.Date.getJavaType()
>
if(result.exists("${parameter.code}")){
this.${CodeReplacer.fieldName(parameter.code)} =DataTypeConvertor.convert(result.getValueByParameterCode("${parameter.code}"),${ValueType.getSimpleJavaType(parameter.valueType)}.class);
}
<#else>
if(result.exists("${parameter.code}")){
this.${CodeReplacer.fieldName(parameter.code)} =result.getValueByParameterCode("${parameter.code}");
}
</#if>
</#list>
}
}
}

224
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/model/model.ftl

@ -0,0 +1,224 @@
<#assign model=resource.model>
/**
* 资源类(name:${resource.name}, code:${resource.code}, version:${resource.version})
* @author auto generated by engine
*/
class ${CodeReplacer.className(resource.code,resource.version)} {
private static final Logger log =LoggerFactory.getLogger(${CodeReplacer.className(resource.code,resource.version)}.class);
/**
* 执行方法(Map作为输入参数,该 Map 封装了调用模型的参数)
* @param map 输入参数封装器
* @return 执行结果
*/
public static ResourceResult execute(Map<String,Object> map) throws Exception{
return execute(map["executor"],map["subModelCode"],map["argument"]);
}
<#-- 执行方法(Map作为输入参数) -->
/**
* 执行方法
* @param executor 执行器对象
* @param subModelCode 子模型代码
* @param data 输入参数
* @return 执行结果
*/
public static ResourceResult execute(Executor executor,String subModelCode,Object data) throws Exception{
if(log.isDebugEnabled()){log.debug("开始执行模型 : ${CodeReplacer.className(resource.code,resource.version)}");}
if(data instanceof Map){
if(log.isDebugEnabled()){log.debug("显示输入参数(Map)=================================================\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(data));}
}else if(data instanceof String){
if(log.isDebugEnabled()){log.debug("显示输入参数(Json字符串)=================================================\n{}",data);}
}
<#if $wrapper.isExecuteTestCase>
<#else>
<#list ($wrapper.libs)! as lib>
if(log.isDebugEnabled()){log.debug("初始化指标库 : ${lib.name}_V${lib.version}");}
${CodeReplacer.className(lib.code,lib.version)} ${CodeReplacer.varName(lib.code,lib.version)} =new ${CodeReplacer.className(lib.code,lib.version)}();
${CodeReplacer.varName(lib.code,lib.version)}.convertArgument(data);
</#list>
</#if>
//初始化模型参数
if(log.isDebugEnabled()){log.debug("从 {} 初始化模型参数","java.lang.String"==data.class?"Json":"Map");}
Argument argument =Argument.convertArgument(data);
//输入参数合法性检查
ValidateResult validateResult =new ValidateResult();
<#if $wrapper.isExecuteTestCase>
<#else>
//输入参数合法性检查(指标库)
<#list ($wrapper.libs)! as lib>
if(log.isDebugEnabled()){log.debug("开始检查输入参数数据合法性(指标库: ${lib.name}_V${lib.version})");}
${CodeReplacer.varName(lib.code,lib.version)}.validate(validateResult);
if(validateResult.hasError()){
if(log.isDebugEnabled()){log.debug("\t检查结果: 失败!");}
ResourceResult result =new ResourceResult();
result.setValidateResult(validateResult);
return result;
}
if(log.isDebugEnabled()){log.debug("\t检查结果: 成功!");}
</#list>
</#if>
//输入参数合法性检查(模型)
if(log.isDebugEnabled()){log.debug("开始检查模型输入参数数据合法性");}
argument.validate(validateResult);
if(validateResult.hasError()){
if(log.isDebugEnabled()){log.debug("\t检查结果: 失败!");}
ResourceResult result =new ResourceResult();
result.setValidateResult(validateResult);
return result;
}
if(log.isDebugEnabled()){log.debug("\t检查结果: 成功!");}
<#if $wrapper.isExecuteTestCase>
<#else>
//执行指标库
<#list ($wrapper.libs)! as lib>
if(log.isDebugEnabled()){log.debug("开始执行指标库: ${lib.name}_V${lib.version}");}
${CodeReplacer.varName(lib.code,lib.version)}.execute();
</#list>
</#if>
<#if $wrapper.isExecuteTestCase>
<#else>
//合并指标库指标
if(log.isDebugEnabled()){log.debug("开始合并指标库指标");}
Map<String,Object> indicatorLibs =new HashMap<String,Object>();
<#list ($wrapper.libs)! as lib>
indicatorLibs.put("${CodeReplacer.varName(lib.code,lib.version)}",${CodeReplacer.varName(lib.code,lib.version)});
</#list>
argument.mergeParameterValueFromIndicatorLib(indicatorLibs);
if(log.isDebugEnabled()){log.debug("显示合并后输入参数:\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(argument));}
</#if>
//执行模型
if(subModelCode){
subModelCode =CodeReplacer.methodName(subModelCode);
"${r'${subModelCode}'}"(executor,argument);//调用子模型
}else{
${CodeReplacer.methodName(model.code)}(executor,argument);//调用顶级模型(${model.name})
}
//返回结果
ResourceResult result =argument.toResult();
if(log.isDebugEnabled()){log.debug("模型调用成功,返回结果:\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(result));}
return result;
}
//顶级模型(${model.fullName})
private static void ${CodeReplacer.methodName(model.code)}(Executor executor,Argument argument){
if(log.isDebugEnabled()){log.debug("开始调用顶级模型: {}","${model.name}");}
<#if (model.enable)!>
<#else>
if(log.isDebugEnabled()){log.debug("开始调用顶级模型: enable==false");}
return;
</#if>
<#if "DOWN_TOP"==(model.executeMode)!>
<#-- 模型的执行模式为:自下而上,首先执行子模型 -->
<#list (model.children)! as subModel>
${CodeReplacer.methodName(subModel.code)}(executor,argument);//${subModel.name}
</#list>
</#if>
<#-- 处理顶级模型的中间值和结果值 -->
<#list (model.parameters)! as parameter>
<#if "INTERMEDIATE"==(parameter.type)! || "OUT"==(parameter.type)! || "RULE_RESULT"==(parameter.type)! || "SINGLE_RULE_RESULT"==(parameter.type)!>
${CodeReplacer.methodName(parameter.code)}(executor,argument);//${parameter.name},${parameter.type}
</#if>
</#list>
}
<#-- 递归生成所有子模型执行方法 -->
<#list (model.children)! as subModel>
//子模型(${subModel.fullName})
private static void ${CodeReplacer.methodName(subModel.code)}(Executor executor,Argument argument){
if(log.isDebugEnabled()){log.debug("开始调用子模型: {}","${subModel.fullName}");}
<#if (subModel.enable)!>
<#else>
if(log.isDebugEnabled()){log.debug("开始调用子模型: enable==false");}
return;
</#if>
<#if "DOWN_TOP"==(subModel.executeMode)!>
<#-- 子模型的执行模式为:自下而上,首先执行子模型的子模型 -->
<#list (subModel.children)! as _subModel>
${CodeReplacer.methodName(_subModel.code)}(executor,argument);//${_subModel.name}
</#list>
</#if>
<#-- 处理子模型的中间值和结果值 -->
<#list (subModel.getParameters())! as parameter>
<#if "INTERMEDIATE"==(parameter.type)! || "OUT"==(parameter.type)! || "RULE_RESULT"==(parameter.type)! || "SINGLE_RULE_RESULT"==(parameter.type)!>
${CodeReplacer.methodName(parameter.code)}(executor,argument);//${parameter.name},${parameter.type}
</#if>
</#list>
}
<#include "/model/sub-model.ftl"/>
</#list>
<#-- 生成所有参数处理器方法 -->
<#list (model.getAllParameters())! as parameter><#-- 循环将每个参数处理生成一个方法 -->
<#if ("INTERMEDIATE"==(parameter.type)! || "OUT"==(parameter.type)! || "RULE_RESULT"==(parameter.type)! || "SINGLE_RULE_RESULT"==(parameter.type)!)>
//参数处理器, ${parameter.name}(${parameter.type})
private static void ${CodeReplacer.methodName(parameter.code)}(Executor executor,Argument ${ExpressionReplacer.ARGUMENT_NAME}){
if(log.isDebugEnabled()){log.debug(" {}","${parameter.name}(${parameter.type})");}
<#list (parameter.processors)! as processor><#-- 循环将每个处理器转换成 java 语句 -->
<#if (processor.enable)!>
<#if "OPTION_VALUE"==(processor.type)!>
<#include "/processor/OPTION_VALUE.ftl"/>
<#elseif "ARITHMETIC"==(processor.type)!>
<#include "/processor/ARITHMETIC.ftl"/>
<#elseif "TERNARY"==(processor.type)!>
<#include "/processor/TERNARY.ftl"/>
<#elseif "WHEN_THEN"==(processor.type)!>
<#include "/processor/WHEN_THEN.ftl"/>
<#elseif "RULE"==(processor.type)!>
<#include "/processor/RULE.ftl"/>
<#elseif "SINGLE_RULE"==(processor.type)!>
<#include "/processor/SINGLE_RULE.ftl"/>
<#elseif "NUMBER_RANGE"==(processor.type)!>
<#include "/processor/NUMBER_RANGE.ftl"/>
<#elseif "CONDITION_RANGE"==(processor.type)!>
<#include "/processor/CONDITION_RANGE.ftl"/>
<#elseif "DECISION_TABLE_2C"==(processor.type)!>
<#include "/processor/DECISION_TABLE_2C.ftl"/>
<#elseif "DECISION_TABLE"==(processor.type)!>
<#include "/processor/DECISION_TABLE.ftl"/>
<#elseif "DECISION_TREE"==(processor.type)!>
<#include "/processor/DECISION_TREE.ftl"/>
<#elseif "EXECUTION_FLOW"==(processor.type)!>
<#include "/processor/EXECUTION_FLOW.ftl"/>
<#elseif "PMML"==(processor.type)!>
<#include "/processor/PMML.ftl"/>
<#elseif "GROOVY_SCRIPT"==(processor.type)!>
<#include "/processor/GROOVY_SCRIPT.ftl"/>
<#elseif "SQL"==(processor.type)!>
<#include "/processor/SQL.ftl"/>
</#if>
</#if>
</#list>
if(log.isDebugEnabled()){log.debug(" 参数结果值 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}
}
</#if>
</#list>
<#-- 决策树函数 -->
<#include "/processor/DECISION_TREE_FUNCTION.ftl"/>
<#-- 执行流函数 -->
<#include "/processor/EXECUTION_FLOW_FUNCTION.ftl"/>
}
<#-- 参数类 -->
<#include "/model/argument.ftl"/>
<#-- 库类 -->
<#include "/lib/lib.ftl"/>
<#-- 数据字典类 -->
<#include "/dictionary/dictionary.ftl"/>
//执行并返回
${CodeReplacer.className(resource.code)}_V${resource.version}.execute(INPUT_PARAMETER);

25
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/model/sub-model.ftl

@ -0,0 +1,25 @@
<#list (subModel.children)! as subModel>
//子模型(${subModel.fullName})
private static void ${subModel.code}(Executor executor,Argument argument){
if(log.isDebugEnabled()){log.debug("开始调用子模型: {}","${subModel.fullName}");}
<#if (subModel.enable)!>
<#else>
if(log.isDebugEnabled()){log.debug("开始调用子模型: enable==false");}
return;
</#if>
<#if "DOWN_TOP"==(subModel.executeMode)!>
<#-- 子模型的执行模式为:自下而上,首先执行子模型的子模型 -->
<#list (subModel.children)! as _subModel>
${_subModel.code}(executor,argument);//${_subModel.name}
</#list>
</#if>
<#-- 处理子模型的中间值和结果值 -->
<#list (subModel.getParameters())! as parameter>
<#if "INTERMEDIATE"==(parameter.type)! || "OUT"==(parameter.type)! || "RULE_RESULT"==(parameter.type)! || "SINGLE_RULE_RESULT"==(parameter.type)!>
${parameter.code}(executor,argument);//${parameter.name},${parameter.type}
</#if>
</#list>
}
<#include "/model/sub-model.ftl"/>
</#list>

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/ARITHMETIC.ftl

@ -0,0 +1,4 @@
//算数运算
${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)} =${ExpressionReplacer.groovy(processor.arithmetic,parameter.valueType<#-- 算数运算,需要进行相关逻辑处理,即使参数类型为字符串也需要执行算数运算表达式 -->)};//${parameter.type}, ${parameter.name}
if(log.isDebugEnabled()){log.debug(" 算数运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/CONDITION_RANGE.ftl

@ -0,0 +1,4 @@
//条件分段函数
${ConditionRange.generateGroovyCode(parameter,processor)}
if(log.isDebugEnabled()){log.debug(" 条件分段函数运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TABLE.ftl

@ -0,0 +1,4 @@
//决策表
${DecisionTable.generateGroovyCode(parameter,processor)}
if(log.isDebugEnabled()){log.debug(" 决策表运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TABLE_2C.ftl

@ -0,0 +1,4 @@
//简单决策表
${DecisionTable2C.generateGroovyCode(parameter,processor)}
if(log.isDebugEnabled()){log.debug(" 简单决策表运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TREE.ftl

@ -0,0 +1,4 @@
//决策树(此处只是入口,真正的决策树计算逻辑在后面通过一系列方法完成)
${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)} =Tree_${CodeReplacer.fieldName(parameter.code)}_${DecisionTree.parse(processor.decisionTree).id}(executor,${ExpressionReplacer.ARGUMENT_NAME});
if(log.isDebugEnabled()){log.debug(" 决策树运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

13
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/DECISION_TREE_FUNCTION.ftl

@ -0,0 +1,13 @@
/*-------------------------------------------------------------------------------*
* 决策树函数 *
*-------------------------------------------------------------------------------*/
<#list (model.getAllParameters())! as parameter><#-- 循环将每个参数处理生成一个方法 -->
<#if ("INTERMEDIATE"==parameter.type || "OUT"==parameter.type)>
<#list (parameter.processors)! as processor>
<#if "DECISION_TREE"==processor.type>
//${parameter.name}(${parameter.type})
${DecisionTree.generateGroovyCode(parameter,processor)}
</#if>
</#list>
</#if>
</#list>

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/EXECUTION_FLOW.ftl

@ -0,0 +1,4 @@
//执行流(此处只是入口,真正的执行流计算逻辑在后面通过一系列方法完成)
Flow_${CodeReplacer.fieldName(parameter.code)}_${ExecutionFlow.parse(processor.executionFlow).id}(executor,${ExpressionReplacer.ARGUMENT_NAME});
if(log.isDebugEnabled()){log.debug(" 执行流运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

13
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/EXECUTION_FLOW_FUNCTION.ftl

@ -0,0 +1,13 @@
/*-------------------------------------------------------------------------------*
* 执行流函数 *
*-------------------------------------------------------------------------------*/
<#list (model.getAllParameters())! as parameter><#-- 循环将每个参数处理生成一个方法 -->
<#if ("INTERMEDIATE"==parameter.type || "OUT"==parameter.type)>
<#list (parameter.processors)! as processor>
<#if "EXECUTION_FLOW"==processor.type>
//${parameter.name}(${parameter.type})
${ExecutionFlow.generateGroovyCode(parameter,processor)}
</#if>
</#list>
</#if>
</#list>

3
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/GROOVY_SCRIPT.ftl

@ -0,0 +1,3 @@
<#if processor.groovyScript??>
${ExpressionReplacer.groovy(processor.groovyScript,null)}
</#if>

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/NUMBER_RANGE.ftl

@ -0,0 +1,4 @@
//数值分段函数
${NumberRange.generateGroovyCode(parameter,processor)}
if(log.isDebugEnabled()){log.debug(" 数值分段函数运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

34
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/OPTION_VALUE.ftl

@ -0,0 +1,34 @@
//选项值运算
<#assign optionParameter=model.getParameterByOptionParameterCode(processor.optionCode)>
<#if optionParameter??>
if(${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(optionParameter.code)}!=null){
<#list model.getParameterOptionsByOptionParameterCode(processor.optionCode) as option>
<#if option_index==0>
<#if optionParameter.valueType=='java.lang.String'>
if(${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(optionParameter.code)}=="""${option.inputValue}"""){
<#else>
if(${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(optionParameter.code)}==${option.inputValue}){
</#if>
<#else>
<#if optionParameter.valueType=='java.lang.String'>
}else if(${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(optionParameter.code)}=="""${option.inputValue}"""){
<#else>
}else if(${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(optionParameter.code)}==${option.inputValue}){
</#if>
</#if>
<#if parameter.valueType=='java.lang.String'>
${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)} ="""${option.value}""";
if(log.isDebugEnabled()){log.debug(" 选项运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}
<#else>
${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)} =${option.value};
if(log.isDebugEnabled()){log.debug(" 选项运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}
</#if>
</#list>
}else{
if(log.isDebugEnabled()){log.debug(" !!!未匹配到选项列表,选项运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}
}
}else{
if(log.isDebugEnabled()){log.debug(" !!!未提供选项输入值,选项运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}
}
</#if>

3
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/PMML.ftl

@ -0,0 +1,3 @@
<#if processor.pmml??>
arg.${CodeReplacer.fieldName(parameter.code)} =JpmmlEvaluator.evaluate('${parameter.id}_${processor.id}','''${processor.pmml}''',arg.toMap());
</#if>

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/RULE.ftl

@ -0,0 +1,4 @@
//规则运算
${Rule.generateGroovyCode(parameter,processor)}
if(log.isDebugEnabled()){log.debug(" 算数运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/SINGLE_RULE.ftl

@ -0,0 +1,4 @@
//单规则运算
${SingleRule.generateGroovyCode(parameter,processor)}
if(log.isDebugEnabled()){log.debug(" 算数运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

17
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/SQL.ftl

@ -0,0 +1,17 @@
//SQL 运算
<#if processor.sqlDatasourceName??>
javax.sql.DataSource ds =io.sc.engine.rule.client.spring.util.EngineSpringApplicationContextUtil.getDataSource('${processor.sqlDatasourceName}');
<#else>
javax.sql.DataSource ds =io.sc.engine.rule.client.spring.util.EngineSpringApplicationContextUtil.getDefaultDataSource();
</#if>
String sql =${ExpressionReplacer.groovy("\n"+processor.sql,"java.lang.String")};
<#if processor.sql??>
ESql.withInstance(ds){ db->
db.query(sql) { rs ->
if (rs.next()) {
${SqlFieldMapping.generateGroovyCode(parameter,processor)}
}
}
}
</#if>

4
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/TERNARY.ftl

@ -0,0 +1,4 @@
//三元运算
${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)} =(${ExpressionReplacer.groovy(processor.ternaryCondition,null)}) ? (${ExpressionReplacer.groovy(processor.ternaryTrue,parameter.valueType)}) : (${ExpressionReplacer.groovy(processor.ternaryFalse,parameter.valueType)});
if(log.isDebugEnabled()){log.debug(" 三元运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}

12
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/processor/WHEN_THEN.ftl

@ -0,0 +1,12 @@
//WhenThen 运算
if(${ExpressionReplacer.groovy(processor.when,null)}){
${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)} =${ExpressionReplacer.groovy(processor.then,parameter.valueType)};
if(log.isDebugEnabled()){log.debug(" WhenThen 运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}
<#-- 如果是短路操作,直接结束处理 -->
<#if processor.isWhenThenShorted>
if(log.isDebugEnabled()){log.debug(" WhenThen 短路!!!");}
if(log.isDebugEnabled()){log.debug(" 参数结果值 : {}",${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(parameter.code)});}
return;
</#if>
}

11
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/resource_groovy.ftl

@ -0,0 +1,11 @@
<#assign resource=$wrapper.resource>
//外部引入-------------------------------------------------------
<#if resource.imports??>
${resource.imports}
</#if>
<#if resource.type=="MODEL">
<#include "/model/model.ftl"/>
<#elseif resource.type=="SCORE_CARD">
<#include "/scorecard/score_card.ftl"/>
</#if>

89
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/scorecard/argument.ftl

@ -0,0 +1,89 @@
/**********************************************************************************
* 评分卡参数类 *
**********************************************************************************/
@JsonIgnoreProperties(ignoreUnknown=true)
class Argument{
<#list (resource.scoreCardVars)! as scoreCardVar>
<#if 'NUMBER_RANGE'==(scoreCardVar.type)! || 'INDICATOR_NUMBER_RANGE'==(scoreCardVar.type)! || 'INDICATOR_VALUE'==(scoreCardVar.type)!>
BigDecimal ${CodeReplacer.fieldName(scoreCardVar.code)};//${scoreCardVar.name}, ${scoreCardVar.type}
<#elseif 'OPTION'==(scoreCardVar.type)! || 'INDICATOR_OPTION'==(scoreCardVar.type)!>
String ${CodeReplacer.fieldName(scoreCardVar.code)};//${scoreCardVar.name}, ${scoreCardVar.type}
</#if>
</#list>
<#list (resource.scoreCardVars)! as scoreCardVar>
BigDecimal R_${scoreCardVar.code};//${scoreCardVar.name}得分, OUT
</#list>
/* 最终得分 -------------------------------*/
BigDecimal _SCORE_;//最终得分
<#-- 参数转换(Map) -->
public static Argument convertArgument(Map<String,Object> map){
if(map!=null){
Argument argument =new Argument();
Object obj =null;
<#list (resource.scoreCardVars)! as scoreCardVar>
<#if 'NUMBER_RANGE'==(scoreCardVar.type)! || 'INDICATOR_NUMBER_RANGE'==(scoreCardVar.type)! || 'INDICATOR_VALUE'==(scoreCardVar.type)!>
obj =DataTypeConvertor.convert(map.get("${scoreCardVar.code}"),BigDecimal.class);if(obj!=null){argument.${CodeReplacer.fieldName(scoreCardVar.code)} =obj;}//${scoreCardVar.name}
<#elseif 'OPTION'==(scoreCardVar.type)! || 'INDICATOR_OPTION'==(scoreCardVar.type)!>
obj =DataTypeConvertor.convert(map.get("${scoreCardVar.code}"),String.class);if(obj!=null){argument.${CodeReplacer.fieldName(scoreCardVar.code)} =obj;}//${scoreCardVar.name}
</#if>
</#list>
return argument;
}
return null;
}
<#-- 参数转换(json) -->
public static Argument convertArgument(String json){
if(json!=null && !"".equals(json.trim())){
return JacksonObjectMapper.getDefaultObjectMapper().readValue(json, Argument.class);
}
return null;
}
public void validate(ValidateResult result) {
}
public void mergeParameterValueFromIndicatorLib(Map<String,Object> libs){
<#list (resource.scoreCardVars)! as scoreCardVar>
<#if 'INDICATOR_OPTION'==(scoreCardVar.type)! || 'INDICATOR_NUMBER_RANGE'==(scoreCardVar.type)! || 'INDICATOR_VALUE'==(scoreCardVar.type)!>
<#-- 如果直接给模型参数(类型为指标)设置过非空值,则直接采用设置过的值,否则采用指标库计算结果值 -->
<#if $wrapper.isExecuteTestCase>
if(this.${CodeReplacer.fieldName(scoreCardVar.code)}==null){this.${CodeReplacer.fieldName(scoreCardVar.code)} =libs.get("${scoreCardVar.libCode}_${scoreCardVar.libVersion}").${CodeReplacer.fieldName(scoreCardVar.indicatorCode)};}//${scoreCardVar.name}
<#else>
this.${CodeReplacer.fieldName(scoreCardVar.code)} =libs.get("${scoreCardVar.libCode}_${scoreCardVar.libVersion}").${CodeReplacer.fieldName(scoreCardVar.indicatorCode)};//${scoreCardVar.name}
</#if>
</#if>
</#list>
}
public ResourceResult toResult(){
ResourceResult resourceResult =new ResourceResult();
<#list (resource.scoreCardVars)! as scoreCardVar>
resourceResult.addParameterResult(new ParameterResult("R_${scoreCardVar.code}","""${scoreCardVar.name}""",ParameterType.OUT,"java.math.BigDecimal",this.R_${scoreCardVar.code}==null?null:this.R_${scoreCardVar.code}.toString()));
</#list>
resourceResult.addParameterResult(new ParameterResult("_SCORE_","最终得分",ParameterType.OUT,"java.math.BigDecimal",this._SCORE_==null?null:this._SCORE_.toString()));
return resourceResult;
}
public Map<String,Object> toMap(){
Map<String,Object> map =new HashMap<String,Object>();
<#list (resource.scoreCardVars)! as scoreCardVar>
map.put("${scoreCardVar.code}",this.${scoreCardVar.code});
</#list>
<#list (resource.scoreCardVars)! as scoreCardVar>
map.put("R_${scoreCardVar.code}",this.R_${scoreCardVar.code});
</#list>
map.put("_SCORE_",this._SCORE_);
return map;
}
}

147
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/scorecard/score_card.ftl

@ -0,0 +1,147 @@
/**
* 资源类(name:${resource.name}, code:${resource.code}, version:${resource.version})
* ${(resource.description)!}
* @author auto generated by engine
*/
class ${CodeReplacer.className(resource.code)}_V${resource.version}{
private static final Logger log =LoggerFactory.getLogger(${CodeReplacer.className(resource.code)}_V${resource.version}.class);
/**
* 执行方法(Map作为输入参数,该 Map 封装了调用模型的参数)
* @param map 输入参数封装器
* @return 执行结果
*/
public static ResourceResult execute(Map<String,Object> map) throws Exception{
return execute(map["executor"],map["subModelCode"],map["argument"]);
}
<#-- 执行方法(Map作为输入参数) -->
/**
* 执行方法
* @param executor 执行器对象
* @param subModelCode 子模型代码
* @param data 输入参数
* @return 执行结果
*/
public static ResourceResult execute(Executor executor,String subModelCode,Object data) throws Exception{
if(log.isDebugEnabled()){log.debug("开始执行评分卡 : ${resource.name}_${resource.version}");}
if(data instanceof Map){
if(log.isDebugEnabled()){log.debug("显示输入参数(Map)=================================================\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(data));}
}else if(data instanceof String){
if(log.isDebugEnabled()){log.debug("显示输入参数(Json字符串)=================================================\n{}",data);}
}
<#list ($wrapper.libs)! as lib>
//初始化指标库[name:${lib.name}, code:${lib.code}, version:${lib.version}]
if(log.isDebugEnabled()){log.debug("初始化指标库 : ${lib.name}_${lib.version}");}
${CodeReplacer.className(lib.code,lib.version)} ${CodeReplacer.varName(lib.code,lib.version)} =new ${CodeReplacer.className(lib.code,lib.version)}();
${CodeReplacer.varName(lib.code,lib.version)}.convertArgument(data);
</#list>
//初始化评分卡变量
if(log.isDebugEnabled()){log.debug("初始化评分卡变量");}
Argument argument =Argument.convertArgument(data);
//输入参数合法性检查(指标库)
ValidateResult validateResult =new ValidateResult();
<#list ($wrapper.libs)! as lib>
if(log.isDebugEnabled()){log.debug("开始检查输入参数数据合法性(指标库: ${lib.name}_${lib.version})");}
${CodeReplacer.varName(lib.code,lib.version)}.validate(validateResult);
if(validateResult.hasError()){
if(log.isDebugEnabled()){log.debug("\t检查结果: 失败!");}
ResourceResult result =new ResourceResult();
result.setValidateResult(validateResult);
return result;
}
if(log.isDebugEnabled()){log.debug("\t检查结果: 成功!");}
</#list>
//输入参数合法性检查(评分卡)
if(log.isDebugEnabled()){log.debug("开始检查评分卡输入参数数据合法性");}
argument.validate(validateResult);
if(validateResult.hasError()){
if(log.isDebugEnabled()){log.debug("\t检查结果: 失败!");}
ResourceResult result =new ResourceResult();
result.setValidateResult(validateResult);
return result;
}
if(log.isDebugEnabled()){log.debug("\t检查结果: 成功!");}
//执行指标库
<#if $wrapper.isExecuteTestCase>
<#else>
<#list ($wrapper.libs)! as lib>
if(log.isDebugEnabled()){log.debug("开始执行指标库: ${lib.name}_${lib.version}");}
${CodeReplacer.varName(lib.code,lib.version)}.execute();
</#list>
</#if>
//合并指标库指标
if(log.isDebugEnabled()){log.debug("开始合并指标库指标");}
Map<String,Object> indicatorLibs =new HashMap<String,Object>();
<#list ($wrapper.libs)! as lib>
indicatorLibs.put("${lib.code}_${lib.version}",${CodeReplacer.varName(lib.code,lib.version)});
</#list>
argument.mergeParameterValueFromIndicatorLib(indicatorLibs);
if(log.isDebugEnabled()){log.debug("显示合并后输入参数:\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(argument));}
//调用评分卡
${CodeReplacer.fieldName(resource.code)}(executor,argument);//调用评分卡(${resource.name})
//返回结果
ResourceResult result =argument.toResult();
if(log.isDebugEnabled()){log.debug("评分卡调用成功,返回结果:\n{}",JacksonObjectMapper.getDefaultObjectMapper().writeValueAsString(result));}
return result;
}
//${resource.name}
public static void ${CodeReplacer.fieldName(resource.code)}(Executor executor,Argument ${ExpressionReplacer.ARGUMENT_NAME}){
if(log.isDebugEnabled()){log.debug("开始调用评分卡: {}","${resource.name}");}
<#list (resource.scoreCardVars)! as scoreCardVar>
//${scoreCardVar.name}
${CodeReplacer.fieldName(scoreCardVar.code)}(executor,${ExpressionReplacer.ARGUMENT_NAME});
</#list>
//计算最终得分
${ExpressionReplacer.ARGUMENT_NAME}._SCORE_ =0;
<#list (resource.scoreCardVars)! as scoreCardVar>
${ExpressionReplacer.ARGUMENT_NAME}._SCORE_ +=${ExpressionReplacer.ARGUMENT_NAME}.R_${scoreCardVar.code}==null?0:${ExpressionReplacer.ARGUMENT_NAME}.R_${scoreCardVar.code};
</#list>
if(log.isDebugEnabled()){log.debug("评分卡结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}._SCORE_);}
}
<#list (resource.scoreCardVars)! as scoreCardVar>
//计算评分卡变量得分(${scoreCardVar.name})
public static void ${CodeReplacer.fieldName(scoreCardVar.code)}(Executor executor,Argument arg){
<#if "OPTION"==(scoreCardVar.type)! || "INDICATOR_OPTION"==(scoreCardVar.type)!>
//选项
if(log.isDebugEnabled()){log.debug(" {}","${scoreCardVar.name}(OUT)");}
${Option.generateGroovyCode(scoreCardVar)}
if(log.isDebugEnabled()){log.debug(" 选项运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.R_${scoreCardVar.code});}
<#elseif "NUMBER_RANGE"==(scoreCardVar.type)! || "INDICATOR_NUMBER_RANGE"==(scoreCardVar.type)!>
//数值分段函数
if(log.isDebugEnabled()){log.debug(" {}","${scoreCardVar.name}(OUT)");}
${NumberRange.generateGroovyCode(scoreCardVar)}
if(log.isDebugEnabled()){log.debug(" 数值分段函数运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.R_${scoreCardVar.code});}
<#elseif "INDICATOR_VALUE"==(scoreCardVar.type)!>
//指标值
if(log.isDebugEnabled()){log.debug(" {}","${scoreCardVar.name}(OUT)");}
${ExpressionReplacer.ARGUMENT_NAME}.R_${CodeReplacer.fieldName(scoreCardVar.code)} =${ExpressionReplacer.ARGUMENT_NAME}.${CodeReplacer.fieldName(scoreCardVar.code)};
if(log.isDebugEnabled()){log.debug(" 指标值运算结果 : {}",${ExpressionReplacer.ARGUMENT_NAME}.R_${CodeReplacer.fieldName(scoreCardVar.code)});}
</#if>
}
</#list>
}
<#-- 参数类 -->
<#include "/scorecard/argument.ftl"/>
<#-- 库类 -->
<#include "/lib/lib.ftl"/>
<#-- 数据字典类 -->
<#include "/dictionary/dictionary.ftl"/>
//执行并返回
${CodeReplacer.className(resource.code)}_V${resource.version}.execute(INPUT_PARAMETER);

2
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/i18n/enums.properties

@ -48,6 +48,7 @@ io.sc.engine.rule.core.enums.ParameterType.CONSTANT=Constant
#================================================
io.sc.engine.rule.core.enums.ProcessorType.EMPTY=Empty
io.sc.engine.rule.core.enums.ProcessorType.OPTION_VALUE=Option Value
io.sc.engine.rule.core.enums.ProcessorType.MATH_FORMULA=Math Formula
io.sc.engine.rule.core.enums.ProcessorType.ARITHMETIC=Arithmetic
io.sc.engine.rule.core.enums.ProcessorType.TERNARY=Ternary
io.sc.engine.rule.core.enums.ProcessorType.WHEN_THEN=When-Then
@ -88,6 +89,7 @@ io.sc.engine.rule.core.enums.HttpAuthorizationType.BEARER=Bearer Token
# \u53C2\u6570\u5904\u7406\u5668\u7C7B\u578B\u679A\u4E3E
#================================================
io.sc.engine.rule.core.enums.ParameterProcessorType.optionParameterCode=Option Value
io.sc.engine.rule.core.enums.ParameterProcessorType.MATH_FORMULA=Math Formula
io.sc.engine.rule.core.enums.ParameterProcessorType.ARITHMETIC=Arithmetic
io.sc.engine.rule.core.enums.ParameterProcessorType.TERNARY=Ternary
io.sc.engine.rule.core.enums.ParameterProcessorType.WHEN_THEN=When-Then

2
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/i18n/enums_tw_CN.properties

@ -48,6 +48,7 @@ io.sc.engine.rule.core.enums.ParameterType.CONSTANT=\u5E38\u91CF
#================================================
io.sc.engine.rule.core.enums.ProcessorType.EMPTY=\u7A7A
io.sc.engine.rule.core.enums.ProcessorType.OPTION_VALUE=\u9078\u9805\u503C
io.sc.engine.rule.core.enums.ProcessorType.MATH_FORMULA=\u6578\u5B78\u516C\u5F0F
io.sc.engine.rule.core.enums.ProcessorType.ARITHMETIC=\u7B97\u6578\u904B\u7B97
io.sc.engine.rule.core.enums.ProcessorType.TERNARY=\u4E09\u5143\u64CD\u4F5C
io.sc.engine.rule.core.enums.ProcessorType.WHEN_THEN=When Then \u904B\u7B97
@ -88,6 +89,7 @@ io.sc.engine.rule.core.enums.HttpAuthorizationType.BEARER=Bearer Token
# \u53C2\u6570\u5904\u7406\u5668\u7C7B\u578B\u679A\u4E3E
#================================================
io.sc.engine.rule.core.enums.ParameterProcessorType.OPTION_VALUE=\u9078\u9805\u503C
io.sc.engine.rule.core.enums.ParameterProcessorType.MATH_FORMULA=\u6578\u5B78\u516C\u5F0F
io.sc.engine.rule.core.enums.ParameterProcessorType.ARITHMETIC=\u7B97\u6578\u904B\u7B97
io.sc.engine.rule.core.enums.ParameterProcessorType.TERNARY=\u4E09\u5143\u64CD\u4F5C
io.sc.engine.rule.core.enums.ParameterProcessorType.WHEN_THEN=When Then \u904B\u7B97

2
io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/i18n/enums_zh_CN.properties

@ -48,6 +48,7 @@ io.sc.engine.rule.core.enums.ParameterType.CONSTANT=\u5E38\u91CF
#================================================
io.sc.engine.rule.core.enums.ProcessorType.EMPTY=\u7A7A
io.sc.engine.rule.core.enums.ProcessorType.OPTION_VALUE=\u9009\u9879\u503C
io.sc.engine.rule.core.enums.ProcessorType.MATH_FORMULA=\u6570\u5B66\u516C\u5F0F
io.sc.engine.rule.core.enums.ProcessorType.ARITHMETIC=\u7B97\u6570\u8FD0\u7B97
io.sc.engine.rule.core.enums.ProcessorType.TERNARY=\u4E09\u5143\u64CD\u4F5C
io.sc.engine.rule.core.enums.ProcessorType.WHEN_THEN=When Then \u8FD0\u7B97
@ -88,6 +89,7 @@ io.sc.engine.rule.core.enums.HttpAuthorizationType.BEARER=Bearer Token
# \u53C2\u6570\u5904\u7406\u5668\u7C7B\u578B\u679A\u4E3E
#================================================
io.sc.engine.rule.core.enums.ParameterProcessorType.OPTION_VALUE=\u9009\u9879\u503C
io.sc.engine.rule.core.enums.ParameterProcessorType.MATH_FORMULA=\u6570\u5B66\u516C\u5F0F
io.sc.engine.rule.core.enums.ParameterProcessorType.ARITHMETIC=\u7B97\u6570\u8FD0\u7B97
io.sc.engine.rule.core.enums.ParameterProcessorType.TERNARY=\u4E09\u5143\u64CD\u4F5C
io.sc.engine.rule.core.enums.ParameterProcessorType.WHEN_THEN=When Then \u8FD0\u7B97

2
io.sc.engine.rule.frontend/package.json

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1",
"mockjs": "1.1.0",
"pinia": "2.1.7",
"platform-core": "8.1.245",
"platform-core": "8.1.248",
"quasar": "2.15.3",
"tailwindcss": "3.4.3",
"vue": "3.4.24",

2
io.sc.engine.rule.frontend/src/components/index.ts

@ -3,6 +3,7 @@
*/
import component_engine_rule_resources from '@/views/resources/Resources.vue';
import component_engine_rule_designer from '@/views/resources/designer/Designer.vue';
import component_engine_rule_authorization from '@/views/authorization/Authorization.vue';
import component_engine_rule_workflow from '@/views/workflow/Workflow.vue';
import component_engine_rule_dictionary from '@/views/dictionary/Dictionary.vue';
@ -12,6 +13,7 @@ import component_engine_rule_migration from '@/views/migration/Migration.vue';
const localComponents = {
'component.engine.rule.resources': component_engine_rule_resources,
'component.engine.rule.designer': component_engine_rule_designer,
'component.engine.rule.authorization': component_engine_rule_authorization,
'component.engine.rule.workflow': component_engine_rule_workflow,
'component.engine.rule.dictionary': component_engine_rule_dictionary,

36
io.sc.engine.rule.frontend/src/i18n/messages.json

@ -1,20 +1,20 @@
{
"menu.engine.rule":"Rule Engine",
"menu.engine.rule.resources": "Resources Manager",
"menu.engine.rule.resources": "Model Manager",
"menu.engine.rule.authorization": "Authorization Manager",
"menu.engine.rule.workflow": "Workflow",
"menu.engine.rule.dictionary": "Meta Data Manager",
"menu.engine.rule.lib": "Feature Library Manager",
"menu.engine.rule.testcase": "Test Case Manager",
"menu.engine.rule.migration": "Migration",
"menu.engine.rule.migration": "Data Back and Migration",
"re.resources.grid.title": "Resources",
"re.resources.grid.title": "Model",
"re.resources.grid.toolbar.addTop": "Top Folder",
"re.resources.grid.toolbar.addChild": "Child Folder",
"re.resources.grid.toolbar.addModel": "Model",
"re.resources.grid.toolbar.addScoreCard": "Score Card",
"re.resources.grid.toolbar.deepClone.tip": "Are you sure to deep clone the resource?",
"re.resources.grid.toolbar.deepCloneNew": "Deep Clone(New Resource)",
"re.resources.grid.toolbar.deepCloneNew": "Deep Clone(new)",
"re.resources.grid.toolbar.deepCloneNew.tip": "Are you sure to deep clone the resource as new resource?",
"re.resources.grid.toolbar.design": "View/Design",
"re.resources.grid.toolbar.deploy.online":"Online",
@ -33,10 +33,11 @@
"re.resources.dialog.attachment.grid.entity.file": "Please select a file",
"re.resources.designer.dialog.title": "Model Designer - {name} ({status},V{version})",
"re.resources.designer.model.grid.title": "Model Tree",
"re.resources.designer.model.grid.title": "Model Structure",
"re.resources.designer.model.grid.toolbar.addChild": "Add Child Model",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode": "Generate Groovy Source Code",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode4TestCase": "Generate Groovy Source Code(Test Case)",
"re.resources.designer.model.grid.toolbar.deepClone.tip": "Are you sure to deep clone the model?",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode": "Generate Script Code",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode4TestCase": "Generate Script Code(Test Case)",
"re.resources.designer.model.grid.entity.executeMode": "Execute Mode",
"re.resources.designer.parameter.tab.title": "Parameter",
@ -56,6 +57,7 @@
"re.resources.designer.parameter.grid.toolbar.add.ruleResult": "Rule Output",
"re.resources.designer.parameter.grid.toolbar.add.singleRuleResult": "Single Rule Output",
"re.resources.designer.parameter.grid.toolbar.add.importPmml": "Import PMML",
"re.resources.designer.parameter.grid.toolbar.deepClone.tip": "Are you sure to deep clone the parameter?",
"re.resources.designer.parameter.grid.entity.valueType": "Value Type",
"re.resources.designer.parameter.grid.entity.valueTypeVersion": "Value Type Version",
"re.resources.designer.parameter.grid.entity.valueScale": "Value Scale",
@ -91,7 +93,7 @@
"re.resources.designer.processor.grid.entity.pmml": "PMML",
"re.resources.designer.processor.grid.entity.decisionTable2C": "Simple Decision Table",
"re.resources.designer.processor.grid.entity.decisionTable": "Decision Table",
"re.resources.designer.processor.grid.entity.groovyScript": "Groovy Script",
"re.resources.designer.processor.grid.entity.groovyScript": "Script",
"re.resources.designer.processor.grid.entity.sqlDatasourceName": "Datasource Name",
"re.resources.designer.processor.grid.entity.sql": "SQL",
"re.resources.designer.processor.grid.entity.sqlParameterValues": "Parameter Values",
@ -102,11 +104,14 @@
"re.resources.designer.processor.dialog.decisionTree.title": "Decision Tree Designer",
"re.resources.designer.processor.dialog.executionFlow.title": "Execution Flow Designer",
"re.resources.designer.testCase.grid.title": "Test Case List",
"re.resources.designer.testCase.grid.title": "Test Cases",
"re.resources.designer.testCase.grid.entity.testResult": "Result",
"re.resources.designer.testCase.grid.entity.lastTestDate": "Test Date",
"re.resources.designer.testCase.grid.entity.ownerCode": "Resource Code",
"re.resources.designer.testCase.grid.entity.ownerName": "Resource Name",
"re.resources.designer.testCase.grid.entity.ownerVersion": "Resource Version",
"re.resources.designer.testCaseParameter.grid.title": "Test Case Parameter List",
"re.resources.designer.testCaseParameter.grid.title": "Parameter List",
"re.resources.designer.testCaseParameter.grid.entity.inputValue": "Input Value",
"re.resources.designer.testCaseParameter.grid.entity.expectValue": "Expect Value",
"re.resources.designer.testCaseParameter.grid.entity.resultValue": "Result Value",
@ -120,7 +125,7 @@
"re.resources.importSample.grid.toolbar.import": "Import Sample",
"re.resources.importSample.grid.toolbar.import.tip": "Are you sure to import the samples?",
"re.dictionary.grid.title": "Meta Data Tree",
"re.dictionary.grid.title": "Meta Data",
"re.dictionary.grid.toolbar.addGroup": "Add New",
"re.dictionary.grid.toolbar.addTop": "Top Folder",
"re.dictionary.grid.toolbar.addChild": "Child Folder",
@ -130,7 +135,7 @@
"re.dictionary.grid.toolbar.cloneGroup": "Clone",
"re.dictionary.grid.toolbar.deepClone": "Deep Clone",
"re.dictionary.grid.toolbar.deepClone.tip": "Are you sure to deep clone the meta data?",
"re.dictionary.grid.toolbar.deepCloneNew": "Deep Clone (New Meta Data)",
"re.dictionary.grid.toolbar.deepCloneNew": "Deep Clone (new)",
"re.dictionary.grid.toolbar.deepCloneNew.tip": "Are you sure to deep clone the meta data as a new meta data?",
"re.dictionary.grid.toolbar.generateJson": "Generate JSON",
"re.dictionary.grid.toolbar.deploy": "Deploy",
@ -165,9 +170,9 @@
"re.lib.grid.toolbar.cloneGroup": "Clone",
"re.lib.grid.toolbar.deepClone": "Deep Clone",
"re.lib.grid.toolbar.deepClone.tip": "Are you sure to clone the Feature Library?",
"re.lib.grid.toolbar.deepCloneNew": "Deep Clone (New Feature Library)",
"re.lib.grid.toolbar.deepCloneNew": "Deep Clone (new)",
"re.lib.grid.toolbar.deepCloneNew.tip": "Are you sure to clone the feature library as a new feature library?",
"re.lib.grid.toolbar.generateGroovy": "Generate Groovy Code",
"re.lib.grid.toolbar.generateGroovy": "Generate Script Code",
"re.lib.grid.toolbar.deploy": "Deploy",
"re.lib.grid.toolbar.deploy.tip": "Are you sure to deploy the Feature Library?",
"re.lib.grid.toolbar.importGroup": "Import",
@ -177,6 +182,9 @@
"re.lib.tab.indicator.title": "Feature",
"re.lib.tab.testcase.title": "Test Case",
"re.indicator.grid.toolbar.addInterface": "Interface",
"re.indicator.grid.toolbar.addIndicator": "Indicator",
"re.migration.import.title":"Import ( From The File Uploaded )",
"re.migration.import.subTitle":"",
"re.migration.import.action":"Import",

50
io.sc.engine.rule.frontend/src/i18n/messages_tw_CN.json

@ -1,20 +1,20 @@
{
"menu.engine.rule":"規則引擎",
"menu.engine.rule.resources": "資源管理",
"menu.engine.rule.resources": "模型管理",
"menu.engine.rule.authorization": "權限管理",
"menu.engine.rule.workflow": "流程審批",
"menu.engine.rule.dictionary": "元數據管理",
"menu.engine.rule.lib": "特征庫管理",
"menu.engine.rule.testcase": "試用例",
"menu.engine.rule.migration": "數據遷移",
"menu.engine.rule.testcase": "試用例",
"menu.engine.rule.migration": "數據備份和遷移",
"re.resources.grid.title": "資源樹",
"re.resources.grid.title": "模型",
"re.resources.grid.toolbar.addTop": "頂級文件夾",
"re.resources.grid.toolbar.addChild": "子文件夾",
"re.resources.grid.toolbar.addModel": "模型",
"re.resources.grid.toolbar.addScoreCard": "評分卡",
"re.resources.grid.toolbar.deepClone.tip": "您確定要深度複製資源嗎?",
"re.resources.grid.toolbar.deepCloneNew": "深度複製(新資源)",
"re.resources.grid.toolbar.deepCloneNew": "深度複製(新)",
"re.resources.grid.toolbar.deepCloneNew.tip": "您確定要深度複製資源成一個新的資源嗎?",
"re.resources.grid.toolbar.design": "查看/設計",
"re.resources.grid.toolbar.deploy.online":"上線",
@ -33,16 +33,17 @@
"re.resources.dialog.attachment.grid.entity.file": "請選擇一個文件",
"re.resources.designer.dialog.title": "模型設計 - {name} ({status},V{version})",
"re.resources.designer.model.grid.title": "模型結構",
"re.resources.designer.model.grid.title": "模型結構",
"re.resources.designer.model.grid.toolbar.addChild": "添加子模型",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode": "生成 Groovy 代碼",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode4TestCase": "生成 Groovy 代碼(測試用例)",
"re.resources.designer.model.grid.toolbar.deepClone.tip": "您確定要深度複製模型嗎?",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode": "生成腳本代碼",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode4TestCase": "生成腳本代碼(測試用例)",
"re.resources.designer.model.grid.entity.executeMode": "執行模式",
"re.resources.designer.parameter.tab.title": "參數",
"re.resources.designer.testcase.tab.title": "測試用例",
"re.resources.designer.validator.tab.title": "驗證器",
"re.resources.designer.processor.tab.title": "處理",
"re.resources.designer.processor.tab.title": "處理邏輯",
"re.resources.designer.option.tab.title": "選項",
"re.resources.designer.parameter.grid.title": "參數列表",
@ -56,6 +57,7 @@
"re.resources.designer.parameter.grid.toolbar.add.ruleResult": "規則結果值",
"re.resources.designer.parameter.grid.toolbar.add.singleRuleResult": "單規則結果值",
"re.resources.designer.parameter.grid.toolbar.add.importPmml": "導入 PMML",
"re.resources.designer.parameter.grid.toolbar.deepClone.tip": "您確定要深度複製參數嗎?",
"re.resources.designer.parameter.grid.entity.valueType": "值類型",
"re.resources.designer.parameter.grid.entity.valueTypeVersion": "值類型版本",
"re.resources.designer.parameter.grid.entity.valueScale": "值精度",
@ -74,7 +76,7 @@
"re.resources.designer.option.grid.entity.value": "計算值",
"re.resources.designer.option.grid.entity.title": "顯示文本",
"re.resources.designer.processor.grid.title": "處理",
"re.resources.designer.processor.grid.title": "處理邏輯",
"re.resources.designer.processor.grid.entity.content": "內容",
"re.resources.designer.processor.grid.entity.optionCode": "選項",
"re.resources.designer.processor.grid.entity.arithmetic": "算數表達式",
@ -83,7 +85,7 @@
"re.resources.designer.processor.grid.entity.ternaryFalse": "條件不滿足時",
"re.resources.designer.processor.grid.entity.when": "When 表達式",
"re.resources.designer.processor.grid.entity.then": "Then 表達式",
"re.resources.designer.processor.grid.entity.isWhenThenShorted": "短路操作",
"re.resources.designer.processor.grid.entity.isWhenThenShorted": "跳過後續操作",
"re.resources.designer.processor.grid.entity.numberRangeVar": "數值分段表達式",
"re.resources.designer.processor.grid.entity.numberRange": "數值分段",
"re.resources.designer.processor.grid.entity.conditionRangeVar": "條件分段",
@ -102,16 +104,19 @@
"re.resources.designer.processor.dialog.decisionTree.title": "決策樹設計器",
"re.resources.designer.processor.dialog.executionFlow.title": "執行流設計器",
"re.resources.designer.testCase.grid.title": "試用例列表",
"re.resources.designer.testCase.grid.entity.testResult": "測試結果",
"re.resources.designer.testCase.grid.title": "試用例",
"re.resources.designer.testCase.grid.entity.testResult": "結果",
"re.resources.designer.testCase.grid.entity.lastTestDate": "測試日期",
"re.resources.designer.testCase.grid.entity.ownerCode": "資源代碼",
"re.resources.designer.testCase.grid.entity.ownerName": "資源名稱",
"re.resources.designer.testCase.grid.entity.ownerVersion": "資源版本",
"re.resources.designer.testCaseParameter.grid.title": "測試用例參數列表",
"re.resources.designer.testCaseParameter.grid.title": "參數列表",
"re.resources.designer.testCaseParameter.grid.entity.inputValue": "輸入值",
"re.resources.designer.testCaseParameter.grid.entity.expectValue": "期望值",
"re.resources.designer.testCaseParameter.grid.entity.resultValue": "結果值",
"re.resources.designer.testCaseParameter.grid.entity.skipCheck": "跳過檢查",
"re.resources.designer.testCaseParameter.grid.entity.testResult": "測試結果",
"re.resources.designer.testCaseParameter.grid.entity.testResult": "結果",
"re.resources.import.dialog.title": "導入資源",
@ -120,7 +125,7 @@
"re.resources.importSample.grid.toolbar.import": "導入示例",
"re.resources.importSample.grid.toolbar.import.tip": "您確定要導入示例資源嗎?",
"re.dictionary.grid.title": "元數據",
"re.dictionary.grid.title": "元數據",
"re.dictionary.grid.toolbar.addGroup": "新增",
"re.dictionary.grid.toolbar.addTop": "頂級文件夾",
"re.dictionary.grid.toolbar.addChild": "子文件夾",
@ -130,7 +135,7 @@
"re.dictionary.grid.toolbar.cloneGroup": "複製",
"re.dictionary.grid.toolbar.deepClone": "深度複製",
"re.dictionary.grid.toolbar.deepClone.tip": "您確定要深度複製元數據嗎?",
"re.dictionary.grid.toolbar.deepCloneNew": "深度復製(新元數據)",
"re.dictionary.grid.toolbar.deepCloneNew": "深度復製(新)",
"re.dictionary.grid.toolbar.deepCloneNew.tip": "您確定要深度複製元數據成一個新的元數據嗎?",
"re.dictionary.grid.toolbar.generateJson": "生成示例 JSON",
"re.dictionary.grid.toolbar.deploy": "發佈",
@ -141,7 +146,7 @@
"re.dictionary.grid.entity.javaClassName": "Java 類全路徑名稱",
"re.dictionary.field.grid.title": "字段列表",
"re.dictionary.field.grid.title": "字段",
"re.dictionary.field.grid.entity.valueType": "值類型",
"re.dictionary.field.grid.entity.valueTypeIsList": "是否列表",
"re.dictionary.field.grid.entity.valueCalculation": "值計算公式",
@ -157,7 +162,7 @@
"re.dictionary.importSample.grid.toolbar.import": "導入示例",
"re.dictionary.importSample.grid.toolbar.import.tip": "您確定要導入示例元數據嗎?",
"re.lib.grid.title": "特征庫",
"re.lib.grid.title": "特征庫",
"re.lib.grid.toolbar.addGroup": "新增",
"re.lib.grid.toolbar.addTop": "頂級文件夾",
"re.lib.grid.toolbar.addChild": "子文件夾",
@ -165,9 +170,9 @@
"re.lib.grid.toolbar.cloneGroup": "複製",
"re.lib.grid.toolbar.deepClone": "深度複製",
"re.lib.grid.toolbar.deepClone.tip": "您確定要深度複製特征庫嗎?",
"re.lib.grid.toolbar.deepCloneNew": "深度複製(新特征庫)",
"re.lib.grid.toolbar.deepCloneNew": "深度複製(新)",
"re.lib.grid.toolbar.deepCloneNew.tip": "您確定要深度複製特征庫成一個新的特征庫嗎?",
"re.lib.grid.toolbar.generateGroovy": "生成 Groovy 源代碼",
"re.lib.grid.toolbar.generateGroovy": "生成腳本源代碼",
"re.lib.grid.toolbar.deploy": "發佈",
"re.lib.grid.toolbar.deploy.tip": "您確定要發佈特征庫嗎?",
"re.lib.grid.toolbar.importGroup": "導入",
@ -177,6 +182,9 @@
"re.lib.tab.indicator.title": "特征",
"re.lib.tab.testcase.title": "測試用例",
"re.indicator.grid.toolbar.addInterface": "接口",
"re.indicator.grid.toolbar.addIndicator": "指標",
"re.migration.import.title":"導入數據 (通過上傳文件導入)",
"re.migration.import.subTitle":"",
"re.migration.import.action":"導入數據",

50
io.sc.engine.rule.frontend/src/i18n/messages_zh_CN.json

@ -1,20 +1,20 @@
{
"menu.engine.rule":"规则引擎",
"menu.engine.rule.resources": "资源管理",
"menu.engine.rule.resources": "模型管理",
"menu.engine.rule.authorization": "权限管理",
"menu.engine.rule.workflow": "流程审批",
"menu.engine.rule.dictionary": "元数据管理",
"menu.engine.rule.lib": "特征库管理",
"menu.engine.rule.testcase": "试用例管理",
"menu.engine.rule.migration": "数据迁移",
"menu.engine.rule.testcase": "试用例管理",
"menu.engine.rule.migration": "数据备份和迁移",
"re.resources.grid.title": "资源树",
"re.resources.grid.title": "模型",
"re.resources.grid.toolbar.addTop": "顶级文件夹",
"re.resources.grid.toolbar.addChild": "子文件夹",
"re.resources.grid.toolbar.addModel": "模型",
"re.resources.grid.toolbar.addScoreCard": "评分卡",
"re.resources.grid.toolbar.deepClone.tip": "您确定要深度复制资源吗?",
"re.resources.grid.toolbar.deepCloneNew": "深度复制(新资源)",
"re.resources.grid.toolbar.deepCloneNew": "深度复制(新)",
"re.resources.grid.toolbar.deepCloneNew.tip": "您确定要深度复制资源成一个新的资源吗?",
"re.resources.grid.toolbar.design": "查看/设计",
"re.resources.grid.toolbar.deploy.online":"上线",
@ -33,16 +33,17 @@
"re.resources.dialog.attachment.grid.entity.file": "请选择一个文件",
"re.resources.designer.dialog.title": "模型设计 - {name} ({status},V{version})",
"re.resources.designer.model.grid.title": "模型结构",
"re.resources.designer.model.grid.title": "模型结构",
"re.resources.designer.model.grid.toolbar.addChild": "添加子模型",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode": "生成 Groovy 代码",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode4TestCase": "生成 Groovy 代码(测试用例)",
"re.resources.designer.model.grid.toolbar.deepClone.tip": "您确定要深度复制模型吗?",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode": "生成脚本代码",
"re.resources.designer.model.grid.toolbar.generateGroovySourceCode4TestCase": "生成脚本代码(测试用例)",
"re.resources.designer.model.grid.entity.executeMode": "执行模式",
"re.resources.designer.parameter.tab.title": "参数",
"re.resources.designer.testcase.tab.title": "测试用例",
"re.resources.designer.validator.tab.title": "验证器",
"re.resources.designer.processor.tab.title": "处理",
"re.resources.designer.processor.tab.title": "处理逻辑",
"re.resources.designer.option.tab.title": "选项",
"re.resources.designer.parameter.grid.title": "参数列表",
@ -56,6 +57,7 @@
"re.resources.designer.parameter.grid.toolbar.add.ruleResult": "规则结果值",
"re.resources.designer.parameter.grid.toolbar.add.singleRuleResult": "单规则结果值",
"re.resources.designer.parameter.grid.toolbar.add.importPmml": "导入 PMML",
"re.resources.designer.parameter.grid.toolbar.deepClone.tip": "您确定要深度复制参数吗?",
"re.resources.designer.parameter.grid.entity.valueType": "值类型",
"re.resources.designer.parameter.grid.entity.valueTypeVersion": "值类型版本",
"re.resources.designer.parameter.grid.entity.valueScale": "值精度",
@ -74,7 +76,7 @@
"re.resources.designer.option.grid.entity.value": "计算值",
"re.resources.designer.option.grid.entity.title": "显示文本",
"re.resources.designer.processor.grid.title": "处理",
"re.resources.designer.processor.grid.title": "处理逻辑",
"re.resources.designer.processor.grid.entity.content": "内容",
"re.resources.designer.processor.grid.entity.optionCode": "选项",
"re.resources.designer.processor.grid.entity.arithmetic": "算数表达式",
@ -83,7 +85,7 @@
"re.resources.designer.processor.grid.entity.ternaryFalse": "条件不满足时",
"re.resources.designer.processor.grid.entity.when": "When 表达式",
"re.resources.designer.processor.grid.entity.then": "Then 表达式",
"re.resources.designer.processor.grid.entity.isWhenThenShorted": "短路操作",
"re.resources.designer.processor.grid.entity.isWhenThenShorted": "跳过后续操作",
"re.resources.designer.processor.grid.entity.numberRangeVar": "数值分段表达式",
"re.resources.designer.processor.grid.entity.numberRange": "数值分段",
"re.resources.designer.processor.grid.entity.conditionRangeVar": "条件分段",
@ -102,16 +104,19 @@
"re.resources.designer.processor.dialog.decisionTree.title": "决策树设计器",
"re.resources.designer.processor.dialog.executionFlow.title": "执行流设计器",
"re.resources.designer.testCase.grid.title": "试用例列表",
"re.resources.designer.testCase.grid.entity.testResult": "测试结果",
"re.resources.designer.testCase.grid.title": "试用例",
"re.resources.designer.testCase.grid.entity.testResult": "结果",
"re.resources.designer.testCase.grid.entity.lastTestDate": "测试日期",
"re.resources.designer.testCase.grid.entity.ownerCode": "资源代码",
"re.resources.designer.testCase.grid.entity.ownerName": "资源名称",
"re.resources.designer.testCase.grid.entity.ownerVersion": "资源版本",
"re.resources.designer.testCaseParameter.grid.title": "测试用例参数列表",
"re.resources.designer.testCaseParameter.grid.title": "参数列表",
"re.resources.designer.testCaseParameter.grid.entity.inputValue": "输入值",
"re.resources.designer.testCaseParameter.grid.entity.expectValue": "期望值",
"re.resources.designer.testCaseParameter.grid.entity.resultValue": "结果值",
"re.resources.designer.testCaseParameter.grid.entity.skipCheck": "跳过检查",
"re.resources.designer.testCaseParameter.grid.entity.testResult": "测试结果",
"re.resources.designer.testCaseParameter.grid.entity.testResult": "结果",
"re.resources.import.dialog.title": "导入资源",
@ -120,7 +125,7 @@
"re.resources.importSample.grid.toolbar.import": "导入示例",
"re.resources.importSample.grid.toolbar.import.tip": "您确定要导入示例资源吗?",
"re.dictionary.grid.title": "元数据",
"re.dictionary.grid.title": "元数据",
"re.dictionary.grid.toolbar.addGroup": "新增",
"re.dictionary.grid.toolbar.addTop": "顶级文件夹",
"re.dictionary.grid.toolbar.addChild": "子文件夹",
@ -130,7 +135,7 @@
"re.dictionary.grid.toolbar.cloneGroup": "复制",
"re.dictionary.grid.toolbar.deepClone": "深度复制",
"re.dictionary.grid.toolbar.deepClone.tip": "您确定要深度复制元数据吗?",
"re.dictionary.grid.toolbar.deepCloneNew": "深度复制(新元數據)",
"re.dictionary.grid.toolbar.deepCloneNew": "深度复制(新)",
"re.dictionary.grid.toolbar.deepCloneNew.tip": "您确定要深度复制元数据成一个新的元数据吗?",
"re.dictionary.grid.toolbar.generateJson": "生成示例 JSON",
"re.dictionary.grid.toolbar.deploy": "发布",
@ -141,7 +146,7 @@
"re.dictionary.grid.entity.javaClassName": "Java 类全路径名称",
"re.dictionary.field.grid.title": "字段列表",
"re.dictionary.field.grid.title": "字段",
"re.dictionary.field.grid.entity.valueType": "值类型",
"re.dictionary.field.grid.entity.valueTypeIsList": "是否列表",
"re.dictionary.field.grid.entity.valueCalculation": "值计算公式",
@ -157,7 +162,7 @@
"re.dictionary.importSample.grid.toolbar.import": "导入示例",
"re.dictionary.importSample.grid.toolbar.import.tip": "您确定要导入示例元数据吗?",
"re.lib.grid.title": "特征库",
"re.lib.grid.title": "特征库",
"re.lib.grid.toolbar.addGroup": "新增",
"re.lib.grid.toolbar.addTop": "顶级文件夹",
"re.lib.grid.toolbar.addChild": "子文件夹",
@ -165,9 +170,9 @@
"re.lib.grid.toolbar.cloneGroup": "复制",
"re.lib.grid.toolbar.deepClone": "深度复制",
"re.lib.grid.toolbar.deepClone.tip": "您确定要深度复制特征库吗?",
"re.lib.grid.toolbar.deepCloneNew": "深度复制(新特征库)",
"re.lib.grid.toolbar.deepCloneNew": "深度复制(新)",
"re.lib.grid.toolbar.deepCloneNew.tip": "您确定要深度复制特征库成一个新的特征库吗?",
"re.lib.grid.toolbar.generateGroovy": "生成 Groovy 源代码",
"re.lib.grid.toolbar.generateGroovy": "生成脚本源代码",
"re.lib.grid.toolbar.deploy": "发布",
"re.lib.grid.toolbar.deploy.tip": "您确定要发布特征库吗?",
"re.lib.grid.toolbar.importGroup": "导入",
@ -177,6 +182,9 @@
"re.lib.tab.indicator.title": "特征",
"re.lib.tab.testcase.title": "测试用例",
"re.indicator.grid.toolbar.addInterface": "接口",
"re.indicator.grid.toolbar.addIndicator": "指标",
"re.migration.import.title":"导入数据 (通过上传文件导入)",
"re.migration.import.subTitle":"",
"re.migration.import.action":"导入数据",

16
io.sc.engine.rule.frontend/src/routes/routes.json

@ -14,6 +14,22 @@
]
}
},
{
"force": true,
"name": "route.engine.rule.designer",
"path": "re/designer",
"parent": "/",
"priority": 0,
"module": "io.sc.engine.rule.frontend",
"component": "component.engine.rule.designer",
"componentPath": "@/views/resources/designer/Designer.vue",
"redirect": null,
"meta": {
"permissions": [
"/re/resources/**/*"
]
}
},
{
"name": "route.engine.rule.authorization",
"path": "re/authorization",

16
io.sc.engine.rule.frontend/src/views/authorization/Authorization.vue

@ -110,9 +110,20 @@
:columns="[
{ width: '100%', name: 'name', label: $t('name') },
{ width: 80, name: 'type', label: $t('type'), format: Formater.enum(Enums.ResourceType) },
{ width: 100, name: 'code', label: $t('code') },
{ width: 150, name: 'code', label: $t('code') },
{ width: 60, name: 'version', label: $t('version') },
{ width: 60, name: 'status', label: $t('status'), format: Formater.enum(Enums.DeployStatus) },
{
width: 80,
name: 'status',
label: $t('status'),
align: 'center',
format: (value, row) => {
return {
componentType: ResourceDeployStatusTag,
attrs: { status: value },
};
},
},
]"
></w-grid>
</div>
@ -122,6 +133,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { Environment, NotifyManager, axios, Tools, EnumTools, Options, Formater } from 'platform-core';
import ResourceDeployStatusTag from '@/views/shared/ResourceDeployStatusTag.vue';
const roleGridRef = ref();
const resourceTreeGridRef = ref();

86
io.sc.engine.rule.frontend/src/views/dictionary/dictionary.vue

@ -5,8 +5,8 @@
<w-grid
ref="treeGridRef"
:title="$t('re.dictionary.grid.title')"
dense-body
hide-bottom
dense-body
:config-button="true"
selection="multiple"
:checkbox-selection="false"
@ -233,7 +233,18 @@
},
},
{ width: 60, name: 'version', label: $t('version') },
{ width: 60, name: 'status', label: $t('status'), format: Formater.enum(Enums.DeployStatus) },
{
width: 60,
name: 'status',
label: $t('status'),
align: 'center',
format: (value, row) => {
return {
componentType: ResourceDeployStatusTag,
attrs: { status: value },
};
},
},
]"
:editor="{
dialog: {
@ -271,26 +282,26 @@
panel: {
columnNum: 1,
fields: [
{ name: 'type', label: $t('type') },
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id') },
{ name: 'parent', label: $t('parent') },
{ name: 'type', label: $t('type') },
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
{ name: 'order', label: $t('order') },
{ name: 'javaClassName', label: $t('re.dictionary.grid.entity.javaClassName') },
{ name: 'dataComeFrom', label: $t('dataComeFrom') },
{ name: 'creator', label: $t('creator') },
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@row-click="
(evt, row, index) => {
currentSelectedDictionaryIdRef = row.id;
console.log(currentSelectedDictionaryIdRef);
if (row.type === 'UD_JAVA_CLASS') {
divStatus.isShowFieldGrid = true;
divStatus.isShowEnumGrid = false;
@ -332,6 +343,7 @@
:fetch-data-url="Environment.apiContextPath('/api/re/dictionary/userDefinedJavaClassField?dictionary=' + currentSelectedDictionaryIdRef)"
:data-url="Environment.apiContextPath('/api/re/dictionary/userDefinedJavaClassField')"
:pageable="false"
sort-by="order"
:query-form-cols-num="3"
:query-form-fields="[
{ name: 'code', label: $t('code'), type: 'text', clearable: true },
@ -340,26 +352,33 @@
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['query', 'refresh', 'separator', 'add', 'clone', 'edit', 'remove', 'separator', 'view']"
:columns="[
{ width: 50, name: 'order', label: $t('order'), align: 'right', sortable: false },
{ width: 100, name: 'code', label: $t('code') },
{ width: 60, name: 'order', label: $t('order'), align: 'right' },
{ width: 120, name: 'code', label: $t('code') },
{ width: '100%', name: 'name', label: $t('name') },
{
width: 150,
width: 100,
name: 'valueType',
label: $t('re.resources.designer.parameter.grid.entity.valueType'),
sortable: false,
format: (value) => {
return ValueTypeMap[value];
},
},
{
width: 80,
width: 85,
name: 'valueTypeIsList',
label: $t('re.resources.designer.parameter.grid.entity.valueTypeIsList'),
sortable: false,
align: 'center',
format: Formater.yesNo(),
},
{ width: 150, name: 'defaultValue', label: $t('defaultValue'), sortable: false },
{ width: 100, name: 'defaultValue', label: $t('defaultValue') },
{
width: 500,
name: 'valueCalculation',
label: $t('re.dictionary.field.grid.entity.valueCalculation'),
format: (value, row) => {
return PlaceHolder.replace(value);
},
},
]"
:editor="{
dialog: {
@ -379,7 +398,17 @@
type: 'checkbox',
},
{ name: 'defaultValue', label: $t('defaultValue'), type: 'text' },
{ name: 'valueCalculation', label: $t('re.dictionary.field.grid.entity.valueCalculation'), type: 'code-mirror', lang: 'groovy' },
{
name: 'valueCalculation',
label: $t('re.dictionary.field.grid.entity.valueCalculation'),
type: 'code-mirror',
lang: 'java',
rows: 3,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
},
{ name: 'order', label: $t('order'), type: 'number' },
],
},
@ -388,7 +417,9 @@
panel: {
columnNum: 1,
fields: [
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id') },
{ name: 'dictionary', label: $t('dictionary') },
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
@ -396,16 +427,35 @@
{ name: 'valueTypeIsList', label: $t('re.dictionary.field.grid.entity.valueTypeIsList') },
{ name: 'defaultValue', label: $t('defaultValue') },
{ name: 'valueCalculation', label: $t('re.dictionary.field.grid.entity.valueCalculation') },
{ name: 'order', label: $t('order') },
{ name: 'dataComeFrom', label: $t('dataComeFrom') },
{ name: 'creator', label: $t('creator') },
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@after-editor-open="
(row) => {
axios
.get(Environment.apiContextPath('/api/re/dictionary/listParemterHintsByUserDefinedJavaClassDictionaryId/' + currentSelectedDictionaryIdRef))
.then((response) => {
const names = [];
if (response.data?.parentParameterNames && response.data?.parentParameterNames.length > 0) {
for (const item of response.data?.parentParameterNames) {
names.push({ label: item, type: 'variable', apply: '${' + item + '}' });
}
}
if (response.data?.parameterNames && response.data?.parameterNames.length > 0) {
for (const item of response.data?.parameterNames) {
names.push({ label: item, type: 'variable', apply: '${' + item + '}' });
}
}
autoCompletionOptionsRef = names;
});
}
"
>
</w-grid>
</div>
@ -485,6 +535,9 @@ import { axios, Environment, Formater, EnumTools, DialogManager, Downloader } fr
import UserDefinedJavaClassDictionaryJsonDialog from './UserDefinedJavaClassDictionaryJsonDialog.vue';
import ImportDialog from './ImportDialog.vue';
import ImportSampleDialog from './ImportSampleDialog.vue';
import GroovyFunctions from '@/views/resources/designer/GroovyFunctions';
import { PlaceHolder } from '@/utils/PlaceHolder';
import ResourceDeployStatusTag from '@/views/shared/ResourceDeployStatusTag.vue';
const treeGridRef = ref();
const fieldGridRef = ref();
@ -493,6 +546,7 @@ const userDefinedJavaClassDictionaryJsonDialogRef = ref();
const importDialogRef = ref();
const importSampleDialogRef = ref();
const currentSelectedDictionaryIdRef = ref('');
const autoCompletionOptionsRef = ref();
const divStatus = reactive({
isShowFieldGrid: false,
isShowEnumGrid: false,

71
io.sc.engine.rule.frontend/src/views/lib/IndicatorGrid.vue

@ -2,7 +2,7 @@
<div style="height: 100%">
<w-grid
ref="gridRef"
:title="$t('re.lib.grid.title')"
:title="$t('re.lib.tab.indicator.title')"
dense-body
hide-bottom
:config-button="true"
@ -22,25 +22,25 @@
name: 'addGroup',
label: $t('re.lib.grid.toolbar.addGroup'),
icon: 'add',
enableIf: (arg) => {
return !readOnly;
},
click: undefined,
},
{
extend: 'add',
name: 'addInterface',
label: $t('re.lib.grid.toolbar.addTop'),
label: $t('re.indicator.grid.toolbar.addInterface'),
afterClick: (arg) => {
arg.grid.getEditorForm().setFieldValue('type', 'FOLDER');
arg.grid.getEditorForm().setFieldValue('type', 'INTERFACE');
},
},
{
extend: 'add',
name: 'addIndicator',
label: $t('re.lib.grid.toolbar.addChild'),
enableIf: (arg) => {
return arg.selected && arg.selected.type === 'FOLDER';
},
label: $t('re.indicator.grid.toolbar.addIndicator'),
afterClick: (arg) => {
arg.grid.getEditorForm().setFieldValue('type', 'FOLDER');
arg.grid.getEditorForm().setFieldValue('type', 'INDICATOR');
},
},
],
@ -51,7 +51,7 @@
icon: 'content_copy',
click: undefined,
enableIf: (arg) => {
return arg.selected;
return !readOnly && arg.selected;
},
},
'clone',
@ -61,7 +61,7 @@
label: $t('re.lib.grid.toolbar.deepClone'),
icon: 'bi-copy',
enableIf: (arg) => {
return arg.selected && arg.selected.type !== 'FOLDER';
return !readOnly && arg.selected;
},
click: (arg) => {
DialogManager.confirm($t('re.lib.grid.toolbar.deepClone.tip'), () => {
@ -73,16 +73,27 @@
},
],
'separator',
'edit',
'remove',
{
extend: 'edit',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{
extend: 'remove',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
'separator',
'view',
'separator',
'export',
]"
:query-form-cols-num="6"
:query-form-fields="[
{ name: 'code', label: $t('code'), type: 'text', clearable: true },
{ name: 'name', label: $t('name'), type: 'text', clearable: true },
{ colSpan: 2, name: 'code', label: $t('code'), type: 'text', clearable: true },
{ colSpan: 3, name: 'name', label: $t('name'), type: 'text', clearable: true },
]"
:columns="[
{ width: 60, name: 'order', label: $t('order'), align: 'right' },
@ -105,19 +116,44 @@
},
form: {
colsNum: 1,
fields: [],
fields: [
{ name: 'name', label: $t('name'), type: 'text' },
{ name: 'type', label: $t('type'), type: 'select', options: Options.enum(Enums.IndicatorType) },
{
name: 'valueType',
label: $t('valueType'),
type: 'select',
options: [],
},
{ name: 'valueTypeIsList', label: $t('re.resources.designer.parameter.grid.entity.valueTypeIsList'), type: 'checkbox' },
{ name: 'defaultValue', label: $t('defaultValue'), type: 'text' },
{ name: 'order', label: $t('order'), type: 'number' },
],
},
}"
:viewer="{
panel: {
columnNum: 1,
fields: [
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id') },
{ name: 'lib', label: $t('lib') },
{ name: 'type', label: $t('type') },
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
{ name: 'valueType', label: $t('re.resources.designer.parameter.grid.entity.valueType') },
{ name: 'valueTypeVersion', label: $t('re.resources.designer.parameter.grid.entity.valueTypeVersion') },
{ name: 'valueScale', label: $t('re.resources.designer.parameter.grid.entity.valueScale') },
{ name: 'valueRoundingMode', label: $t('re.resources.designer.parameter.grid.entity.valueRoundingMode') },
{ name: 'valueTypeIsList', label: $t('re.resources.designer.parameter.grid.entity.valueTypeIsList') },
{ name: 'defaultValue', label: $t('defaultValue') },
{ name: 'dataComeFrom', label: $t('dataComeFrom') },
{ name: 'creator', label: $t('creator') },
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@ -128,13 +164,14 @@
</template>
<script setup lang="ts">
import { ref, useAttrs, onMounted } from 'vue';
import { axios, Environment, EnumTools, Formater, DialogManager } from 'platform-core';
import { axios, Environment, EnumTools, Formater, Options, DialogManager } from 'platform-core';
import ImportDialog from './ImportDialog.vue';
const attrs = useAttrs();
const props = defineProps({
lib: { type: Object, default: undefined },
readOnly: { type: Boolean, default: false },
});
const gridRef = ref();

17
io.sc.engine.rule.frontend/src/views/lib/Lib.vue

@ -7,6 +7,7 @@
(evt, row, index) => {
if (row.type === 'INDICATOR') {
currentSelectedLibRef = row;
readOnlyRef = currentSelectedLibRef.status !== 'SKETCH';
showStatus.detail = true;
indicatorGridRef?.refresh();
testcaseGridRef?.refresh();
@ -36,6 +37,7 @@
<IndicatorGrid
ref="indicatorGridRef"
:lib="currentSelectedLibRef"
:read-only="readOnlyRef"
@row-click="
(evt, row, index) => {
currentSelectedIndicatorRef = row;
@ -62,8 +64,18 @@
></IndicatorGrid>
</template>
<template #after>
<ValidatorGrid v-if="showStatus.validator" ref="validatorGridRef" :indicator="currentSelectedIndicatorRef"></ValidatorGrid>
<ProcessorGrid v-if="showStatus.processor" ref="processorGridRef" :indicator="currentSelectedIndicatorRef"></ProcessorGrid>
<ValidatorGrid
v-if="showStatus.validator"
ref="validatorGridRef"
:indicator="currentSelectedIndicatorRef"
:read-only="readOnlyRef"
></ValidatorGrid>
<ProcessorGrid
v-if="showStatus.processor"
ref="processorGridRef"
:indicator="currentSelectedIndicatorRef"
:read-only="readOnlyRef"
></ProcessorGrid>
</template>
</q-splitter>
</q-tab-panel>
@ -126,4 +138,5 @@ const showStatus = reactive({
const currentSelectedLibRef = ref({});
const currentSelectedIndicatorRef = ref({});
const currentSelectedTestCaseRef = ref({});
const readOnlyRef = ref(false);
</script>

29
io.sc.engine.rule.frontend/src/views/lib/LibGrid.vue

@ -138,7 +138,7 @@
},
click: (arg) => {
DialogManager.confirm($t('re.lib.grid.toolbar.deploy.tip'), () => {
axios.post(Environment.apiContextPath('/api/re/lib/deploy/' + arg.selected.id)).then(() => {
axios.post(Environment.apiContextPath('/api/re/lib/deploy/' + arg.selected.id)).then((response) => {
treeGridRef.refresh();
});
});
@ -187,11 +187,13 @@
width: '100%',
name: 'name',
label: $t('name'),
sortable: false,
},
{
width: 80,
name: 'type',
label: $t('type'),
sortable: false,
format: (value) => {
if (value !== 'FOLDER') {
return Formater.enum(Enums.LibType)(value);
@ -199,7 +201,19 @@
},
},
{ width: 60, name: 'version', label: $t('version') },
{ width: 60, name: 'status', label: $t('status'), format: Formater.enum(Enums.DeployStatus) },
{
width: 60,
name: 'status',
label: $t('status'),
align: 'center',
sortable: false,
format: (value, row) => {
return {
componentType: ResourceDeployStatusTag,
attrs: { status: value },
};
},
},
]"
:editor="{
dialog: {
@ -228,19 +242,19 @@
panel: {
columnNum: 1,
fields: [
{ name: 'type', label: $t('type') },
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id') },
{ name: 'parent', label: $t('parent') },
{ name: 'type', label: $t('type') },
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
{ name: 'order', label: $t('order') },
{ name: 'dataComeFrom', label: $t('dataComeFrom') },
{ name: 'creator', label: $t('creator') },
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@ -251,13 +265,16 @@
</div>
</template>
<script setup lang="ts">
import { useAttrs } from 'vue';
import { ref, useAttrs } from 'vue';
import { axios, Environment, Formater, EnumTools, DialogManager, Downloader } from 'platform-core';
import ImportDialog from './ImportDialog.vue';
import ImportSampleDialog from './ImportSampleDialog.vue';
import ResourceDeployStatusTag from '@/views/shared/ResourceDeployStatusTag.vue';
const attrs = useAttrs();
const treeGridRef = ref();
const Enums = await EnumTools.fetch(['io.sc.engine.rule.core.enums.LibType', 'io.sc.engine.rule.core.enums.DeployStatus']);
let ValueTypeMap = {};
const ValueTypeList = [];

440
io.sc.engine.rule.frontend/src/views/lib/ProcessorGrid.vue

@ -4,7 +4,7 @@
:title="$t('re.resources.designer.processor.grid.title')"
dense-body
hide-bottom
:config-button="false"
:config-button="true"
selection="multiple"
:checkbox-selection="false"
:tree="false"
@ -19,6 +19,9 @@
{
extend: 'add',
click: undefined,
enableIf: (arg) => {
return !readOnly;
},
},
{
extend: 'add',
@ -106,9 +109,24 @@
},
},
],
'clone',
'edit',
'remove',
{
extend: 'clone',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{
extend: 'edit',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{
extend: 'remove',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
'separator',
'view',
'separator',
@ -124,14 +142,68 @@
sortable: false,
format: (value, row) => {
const type = row.type;
return '';
if ('ARITHMETIC' === type) {
return PlaceHolder.replace(row.arithmetic);
} else if ('TERNARY' === type) {
return row.ternaryCondition + ' <b><span>?</span></b> ' + row.ternaryTrue + ' <b><span>:</span></b> ' + row.ternaryFalse;
} else if ('WHEN_THEN' === type) {
let str = '';
if (row.isWhenThenShorted) {
str += '<span>' + $t('re.resources.designer.processor.grid.entity.isWhenThenShorted') + ', </span>';
}
if (row.when) {
str += '<span>When</span> ' + PlaceHolder.replace(row.when) + ' ';
}
if (row.then) {
str += '<span>Then</span> ' + PlaceHolder.replace(row.then);
}
return str;
} else if ('NUMBER_RANGE' === type) {
const objs = Tools.json2Object(row.numberRange);
if (objs) {
let str = `<div class='border border-b-0'>`;
str += `<table width='100%'>`;
for (let i = 0; i < objs.length; i++) {
const obj = objs[i];
str += '<tr>';
if (i == 0) {
str += ' <td rowspan=' + objs.length + '>' + PlaceHolder.replace(row.numberRangeVar) + '</td>';
}
str += ' <td>' + Tools.generateIntervalRange(obj.minIncluded, obj.min, obj.max, obj.maxIncluded) + '</td>';
str += ' <td>' + ('' + PlaceHolder.replace('' + obj.value)) + '</td>';
str += '</tr>';
}
str += '</table>';
str += '</div>';
return str;
}
return '';
} else if ('CONDITION_RANGE' === type) {
const objs = Tools.json2Object(row.conditionRange);
if (objs) {
let str = `<div class='border border-b-0'>`;
str += `<table width='100%'>`;
for (let i = 0; i < objs.length; i++) {
const obj = objs[i];
str += '<tr>';
str += ' <td>' + PlaceHolder.replace(obj.condition) + '</td>';
str += ' <td><span>' + ('' + PlaceHolder.replace(obj.value)) + '</span></td>';
str += '</tr>';
}
str += '</table>';
str += `</div>`;
return str;
}
return '';
} else if ('GROOVY_SCRIPT' === type) {
return transfromContent(row.groovyScript);
}
},
},
]"
:editor="{
dialog: {
width: '600px',
width: '800px',
},
form: {
colsNum: 1,
@ -145,6 +217,12 @@
name: 'arithmetic',
label: $t('re.resources.designer.processor.grid.entity.arithmetic'),
type: 'code-mirror',
lang: 'java',
rows: 5,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
showIf: (arg) => {
return 'ARITHMETIC' === arg.form.getFieldValue('type');
},
@ -153,7 +231,12 @@
name: 'ternaryCondition',
label: $t('re.resources.designer.processor.grid.entity.ternaryCondition'),
type: 'code-mirror',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
showIf: (arg) => {
return 'TERNARY' === arg.form.getFieldValue('type');
},
@ -162,7 +245,12 @@
name: 'ternaryTrue',
label: $t('re.resources.designer.processor.grid.entity.ternaryTrue'),
type: 'code-mirror',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
showIf: (arg) => {
return 'TERNARY' === arg.form.getFieldValue('type');
},
@ -171,8 +259,12 @@
name: 'ternaryFalse',
label: $t('re.resources.designer.processor.grid.entity.ternaryFalse'),
type: 'code-mirror',
lang: 'groovy',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
showIf: (arg) => {
return 'TERNARY' === arg.form.getFieldValue('type');
},
@ -181,8 +273,12 @@
name: 'when',
label: $t('re.resources.designer.processor.grid.entity.when'),
type: 'code-mirror',
lang: 'groovy',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
showIf: (arg) => {
return 'WHEN_THEN' === arg.form.getFieldValue('type');
},
@ -191,8 +287,12 @@
name: 'then',
label: $t('re.resources.designer.processor.grid.entity.then'),
type: 'code-mirror',
lang: 'groovy',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
showIf: (arg) => {
return 'WHEN_THEN' === arg.form.getFieldValue('type');
},
@ -206,28 +306,246 @@
},
},
{
name: 'numberRange',
label: $t('re.resources.designer.processor.grid.entity.numberRange'),
name: 'numberRangeVar',
label: $t('re.resources.designer.processor.grid.entity.numberRangeVar'),
showIf: (arg) => {
return 'NUMBER_RANGE' === arg.form.getFieldValue('type');
},
type: 'code-mirror',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
},
{
name: 'numberRange',
label: $t('re.resources.designer.processor.grid.entity.numberRange'),
showIf: (arg) => {
return 'NUMBER_RANGE' === arg.form.getFieldValue('type');
},
type: 'w-grid',
height: 300,
denseBody: true,
draggable: true,
pageable: false,
configButton: false,
toolbarConfigure: { noIcon: false },
toolbarActions: [
'add',
'clone',
'edit',
{
extend: 'remove',
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('numberRange');
grid.removeRows(arg.selecteds);
},
},
'separator',
{
name: 'example',
label: $t('example'),
icon: 'bi-balloon',
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('numberRange');
const sampleData = [
{ uuid: Tools.uuid(), minIncluded: false, min: null, max: 0, maxIncluded: false, value: 1 },
{ uuid: Tools.uuid(), minIncluded: true, min: 0, max: 1, maxIncluded: false, value: 2 },
{ uuid: Tools.uuid(), minIncluded: true, min: 1, max: 2, maxIncluded: false, value: 3 },
{ uuid: Tools.uuid(), minIncluded: true, min: 2, max: 3, maxIncluded: false, value: 4 },
{ uuid: Tools.uuid(), minIncluded: true, min: 3, max: null, maxIncluded: false, value: 5 },
{ uuid: Tools.uuid(), minIncluded: false, min: null, max: null, maxIncluded: false, value: 0 },
];
grid.setLocalData(sampleData);
},
},
],
primaryKey: 'uuid',
columns: [
{ width: 200, name: 'uuid', label: 'uuid', hidden: true },
{
width: 60,
name: 'minIncluded',
label: $t('include'),
align: 'center',
sortable: false,
format: (value) => {
if (value) {
return '[';
} else {
return '(';
}
},
},
{ width: 100, name: 'min', label: $t('minValue'), align: 'right', sortable: false },
{ width: 100, name: 'max', label: $t('maxValue'), align: 'right', sortable: false },
{
width: 60,
name: 'maxIncluded',
label: $t('include'),
align: 'center',
sortable: false,
format: (value) => {
if (value) {
return '[';
} else {
return ')';
}
},
},
{ width: '100%', name: 'value', label: $t('value'), sortable: false },
],
editor: {
dialog: {
width: '600px',
},
form: {
colsNum: 4,
fields: [
{ name: 'uuid', label: 'uuid', hidden: true, colSpan: 4 },
{ name: 'min', label: $t('minValue'), type: 'text', colSpan: 3 },
{ name: 'minIncluded', label: $t('include'), type: 'checkbox' },
{ name: 'max', label: $t('maxValue'), type: 'text', colSpan: 3 },
{ name: 'maxIncluded', label: $t('include'), type: 'checkbox' },
{ name: 'value', label: $t('value'), type: 'number', colSpan: 3 },
],
},
},
onBeforeEditorDataSubmit: (data, callback) => {
const grid = gridRef.getEditorForm().getFieldComponent('numberRange');
const form = grid.getEditorForm();
if ('add' == form.getStatus() || 'clone' == form.getStatus()) {
data.uuid = Tools.uuid();
grid.addRow(data);
callback(false);
} else if ('edit' == form.getStatus()) {
grid.replaceRow(data);
callback(false);
}
},
},
{
name: 'conditionRange',
label: $t('re.resources.designer.processor.grid.entity.conditionRange'),
type: 'code-mirror',
rows: 1,
showIf: (arg) => {
return 'CONDITION_RANGE' === arg.form.getFieldValue('type');
},
type: 'w-grid',
height: 300,
denseBody: true,
draggable: true,
pageable: false,
configButton: false,
toolbarConfigure: { noIcon: false },
toolbarActions: [
'add',
'clone',
'edit',
{
extend: 'remove',
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('conditionRange');
grid.removeRows(arg.selecteds);
},
},
'separator',
{
name: 'example',
label: $t('example'),
icon: 'bi-balloon',
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('conditionRange');
const sampleData = [
{ uuid: Tools.uuid(), condition: '${变量名}<=0', value: '0' },
{ uuid: Tools.uuid(), condition: '${变量名}>0 && ${变量名}<=50', value: '50' },
{ uuid: Tools.uuid(), condition: '${变量名}>50 && ${变量名}<=80', value: '80' },
{ uuid: Tools.uuid(), condition: '${变量名}>80 && ${变量名}<=100', value: '100' },
{ uuid: Tools.uuid(), condition: '${变量名}>100', value: '60' },
];
grid.setLocalData(sampleData);
},
},
],
primaryKey: 'uuid',
columns: [
{ name: 'uuid', label: 'uuid', hidden: true },
{
name: 'condition',
label: $t('condition'),
align: 'left',
sortable: false,
format: (value) => {
return PlaceHolder.replace(value);
},
},
{
name: 'value',
label: $t('value'),
sortable: false,
format: (value) => {
return PlaceHolder.replace(value);
},
},
],
editor: {
dialog: {
width: '800px',
},
form: {
colsNum: 1,
fields: [
{ name: 'uuid', label: 'uuid', hidden: true },
{
name: 'condition',
label: $t('condition'),
type: 'code-mirror',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
},
{
name: 'value',
label: $t('value'),
type: 'code-mirror',
lang: 'java',
rows: 1,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
},
],
},
},
onBeforeEditorDataSubmit: (data, callback) => {
const grid = gridRef.getEditorForm().getFieldComponent('conditionRange');
const form = grid.getEditorForm();
if ('add' == form.getStatus() || 'clone' == form.getStatus()) {
data.uuid = Tools.uuid();
grid.addRow(data);
callback(false);
} else if ('edit' == form.getStatus()) {
grid.replaceRow(data);
callback(false);
}
},
},
{
name: 'groovyScript',
label: $t('re.resources.designer.processor.grid.entity.groovyScript'),
type: 'code-mirror',
rows: 1,
rows: 20,
lang: 'java',
lineNumber: true,
placeholder: true,
autoCompletion: true,
autoCompletionOptions: autoCompletionOptionsRef,
extAutoCompletionOptions: GroovyFunctions,
showIf: (arg) => {
return 'GROOVY_SCRIPT' === arg.form.getFieldValue('type');
},
@ -275,13 +593,13 @@
panel: {
columnNum: 1,
fields: [
{ name: 'id', label: $t(''), primaryKey: true },
{ name: 'parameter', label: $t('') },
{ name: 'description', label: $t('') },
{ name: 'order', label: $t('') },
{ name: 'enable', label: $t('') },
{ name: 'type', label: $t('') },
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id'), primaryKey: true },
{ name: 'indicator', label: $t('indicator') },
{ name: 'description', label: $t('description') },
{ name: 'enable', label: $t('enable') },
{ name: 'type', label: $t('type') },
{ name: 'optionCode', label: $t('re.resources.designer.processor.grid.entity.optionCode') },
{ name: 'arithmetic', label: $t('re.resources.designer.processor.grid.entity.arithmetic') },
{ name: 'ternaryCondition', label: $t('re.resources.designer.processor.grid.entity.ternaryCondition') },
{ name: 'ternaryTrue', label: $t('re.resources.designer.processor.grid.entity.ternaryTrue') },
@ -293,6 +611,8 @@
{ name: 'singleRule', label: $t('re.resources.designer.processor.grid.entity.singleRule') },
{ name: 'numberRange', label: $t('re.resources.designer.processor.grid.entity.numberRange') },
{ name: 'conditionRange', label: $t('re.resources.designer.processor.grid.entity.conditionRange') },
{ name: 'decisionTable2C', label: $t('re.resources.designer.processor.grid.entity.decisionTable2C') },
{ name: 'decisionTable', label: $t('re.resources.designer.processor.grid.entity.decisionTable') },
{ name: 'groovyScript', label: $t('re.resources.designer.processor.grid.entity.groovyScript') },
{ name: 'sqlDatasourceName', label: $t('re.resources.designer.processor.grid.entity.sqlDatasourceName') },
@ -305,21 +625,93 @@
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@before-editor-data-submit="
(data, callback) => {
const form = gridRef.getEditorForm();
if ('NUMBER_RANGE' === data.type) {
const grid = form.getFieldComponent('numberRange');
const localData = grid.getLocalData();
const ranges = [];
for (const item of localData) {
ranges.push({
uuid: item.uuid,
minIncluded: item.minIncluded,
min: item.min,
max: item.max,
maxIncluded: item.maxIncluded,
value: item.value,
});
}
data.numberRange = Tools.object2Json(ranges);
} else if ('CONDITION_RANGE' === data.type) {
const grid = form.getFieldComponent('conditionRange');
const localData = grid.getLocalData();
const ranges = [];
for (const item of localData) {
ranges.push({
uuid: item.uuid,
condition: item.condition,
value: item.value,
});
}
data.conditionRange = Tools.object2Json(ranges);
}
}
"
@after-editor-open="
(row) => {
axios.get(Environment.apiContextPath('/api/re/indicator/listParemterHintsByIndicatorId/' + indicator.id)).then((response) => {
const names = [];
if (response.data?.parentParameterNames && response.data?.parentParameterNames.length > 0) {
for (const item of response.data?.parentParameterNames) {
names.push({ label: item, type: 'variable', apply: '${' + item + '}' });
}
}
if (response.data?.parameterNames && response.data?.parameterNames.length > 0) {
for (const item of response.data?.parameterNames) {
names.push({ label: item, type: 'variable', apply: '${' + item + '}' });
}
}
autoCompletionOptionsRef = names;
});
const type = gridRef.getEditorForm().getFieldValue('type');
if ('NUMBER_RANGE' === type) {
const grid = gridRef.getEditorForm().getFieldComponent('numberRange');
const rows = Tools.json2Object(row.numberRange);
grid.setLocalData(rows);
} else if ('CONDITION_RANGE' === type) {
const grid = gridRef.getEditorForm().getFieldComponent('conditionRange');
const rows = Tools.json2Object(row.conditionRange);
grid.setLocalData(rows);
}
}
"
></w-grid>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { Environment, Formater, EnumTools, Options } from 'platform-core';
import { axios, Environment, Formater, EnumTools, Tools } from 'platform-core';
import { PlaceHolder } from '@/utils/PlaceHolder';
import GroovyFunctions from '@/views/resources/designer/GroovyFunctions';
const props = defineProps({
indicator: { type: Object, default: undefined },
readOnly: { type: Boolean, default: false },
});
const gridRef = ref();
const autoCompletionOptionsRef = ref([]);
const transfromContent = (xml) => {
const div = document.createElement('div');
div.textContent = xml;
const result = div.outerHTML;
div.parentNode?.removeChild(div);
return result;
};
const refresh = () => {
gridRef?.value?.refresh();

5
io.sc.engine.rule.frontend/src/views/lib/TestCase.vue

@ -67,9 +67,8 @@
fields: [
{ name: 'order', label: $t('order'), type: 'text', hidden: true },
{ name: 'id', label: $t('id'), type: 'text', hidden: true },
{ name: 'ownerType', label: $t('ownerType'), type: 'text', defaultValue: 'MODEL', hidden: true },
{ name: 'owner', label: $t('owner'), type: 'text', defaultValue: lib.resource, hidden: true },
{ name: 'ownerId', label: $t('ownerId'), type: 'text', defaultValue: lib.resource, hidden: true },
{ name: 'ownerType', label: $t('ownerType'), type: 'text', defaultValue: 'LIB', hidden: true },
{ name: 'owner', label: $t('owner'), type: 'text', defaultValue: lib.id, hidden: true },
{ name: 'name', label: $t('name'), type: 'text', required: true },
{ name: 'description', label: $t('description'), type: 'text' },
],

24
io.sc.engine.rule.frontend/src/views/lib/TestCaseParameter.vue

@ -48,13 +48,30 @@
]"
:columns="[
{ width: 300, name: 'name', label: $t('name') },
{ width: 100, name: 'parameterType', label: $t('type'), format: Formater.enum(Enums.ParameterType) },
{ width: 100, name: 'indicatorType', label: $t('type'), format: Formater.enum(Enums.IndicatorType) },
{
width: 100,
name: 'valueType',
label: $t('re.resources.designer.parameter.grid.entity.valueType'),
format: (value) => {
format: (value, row) => {
return ValueTypeMap[value];
// if (row.valueTypeVersion) {
// return ValueTypeMap[value] + ' (V' + row.valueTypeVersion + ')';
// }
// if (row.valueType == 'java.math.BigDecimal') {
// if (row.valueRoundingMode == 'HALF_UP') {
// return ValueTypeMap[value] + '(' + row.valueScale + ')';
// } else {
// return ValueTypeMap[value] + '(' + row.valueScale + ',' + Formater.enum(Enums.RoundingMode)(row.valueRoundingMode) + ')';
// }
// }
// var result = ValueTypeMap[value];
// result = result || row.valueType;
// if (result) {
// result = result.replace('<', '&lt;');
// result = result.replace('>', '&gt;');
// }
// return result;
},
},
{ width: 100, name: 'defaultValue', label: $t('defaultValue') },
@ -180,7 +197,8 @@ defineExpose({
refresh,
});
const Enums = await EnumTools.fetch(['io.sc.engine.rule.core.enums.ParameterType']);
const Enums = await EnumTools.fetch(['io.sc.engine.rule.core.enums.IndicatorType', 'io.sc.platform.core.enums.RoundingMode']);
let ValueTypeMap = {};
const response = await axios.get(Environment.apiContextPath('/api/re/dictionary/getAllDictionaryMap'));
if (response && response.data) {

2
io.sc.engine.rule.frontend/src/views/lib/ValidatorGrid.vue

@ -5,7 +5,7 @@
:title="$t('re.resources.designer.validator.grid.title')"
dense-body
hide-bottom
:config-button="false"
:config-button="true"
selection="multiple"
:checkbox-selection="false"
:tree="false"

63
io.sc.engine.rule.frontend/src/views/resources/Resources.vue

@ -24,11 +24,12 @@
"
:data-url="Environment.apiContextPath('/api/re/resource')"
:pageable="false"
:sort-by="['order', '-lastModifyDate']"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="[
'refresh',
'separator',
'expand',
'separator',
[
{
extend: 'add',
@ -76,9 +77,7 @@
arg.grid.getEditorForm().setFieldValue('type', 'SCORE_CARD');
},
},
],
[
'clone',
'separator',
{
extend: 'deepClone',
name: 'deepClone',
@ -195,7 +194,7 @@
currentSelectedResourceIdRef = arg.selected.id;
axios.get(Environment.apiContextPath('/api/parameter/list/parameter.re.server.deploy.approve.workflow.enable')).then((response) => {
if (response.data === 'true') {
startDeployWorkflowDialogRef.open(arg.selected.id, arg.selected.code, arg.selected.version);
startDeployWorkflowDialogRef.open(arg.selected.id, arg.selected.code, arg.selected.version, 'OFF_LINE');
} else {
DialogManager.confirm($t('re.resources.grid.toolbar.deploy.offline.tip'), () => {
axios.post(Environment.apiContextPath('/api/re/resource/offline/' + arg.selected.id)).then(() => {
@ -260,37 +259,10 @@
label: $t('status'),
align: 'center',
format: (value, row) => {
const result = {
componentType: 'q-chip',
attrs: {
color: '',
textColor: 'white',
size: '10px',
label: $t('io.sc.engine.rule.core.enums.DeployStatus.HISTORY'),
},
return {
componentType: ResourceDeployStatusTag,
attrs: { status: value },
};
if (value === 'HISTORY') {
result.attrs.label = $t('io.sc.engine.rule.core.enums.DeployStatus.HISTORY');
result.attrs.color = '';
return result;
} else if (value === 'ON_LINE') {
result.attrs.label = $t('io.sc.engine.rule.core.enums.DeployStatus.ON_LINE');
result.attrs.color = 'green';
return result;
} else if (value === 'OFF_LINE') {
result.attrs.label = $t('io.sc.engine.rule.core.enums.DeployStatus.OFF_LINE');
result.attrs.color = 'red';
return result;
} else if (value === 'SKETCH') {
result.attrs.label = $t('io.sc.engine.rule.core.enums.DeployStatus.SKETCH');
result.attrs.color = 'blue';
return result;
} else if (value === 'APPROVING') {
result.attrs.label = $t('io.sc.engine.rule.core.enums.DeployStatus.APPROVING');
result.attrs.color = 'orange';
return result;
}
return '';
},
},
{ width: 120, name: 'taskName', label: $t('re.resources.grid.entity.taskName') },
@ -347,26 +319,24 @@
columnNum: 1,
fields: [
{ name: 'id', label: $t('id') },
{ name: 'parent', label: $t('parent') },
{ name: 'order', label: $t('order') },
{ name: 'type', label: $t('type') },
{ name: 'name', label: $t('name') },
{ name: 'type', label: $t('type'), format: Formater.none() },
{ name: 'code', label: $t('code') },
{ name: 'description', label: $t('description') },
{ name: 'version', label: $t('version') },
{ name: 'status', label: $t('status'), format: Formater.none() },
{ name: 'status', label: $t('status') },
{ name: 'effectiveDate', label: $t('effectiveDate') },
{ name: 'taskName', label: $t('re.resources.grid.entity.taskName') },
{ name: 'taskAssignee', label: $t('re.resources.grid.entity.taskAssignee') },
{
name: 'attachmentHtml',
label: $t('attachment'),
format: (value) => {
return value;
},
},
{ name: 'attachmentCount', label: $t('attachment') },
{ name: 'imports', label: $t('imports') },
{ name: 'dataComeFrom', label: $t('dataComeFrom') },
{ name: 'creator', label: $t('creator') },
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
{ name: 'lastModifyDate', label: $t('lastModifyDate') },
],
},
}"
@ -408,6 +378,7 @@ import DesignerDialog from './designer/DesignerDialog.vue';
import ImportSampleDialog from './ImportSampleDialog.vue';
import ImportDialog from './ImportDialog.vue';
import StartDeployWorkflowDialog from './StartDeployWorkflowDialog.vue';
import ResourceDeployStatusTag from '@/views/shared/ResourceDeployStatusTag.vue';
const treeGridRef = ref();
const attachmentDialogRef = ref();

26
io.sc.engine.rule.frontend/src/views/resources/designer/DesignerDialog.vue

@ -16,6 +16,7 @@
<template #before>
<Model
:resource="currentSelectedResourceRef"
:read-only="readOnlyRef"
@row-click="
(evt, row, index) => {
currentSelectedModelRef = row;
@ -79,7 +80,9 @@
<q-tab-panel v-if="statusReactive.isShowParameter" name="parameter" style="padding: 0px; height: 100%">
<Parameter
ref="parameterGridRef"
:read-only="readOnlyRef"
:model="currentSelectedModelRef"
:resource="currentSelectedResourceRef"
@row-click="
(evt, row, index) => {
currentSelectedParameterRef = row;
@ -122,6 +125,7 @@
<q-tab-panel v-if="statusReactive.isShowTestCase" name="testcase" class="px-0 pb-0" style="padding: 0px; height: 100%">
<TestCase
ref="testCaseGridRef"
:read-only="readOnlyRef"
:model="currentSelectedModelRef"
@row-click="
(evt, row, index) => {
@ -147,9 +151,19 @@
</template>
<template #after>
<div style="height: 100%">
<Validator v-if="statusReactive.isShowValidator" ref="validatorGridRef" :parameter="currentSelectedParameterRef"></Validator>
<Processor v-if="statusReactive.isShowProcessor" ref="processorGridRef" :parameter="currentSelectedParameterRef"></Processor>
<Option v-if="statusReactive.isShowOption" ref="optionGridRef" :parameter="currentSelectedParameterRef"></Option>
<Validator
v-if="statusReactive.isShowValidator"
ref="validatorGridRef"
:read-only="readOnlyRef"
:parameter="currentSelectedParameterRef"
></Validator>
<Processor
v-if="statusReactive.isShowProcessor"
ref="processorGridRef"
:read-only="readOnlyRef"
:parameter="currentSelectedParameterRef"
></Processor>
<Option v-if="statusReactive.isShowOption" ref="optionGridRef" :read-only="readOnlyRef" :parameter="currentSelectedParameterRef"></Option>
<TestCaseParameter
v-if="statusReactive.isShowTestCaseParameter"
ref="testCaseParameterGridRef"
@ -185,7 +199,7 @@ const dialogRef = ref();
const horizontalSplitterRef = ref(400);
const verticalSplitterRef = ref(400);
const readOnlyRef = ref();
const readOnlyRef = ref(false);
const currentSelectedResourceRef = ref();
const currentSelectedModelRef = ref({});
const currentSelectedParameterRef = ref({});
@ -207,9 +221,9 @@ const statusReactive = reactive({
isShowTestCaseParameter: false,
});
const open = (resource, readOnly) => {
readOnlyRef.value = Tools.isUndefinedOrNull(readOnly) ? false : readOnly;
const open = (resource) => {
currentSelectedResourceRef.value = resource;
readOnlyRef.value = currentSelectedResourceRef.value.status !== 'SKETCH';
dialogRef.value.show();
};

6
io.sc.engine.rule.frontend/src/views/resources/designer/GroovyFunctions.ts

@ -7,8 +7,10 @@ const GroovyFunctions = [
{ boost: -50, label: '&&', type: 'keyword', apply: '&&', detail: '并且', info: '并且' },
{ boost: -50, label: '||', type: 'keyword', apply: '||', detail: '或者', info: '或者' },
{ boost: -50, label: '!', type: 'keyword', apply: '!', detail: '非', info: '非' },
{ boost: -60, label: 'PI', type: 'constant', apply: 'PI', detail: '常量 π', info: '常量 π' },
{ boost: -60, label: 'E', type: 'constant', apply: 'E', detail: '常量 e', info: '常量 e' },
{ boost: -60, label: 'null', type: 'constant', apply: 'null', detail: '空', info: '空' },
{ boost: -61, label: "''", type: 'constant', apply: "''", detail: '空字符串', info: '空字符串' },
{ boost: -62, label: 'PI', type: 'constant', apply: 'PI', detail: '常量 π', info: '常量 π' },
{ boost: -63, label: 'E', type: 'constant', apply: 'E', detail: '常量 e', info: '常量 e' },
{
boost: -70,
label: 'IEEEremainder(v1,v2)',

52
io.sc.engine.rule.frontend/src/views/resources/designer/Model.vue

@ -1,5 +1,6 @@
<template>
<w-grid
ref="treeGridRef"
:title="$t('re.resources.designer.model.grid.title')"
dense-body
class="px-1"
@ -24,12 +25,15 @@
{
extend: 'addChild',
label: $t('re.resources.designer.model.grid.toolbar.addChild'),
enableIf: (arg) => {
return !readOnly;
},
},
'separator',
{
extend: 'clone',
enableIf: (arg) => {
return arg.selected && arg.selected.parent;
return !readOnly && arg.selected && arg.selected.parent;
},
},
{
@ -37,28 +41,45 @@
label: $t('deepClone'),
icon: 'bi-copy',
enableIf: (arg) => {
return arg.selected && arg.selected.parent;
return !readOnly && arg.selected && arg.selected.parent;
},
click: (arg) => {
DialogManager.confirm($t('re.resources.designer.model.grid.toolbar.deepClone.tip'), () => {
axios.post(Environment.apiContextPath('/api/re/model/deepClone/' + arg.selected.id)).then(() => {
treeGridRef.refresh();
});
});
},
},
'separator',
{
extend: 'edit',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{
extend: 'remove',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
click: (arg) => {},
},
'edit',
'remove',
'separator',
{
name: 'generateGroovySourceCode',
label: $t('re.resources.designer.model.grid.toolbar.generateGroovySourceCode'),
icon: 'bi-briefcase-fill',
icon: 'bi-code',
enableIf: (arg) => {
return arg.selected;
return !readOnly && arg.selected;
},
click: (arg) => {},
},
{
name: 'generateGroovySourceCode4TestCase',
label: $t('re.resources.designer.model.grid.toolbar.generateGroovySourceCode4TestCase'),
icon: 'bi-briefcase-fill',
icon: 'bi-code',
enableIf: (arg) => {
return arg.selected;
return !readOnly && arg.selected;
},
click: (arg) => {},
},
@ -96,7 +117,6 @@
:editor="{
dialog: {
width: '600px',
height: '400px',
},
form: {
colsNum: 1,
@ -105,7 +125,7 @@
{ name: 'name', label: $t('name'), type: 'text', required: true },
{
name: 'category',
label: $t('re.resources.designer.model.grid.entity.category'),
label: $t('category'),
type: 'select',
options: Options.enum(Enums.ModelCategory),
defaultValue: 'OTHER',
@ -128,6 +148,8 @@
fields: [
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id') },
{ name: 'parent', label: $t('parent') },
{ name: 'resource', label: $t('resource') },
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
@ -140,7 +162,6 @@
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@ -148,14 +169,17 @@
></w-grid>
</template>
<script setup lang="ts">
import { useAttrs } from 'vue';
import { Environment, EnumTools, Formater, Options } from 'platform-core';
import { ref, useAttrs } from 'vue';
import { axios, Environment, EnumTools, Formater, Options, DialogManager } from 'platform-core';
const attrs = useAttrs();
const props = defineProps({
resource: { type: Object, default: undefined },
readOnly: { type: Boolean, default: false },
});
const treeGridRef = ref();
const Enums = await EnumTools.fetch(['io.sc.engine.rule.core.enums.ModelCategory', 'io.sc.engine.rule.core.enums.ExecuteMode']);
</script>

30
io.sc.engine.rule.frontend/src/views/resources/designer/Option.vue

@ -7,13 +7,38 @@
hide-bottom
:config-button="false"
selection="multiple"
:checkbox-selection="false"
:checkbox-selection="true"
:tree="false"
:fetch-data-url="Environment.apiContextPath('/api/re/model/parameter/option/findByParameterId?parameterId=' + parameter.id)"
:data-url="Environment.apiContextPath('/api/re/model/parameter/option')"
:pageable="false"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['refresh', 'separator', 'add', 'edit', 'remove', 'separator', 'view', 'separator', 'export']"
:toolbar-actions="[
'refresh',
'separator',
{
extend: 'add',
enableIf: (arg) => {
return !readOnly;
},
},
{
extend: 'edit',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{
extend: 'remove',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
'separator',
'view',
'separator',
'export',
]"
:columns="[
{ width: 60, name: 'order', label: $t('order'), sortable: false, align: 'right' },
{ width: 100, name: 'inputValue', label: $t('re.resources.designer.option.grid.entity.inputValue'), sortable: false },
@ -85,6 +110,7 @@ const props = defineProps({
fetchDataUrl: { type: String, default: '' },
dataUrl: { type: String, default: '' },
parameter: { type: Object, default: undefined },
readOnly: { type: Boolean, default: false },
});
const emit = defineEmits<{

117
io.sc.engine.rule.frontend/src/views/resources/designer/Parameter.vue

@ -8,7 +8,7 @@
hide-bottom
:config-button="false"
selection="multiple"
:checkbox-selection="false"
:checkbox-selection="true"
:tree="false"
:fetch-data-url="Environment.apiContextPath('/api/re/model/parameter/findByModelId?modelId=' + model.id)"
:data-url="Environment.apiContextPath('/api/re/model/parameter')"
@ -17,15 +17,13 @@
:toolbar-actions="[
'refresh',
'separator',
{
name: 'move',
label: $t('re.resources.designer.parameter.grid.toolbar.move'),
icon: 'bi-share-fill',
},
[
{
extend: 'add',
click: undefined,
enableIf: (arg) => {
return !readOnly;
},
},
{
extend: 'add',
@ -60,8 +58,8 @@
name: 'indicator',
label: $t('re.resources.designer.parameter.grid.toolbar.add.indicator'),
icon: 'bi-link',
afterClick: (arg) => {
arg.grid.getEditorForm().setFieldValue('type', 'INDICATOR');
click: (arg) => {
selectIndicatorDialogRef.open();
},
},
'separator',
@ -113,7 +111,7 @@
{
extend: 'clone',
enableIf: (arg) => {
return arg.selected && arg.selected.parent;
return !readOnly && arg.selected;
},
},
{
@ -122,12 +120,40 @@
label: $t('deepClone'),
icon: 'bi-copy',
enableIf: (arg) => {
return arg.selected && arg.selected.parent;
return !readOnly && arg.selected;
},
click: (arg) => {
DialogManager.confirm($t('re.resources.designer.parameter.grid.toolbar.deepClone.tip'), () => {
axios.post(Environment.apiContextPath('/api/re/model/parameter/deepClone/' + arg.selected.id)).then(() => {
gridRef.refresh();
});
});
},
},
{
extend: 'edit',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{
extend: 'remove',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
'separator',
{
name: 'move',
label: $t('re.resources.designer.parameter.grid.toolbar.move'),
icon: 'bi-share-fill',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
click: (arg) => {
moveParameterDialogRef.open();
},
click: (arg) => {},
},
'edit',
'remove',
'separator',
'view',
'separator',
@ -137,14 +163,30 @@
{ width: 60, name: 'order', label: $t('order'), sortable: false, align: 'right' },
{ width: '100%', name: 'name', label: $t('name'), sortable: false },
{ width: 150, name: 'code', label: $t('code'), sortable: false },
{ width: 100, name: 'type', label: $t('type'), sortable: false, format: Formater.enum(Enums.ParameterType) },
{ width: 110, name: 'type', label: $t('type'), sortable: false, format: Formater.enum(Enums.ParameterType) },
{
width: 150,
width: 180,
name: 'valueType',
label: $t('re.resources.designer.parameter.grid.entity.valueType'),
sortable: false,
format: (value) => {
return ValueTypeMap[value];
format: (value, row) => {
if (row.valueTypeVersion) {
return ValueTypeMap[value] + ' (V' + row.valueTypeVersion + ')';
}
if (row.valueType == 'java.math.BigDecimal') {
if (row.valueRoundingMode == 'HALF_UP') {
return ValueTypeMap[value] + '(' + row.valueScale + ')';
} else {
return ValueTypeMap[value] + '(' + row.valueScale + ',' + Formater.enum(Enums.RoundingMode)(row.valueRoundingMode) + ')';
}
}
var result = ValueTypeMap[value];
result = result || row.valueType;
if (result) {
result = result.replace('<', '&lt;');
result = result.replace('>', '&gt;');
}
return result;
},
},
{
@ -159,7 +201,6 @@
:editor="{
dialog: {
width: '600px',
height: '550px',
},
form: {
colsNum: 1,
@ -173,24 +214,34 @@
name: 'libCode',
label: $t('re.resources.designer.parameter.grid.entity.libCode'),
type: 'select',
options: libCodeOptionsRef,
showIf: (arg) => {
const type = arg.form.getFieldValue('type');
return type === 'INDICATOR';
},
'onUpdate:modelValue': (value) => {
libVersionOptionsRef = IndicatorManager.getLibVersionMap(value);
},
},
{
name: 'libVersion',
label: $t('re.resources.designer.parameter.grid.entity.libVersion'),
type: 'select',
options: libVersionOptionsRef,
showIf: (arg) => {
const type = arg.form.getFieldValue('type');
return type === 'INDICATOR';
},
'onUpdate:modelValue': (value) => {
const libCode = gridRef.getEditorForm().getFieldValue('libCode');
indicatorCodeOptionsRef = IndicatorManager.getIndicatorMap(libCode, value);
},
},
{
name: 'indicatorCode',
label: $t('re.resources.designer.parameter.grid.entity.indicatorCode'),
type: 'select',
options: indicatorCodeOptionsRef,
showIf: (arg) => {
const type = arg.form.getFieldValue('type');
return type === 'INDICATOR';
@ -305,6 +356,7 @@
fields: [
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id') },
{ name: 'model', label: $t('model') },
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
@ -324,7 +376,6 @@
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@ -338,15 +389,35 @@
emit('beforeRequestData');
}
"
@after-editor-open="
(row) => {
console.log(row);
if (row.type === 'INDICATOR') {
axios.get(Environment.apiContextPath('/api/re/lib/isc/getLibInformationWrapper')).then((response) => {
IndicatorManager.setWrapper(response.data);
libCodeOptionsRef = IndicatorManager.getLibMap();
libVersionOptionsRef = IndicatorManager.getLibVersionMap(row.libCode);
indicatorCodeOptionsRef = IndicatorManager.getIndicatorMap(row.libCode, row.libVersion);
});
}
}
"
></w-grid>
<SelectIndicatorDialog ref="selectIndicatorDialogRef" :parameter-grid="gridRef" :model-id="model.id"></SelectIndicatorDialog>
<MoveParameterDialog ref="moveParameterDialogRef" :parameter-grid="gridRef" :resource="resource"></MoveParameterDialog>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { axios, Environment, EnumTools, Formater, Options, Tools } from 'platform-core';
import { axios, Environment, EnumTools, DialogManager, Formater, Options, Tools } from 'platform-core';
import { IndicatorManager } from '@/views/shared/IndicatorManager';
import SelectIndicatorDialog from '@/views/shared/SelectIndicatorDialog.vue';
import MoveParameterDialog from '@/views/shared/MoveParameterDialog.vue';
const props = defineProps({
resource: { type: Object, default: undefined },
model: { type: Object, default: undefined },
readOnly: { type: Boolean, default: false },
});
const emit = defineEmits<{
@ -355,6 +426,11 @@ const emit = defineEmits<{
}>();
const gridRef = ref();
const libCodeOptionsRef = ref([]);
const libVersionOptionsRef = ref();
const indicatorCodeOptionsRef = ref();
const selectIndicatorDialogRef = ref();
const moveParameterDialogRef = ref();
const refresh = () => {
gridRef.value.refresh();
@ -369,6 +445,7 @@ const Enums = await EnumTools.fetch([
'io.sc.engine.rule.core.enums.ParameterType',
'io.sc.engine.rule.core.enums.DeployStatus',
]);
let ValueTypeMap = {};
const ValueTypeList = [];
const response = await axios.get(Environment.apiContextPath('/api/re/dictionary/getAllDictionaryMap'));

55
io.sc.engine.rule.frontend/src/views/resources/designer/Processor.vue

@ -8,7 +8,7 @@
hide-bottom
:config-button="false"
selection="multiple"
:checkbox-selection="false"
:checkbox-selection="true"
:tree="false"
:fetch-data-url="Environment.apiContextPath('/api/re/model/parameter/processor/findByParameterId?parameterId=' + parameter.id)"
:data-url="Environment.apiContextPath('/api/re/model/parameter/processor')"
@ -20,6 +20,9 @@
[
{
extend: 'add',
enableIf: (arg) => {
return !readOnly;
},
click: undefined,
},
{
@ -34,6 +37,19 @@
arg.grid.getEditorForm().setFieldValue('type', 'OPTION_VALUE');
},
},
/*
{
extend: 'add',
name: 'mathFormula',
label: Formater.enum(Enums.ProcessorType)('MATH_FORMULA'),
icon: 'bi-calculator',
enableIf: (arg) => {
return parameter.type !== 'RULE_RESULT' && parameter.type !== 'SINGLE_RULE_RESULT';
},
afterClick: (arg) => {
arg.grid.getEditorForm().setFieldValue('type', 'MATH_FORMULA');
},
},*/
{
extend: 'add',
name: 'arithmetic',
@ -205,6 +221,9 @@
],
{
extend: 'edit',
enableIf: (arg) => {
return arg.selected;
},
click: (arg) => {
const type = arg.selected?.type;
if ('DECISION_TREE' === type) {
@ -216,7 +235,12 @@
}
},
},
'remove',
{
extend: 'remove',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
'separator',
{
name: 'enable',
@ -233,7 +257,7 @@
return 'bi-check';
},
enableIf: (arg) => {
return arg.selected;
return !readOnly && arg.selected;
},
click: (arg) => {
const data = arg.selected;
@ -347,7 +371,15 @@
showIf: (arg) => {
return 'OPTION_VALUE' === arg.form.getFieldValue('type');
},
},
} /*
{
name: 'mathFormula',
label: $t('re.resources.designer.processor.grid.entity.mathFormula'),
type: 'expression',
showIf: (arg) => {
return 'MATH_FORMULA' === arg.form.getFieldValue('type');
},
},*/,
{
name: 'arithmetic',
label: $t('re.resources.designer.processor.grid.entity.arithmetic'),
@ -772,13 +804,12 @@
panel: {
columnNum: 1,
fields: [
{ name: 'id', label: $t(''), primaryKey: true },
{ name: 'parameter', label: $t('') },
{ name: 'description', label: $t('') },
{ name: 'order', label: $t('') },
{ name: 'enable', label: $t('') },
{ name: 'type', label: $t('') },
{ name: 'order', label: $t('order') },
{ name: 'id', label: $t('id'), primaryKey: true },
{ name: 'parameter', label: $t('parameter') },
{ name: 'description', label: $t('description') },
{ name: 'enable', label: $t('enable') },
{ name: 'type', label: $t('type') },
{ name: 'optionCode', label: $t('re.resources.designer.processor.grid.entity.optionCode') },
{ name: 'arithmetic', label: $t('re.resources.designer.processor.grid.entity.arithmetic') },
{ name: 'ternaryCondition', label: $t('re.resources.designer.processor.grid.entity.ternaryCondition') },
@ -805,7 +836,6 @@
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@ -899,6 +929,7 @@ const props = defineProps({
fetchDataUrl: { type: String, default: '' },
dataUrl: { type: String, default: '' },
parameter: { type: Object, default: undefined },
readOnly: { type: Boolean, default: false },
});
const emit = defineEmits<{

29
io.sc.engine.rule.frontend/src/views/resources/designer/TestCaseParameter.vue

@ -29,6 +29,9 @@
'separator',
{
extend: 'edit',
enableIf: (arg) => {
return arg.selected && arg.selected.category !== 'M';
},
},
'separator',
{
@ -47,27 +50,33 @@
'export',
]"
:columns="[
{ width: 300, name: 'name', label: $t('name') },
{ width: 100, name: 'parameterType', label: $t('type'), format: Formater.enum(Enums.ParameterType) },
{ width: 350, name: 'name', label: $t('name'), sortable: false },
{ width: 100, name: 'parameterType', label: $t('type'), format: Formater.enum(Enums.ParameterType), sortable: false },
{
width: 100,
width: 90,
name: 'valueType',
label: $t('re.resources.designer.parameter.grid.entity.valueType'),
sortable: false,
format: (value) => {
return ValueTypeMap[value];
},
},
{ width: 100, name: 'defaultValue', label: $t('defaultValue') },
{ width: 100, name: 'inputValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.inputValue') },
{ width: 100, name: 'expectValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.expectValue') },
{ width: 100, name: 'resultValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.resultValue') },
{ width: 100, name: 'skipCheck', label: $t('re.resources.designer.testCaseParameter.grid.entity.skipCheck') },
{ width: 100, name: 'testResult', label: $t('re.resources.designer.testCaseParameter.grid.entity.testResult'), format: PassOrNotFormater },
{ width: 90, name: 'defaultValue', label: $t('defaultValue'), sortable: false },
{ width: 90, name: 'inputValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.inputValue'), sortable: false },
{ width: 90, name: 'expectValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.expectValue'), sortable: false },
{ width: 90, name: 'resultValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.resultValue'), sortable: false },
{ width: 80, name: 'skipCheck', label: $t('re.resources.designer.testCaseParameter.grid.entity.skipCheck'), sortable: false },
{
width: 80,
name: 'testResult',
label: $t('re.resources.designer.testCaseParameter.grid.entity.testResult'),
format: PassOrNotFormater,
sortable: false,
},
]"
:editor="{
dialog: {
width: '600px',
height: '550px',
},
form: {
colsNum: 1,

25
io.sc.engine.rule.frontend/src/views/resources/designer/Testcase.vue

@ -12,6 +12,7 @@
:fetch-data-url="Environment.apiContextPath('/api/re/testCase/findByOwnerId?ownerId=' + model.resource)"
:data-url="Environment.apiContextPath('/api/re/testCase')"
:pageable="false"
:sort-by="['-lastModifyDate']"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="[
'refresh',
@ -32,21 +33,31 @@
name: 'execute',
label: $t('execute'),
icon: 'bi-caret-right',
click: (arg) => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + arg.selected.id)).then((response) => {
gridRef.refresh();
});
},
},
{
name: 'executeAll',
label: $t('executeAll'),
icon: 'bi-caret-right-fill',
icon: 'bi-fast-forward',
click: (arg) => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeAllTestCase/' + model.resource), { loading: true }).then((response) => {
gridRef.refresh();
});
},
},
'view',
'separator',
'export',
]"
:columns="[
{ width: 50, name: 'order', label: $t('order'), hidden: true },
{ width: 60, name: 'order', label: $t('order'), align: 'right', hidden: true },
{ width: 100, name: 'id', label: $t('id'), hidden: true },
{
width: 100,
width: 60,
name: 'testResult',
label: $t('re.resources.designer.testCase.grid.entity.testResult'),
align: 'center',
@ -55,6 +66,7 @@
{ width: 150, name: 'lastTestDate', label: $t('re.resources.designer.testCase.grid.entity.lastTestDate') },
{ width: 400, name: 'name', label: $t('name') },
{ width: '100%', name: 'description', label: $t('description') },
{ width: 140, name: 'lastModifyDate', label: $t('lastModifyDate') },
]"
:editor="{
dialog: {
@ -64,13 +76,13 @@
form: {
colsNum: 1,
fields: [
{ name: 'order', label: $t('order'), type: 'text', hidden: true },
{ name: 'id', label: $t('id'), type: 'text', hidden: true },
{ name: 'ownerType', label: $t('ownerType'), type: 'text', defaultValue: 'MODEL', hidden: true },
{ name: 'owner', label: $t('owner'), type: 'text', defaultValue: model.resource, hidden: true },
{ name: 'ownerId', label: $t('ownerId'), type: 'text', defaultValue: model.resource, hidden: true },
{ name: 'name', label: $t('name'), type: 'text', required: true },
{ name: 'description', label: $t('description'), type: 'text' },
{ name: 'order', label: $t('order'), type: 'number' },
],
},
}"
@ -102,6 +114,11 @@
emit('beforeRequestData');
}
"
@after-editor-open="
(row) => {
console.log(gridRef.getEditorForm());
}
"
></w-grid>
</template>
<script setup lang="ts">

30
io.sc.engine.rule.frontend/src/views/resources/designer/Validator.vue

@ -7,13 +7,38 @@
hide-bottom
:config-button="false"
selection="multiple"
:checkbox-selection="false"
:checkbox-selection="true"
:tree="false"
:fetch-data-url="Environment.apiContextPath('/api/re/model/parameter/validator/findByParameterId?parameterId=' + parameter.id)"
:data-url="Environment.apiContextPath('/api/re/model/parameter/validator')"
:pageable="false"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['refresh', 'separator', 'add', 'edit', 'remove', 'separator', 'view', 'separator', 'export']"
:toolbar-actions="[
'refresh',
'separator',
{
extend: 'add',
enableIf: (arg) => {
return !readOnly;
},
},
{
extend: 'edit',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{
extend: 'remove',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
'separator',
'view',
'separator',
'export',
]"
:columns="[
{ width: 60, name: 'order', label: $t('order'), sortable: false, align: 'right' },
{ width: 100, name: 'type', label: $t('type'), sortable: false, format: Formater.enum(Enums.ValidatorType) },
@ -156,6 +181,7 @@ const props = defineProps({
fetchDataUrl: { type: String, default: '' },
dataUrl: { type: String, default: '' },
parameter: { type: Object, default: undefined },
readOnly: { type: Boolean, default: false },
});
const emit = defineEmits<{

111
io.sc.engine.rule.frontend/src/views/shared/IndicatorManager.ts

@ -0,0 +1,111 @@
class IndicatorManager {
static #wrapper: any;
public static setWrapper(wrapper): void {
IndicatorManager.#wrapper = wrapper;
}
public static getLibMap() {
if (IndicatorManager.#wrapper) {
const result = [];
for (const libCode in IndicatorManager.#wrapper) {
const lib = IndicatorManager.#wrapper[libCode];
if (lib) {
result.push({ label: lib.name, value: libCode });
}
}
return result;
}
return [];
}
public static getLibVersionMap(libCode) {
if (IndicatorManager.#wrapper) {
if (libCode) {
const lib = IndicatorManager.#wrapper[libCode];
if (lib) {
const versions = lib.versions;
if (versions) {
const result = [];
for (const version in versions) {
result.push({ label: version, value: version });
}
return result;
}
}
}
}
return [];
}
public static getIndicatorMap(libCode, libVersion) {
if (IndicatorManager.#wrapper) {
if (libCode) {
const lib = IndicatorManager.#wrapper[libCode];
if (lib) {
const versions = lib.versions;
if (versions) {
const indicators = versions['' + libVersion];
if (indicators) {
const result = [];
for (const code in indicators) {
result.push({ label: indicators[code], value: code });
}
return result;
}
}
}
}
}
return [];
}
public static getIndicatorName(libCode, libVersion, indicatorCode) {
if (IndicatorManager.#wrapper) {
if (libCode) {
const lib = IndicatorManager.#wrapper[libCode];
if (lib) {
const versions = lib.versions;
if (versions) {
const indicators = versions[libVersion];
if (indicators) {
for (const code in indicators) {
if (code == indicatorCode) {
return indicators[code];
}
}
}
}
}
}
}
return null;
}
public static getIndicatorFullPathName(libCode, libVersion, indicatorCode) {
let path = '';
if (IndicatorManager.#wrapper) {
if (libCode) {
const lib = IndicatorManager.#wrapper[libCode];
if (lib) {
path += lib.name;
const versions = lib.versions;
if (versions) {
const indicators = versions[libVersion];
if (indicators) {
path += '/' + libVersion;
for (const code in indicators) {
if (code == indicatorCode) {
path += '/' + indicators[code];
}
}
}
}
}
}
}
return path;
}
}
export { IndicatorManager };

14
io.sc.engine.rule.frontend/src/views/shared/ResourceDeployStatusTag.vue

@ -0,0 +1,14 @@
<template>
<div>
<q-chip v-if="status === 'HISTORY'" :label="$t('io.sc.engine.rule.core.enums.DeployStatus.HISTORY')" dense></q-chip>
<q-chip v-if="status === 'ON_LINE'" color="green" text-color="white" :label="$t('io.sc.engine.rule.core.enums.DeployStatus.ON_LINE')" dense></q-chip>
<q-chip v-if="status === 'OFF_LINE'" color="brown" text-color="white" :label="$t('io.sc.engine.rule.core.enums.DeployStatus.OFF_LINE')" dense></q-chip>
<q-chip v-if="status === 'SKETCH'" color="blue-grey" text-color="white" :label="$t('io.sc.engine.rule.core.enums.DeployStatus.SKETCH')" dense></q-chip>
<q-chip v-if="status === 'APPROVING'" color="orange" text-color="white" :label="$t('io.sc.engine.rule.core.enums.DeployStatus.APPROVING')" dense></q-chip>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
status: { type: String, default: '' },
});
</script>

184
io.sc.engine.rule.frontend/src/views/shared/SelectIndicatorDialog.vue

@ -0,0 +1,184 @@
<template>
<w-dialog
ref="dialogRef"
:title="$t('re.workflow.dialog.title')"
width="1248px"
height="500px"
:can-maximize="false"
:buttons="[
{
label: $t('confirm'),
noCaps: true,
click: () => {
axios
.post(Environment.apiContextPath('/api/re/model/parameter/addIndicators'), {
modelId: modelId,
indicators: indicatorGridRef.getTickedRows(),
})
.then((response) => {
close();
parameterGrid.refresh();
});
},
},
]"
>
<q-splitter :model-value="450" unit="px" separator-style="width: 3px;" class="w-full" style="height: 100%">
<template #before>
<div class="pr-1" style="height: 100%">
<w-grid
ref="libTreeGridRef"
:title="$t('re.lib.grid.title')"
dense-body
hide-bottom
:config-button="true"
selection="multiple"
:checkbox-selection="false"
:tree="true"
:tree-icon="
(row) => {
if (row.type === 'FOLDER') {
return { name: 'folder', color: 'amber' };
} else {
return { name: 'bi-card-list' };
}
}
"
ticked-field="selected"
:data-url="Environment.apiContextPath('/api/re/lib')"
:pageable="false"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['refresh', 'separator', 'expand', 'separator', 'view', 'separator']"
:columns="[
{
width: '100%',
name: 'name',
label: $t('name'),
},
{
width: 80,
name: 'type',
label: $t('type'),
format: (value) => {
if (value !== 'FOLDER') {
return Formater.enum(Enums.LibType)(value);
}
},
},
{ width: 60, name: 'version', label: $t('version') },
{
width: 80,
name: 'status',
label: $t('status'),
align: 'center',
format: (value, row) => {
return {
componentType: ResourceDeployStatusTag,
attrs: { status: value },
};
},
},
]"
@row-click="
(evt, row, index) => {
console.log(row);
if (row.type === 'INDICATOR') {
currentSelectedLibIdRef = row.id;
} else {
currentSelectedLibIdRef = null;
}
indicatorGridRef?.refresh();
}
"
@before-request-data="
() => {
currentSelectedLibIdRef = null;
indicatorGridRef?.refresh();
}
"
></w-grid>
</div>
</template>
<template #after>
<div class="pl-1" style="height: 100%">
<w-grid
ref="indicatorGridRef"
:title="$t('re.lib.grid.title')"
dense-body
hide-bottom
:config-button="true"
selection="multiple"
:checkbox-selection="true"
:tree="false"
:fetch-data-url="Environment.apiContextPath('api/re/indicator?lib=' + currentSelectedLibIdRef)"
:data-url="Environment.apiContextPath('api/re/indicator')"
:pageable="false"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['query', 'refresh', 'separator', 'view']"
:query-form-cols-num="2"
:query-form-fields="[
{ name: 'code', label: $t('code'), type: 'text', clearable: true },
{ name: 'name', label: $t('name'), type: 'text', clearable: true },
]"
:columns="[
{ width: 60, name: 'order', label: $t('order'), align: 'right' },
{ width: 250, name: 'name', label: $t('name') },
{ width: 100, name: 'type', label: $t('type'), format: Formater.enum(Enums.IndicatorType) },
{
width: 100,
name: 'valueType',
label: $t('valueType'),
format: (value, row) => {
return ValueTypeMap[value];
},
},
{ width: 80, name: 'valueTypeIsList', label: $t('re.resources.designer.parameter.grid.entity.valueTypeIsList'), format: Formater.checkTag() },
{ width: '100%', name: 'defaultValue', label: $t('defaultValue') },
]"
></w-grid>
</div>
</template>
</q-splitter>
</w-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { axios, Environment, EnumTools, Formater } from 'platform-core';
import ResourceDeployStatusTag from '@/views/shared/ResourceDeployStatusTag.vue';
const props = defineProps({
parameterGrid: { type: Object, default: undefined },
modelId: { type: String, default: undefined },
});
const dialogRef = ref();
const libTreeGridRef = ref();
const currentSelectedLibIdRef = ref();
const indicatorGridRef = ref();
const open = () => {
dialogRef.value.show();
};
const close = () => {
dialogRef.value.hide();
};
defineExpose({
open,
close,
});
const Enums = await EnumTools.fetch(['io.sc.engine.rule.core.enums.LibType', 'io.sc.engine.rule.core.enums.DeployStatus']);
let ValueTypeMap = {};
let ValueTypeList = [];
const response = await axios.get(Environment.apiContextPath('/api/re/dictionary/getAllDictionaryMap'));
if (response && response.data) {
ValueTypeMap = {};
ValueTypeList = [];
for (const item of response.data) {
ValueTypeMap[item.key] = item.value;
ValueTypeList.push({ value: item.key, label: item.value });
}
}
</script>

73
io.sc.engine.rule.frontend/src/views/testcase/Testcase.vue

@ -1,41 +1,46 @@
<template>
<q-splitter :model-value="splitterRef" unit="px" separator-style="width: 3px;" class="w-full" style="height: 100%">
<q-splitter horizontal :model-value="splitterRef" unit="px" separator-style="width: 3px;" class="w-full" style="height: 100%">
<template #before>
<div class="pr-1" style="height: 100%">
<w-grid
ref="testcaseGridRef"
:title="$t('re.resources.designer.testCase.grid.title')"
:config-button="false"
dense-body
:config-button="true"
selection="multiple"
:checkbox-selection="false"
:tree="false"
:data-url="Environment.apiContextPath('/api/re/testCase')"
:pageable="true"
:pagination="{ rowsPerPage: 50 }"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="[
'refresh',
'separator',
'clone',
{
extend: 'clone',
name: 'deepClone',
label: $t('deepClone'),
icon: 'bi-copy',
click: (arg) => {},
},
'edit',
'remove',
'separator',
{
name: 'execute',
label: $t('execute'),
icon: 'bi-caret-right',
enableIf: (arg) => {
return arg.selected;
},
click: (arg) => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + arg.selected.id), {}, { loading: true }).then((response) => {
testcaseGridRef.refresh();
});
},
},
{
name: 'executeAll',
label: $t('executeAll'),
icon: 'bi-caret-right-fill',
icon: 'bi-fast-forward',
click: () => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase'), {}, { loading: true }).then(() => {
testcaseGridRef?.refresh();
});
},
},
'separator',
'view',
'separator',
'export',
@ -44,14 +49,17 @@
{ width: 50, name: 'order', label: $t('order'), hidden: true },
{ width: 100, name: 'id', label: $t('id'), hidden: true },
{
width: 80,
width: 60,
name: 'testResult',
label: $t('re.resources.designer.testCase.grid.entity.testResult'),
align: 'center',
sortable: false,
format: PassOrNotFormater,
},
{ width: 150, name: 'lastTestDate', label: $t('re.resources.designer.testCase.grid.entity.lastTestDate') },
{ width: 60, name: 'ownerType', label: $t('type'), sortable: false, format: Formater.enum(Enums.ResourceType) },
{ width: 150, name: 'ownerCode', label: $t('re.resources.designer.testCase.grid.entity.ownerCode'), sortable: false },
{ width: 200, name: 'ownerName', label: $t('re.resources.designer.testCase.grid.entity.ownerName'), sortable: false },
{ width: 100, name: 'ownerVersion', label: $t('re.resources.designer.testCase.grid.entity.ownerVersion'), sortable: false },
{ width: 200, name: 'name', label: $t('name') },
{ width: '100%', name: 'description', label: $t('description') },
]"
@ -110,7 +118,7 @@
:title="$t('re.resources.designer.testCaseParameter.grid.title')"
dense-body
hide-bottom
:config-button="false"
:config-button="true"
selection="multiple"
:checkbox-selection="false"
:tree="true"
@ -134,6 +142,9 @@
'separator',
{
extend: 'edit',
enableIf: (arg) => {
return arg.selected && arg.selected.category !== 'M';
},
},
'separator',
{
@ -141,7 +152,7 @@
label: $t('execute'),
icon: 'bi-caret-right',
click: () => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + currentSelectedTestCaseRef.id)).then(() => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + currentSelectedTestCaseRef.id), {}, { loading: true }).then(() => {
testcaseParameterGridRef?.refresh();
});
},
@ -152,22 +163,29 @@
'export',
]"
:columns="[
{ width: 300, name: 'name', label: $t('name') },
{ width: 100, name: 'parameterType', label: $t('type'), format: Formater.enum(Enums.ParameterType) },
{ width: '100%', name: 'name', label: $t('name'), sortable: false },
{ width: 100, name: 'parameterType', label: $t('type'), format: Formater.enum(Enums.ParameterType), sortable: false },
{
width: 100,
name: 'valueType',
label: $t('re.resources.designer.parameter.grid.entity.valueType'),
sortable: false,
format: (value) => {
return ValueTypeMap[value];
},
},
{ width: 100, name: 'defaultValue', label: $t('defaultValue') },
{ width: 100, name: 'inputValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.inputValue') },
{ width: 100, name: 'expectValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.expectValue') },
{ width: 100, name: 'resultValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.resultValue') },
{ width: 100, name: 'skipCheck', label: $t('re.resources.designer.testCaseParameter.grid.entity.skipCheck') },
{ width: 100, name: 'testResult', label: $t('re.resources.designer.testCaseParameter.grid.entity.testResult'), format: PassOrNotFormater },
{ width: 100, name: 'defaultValue', label: $t('defaultValue'), sortable: false },
{ width: 100, name: 'inputValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.inputValue'), sortable: false },
{ width: 100, name: 'expectValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.expectValue'), sortable: false },
{ width: 100, name: 'resultValue', label: $t('re.resources.designer.testCaseParameter.grid.entity.resultValue'), sortable: false },
{ width: 100, name: 'skipCheck', label: $t('re.resources.designer.testCaseParameter.grid.entity.skipCheck'), sortable: false },
{
width: 80,
name: 'testResult',
label: $t('re.resources.designer.testCaseParameter.grid.entity.testResult'),
sortable: false,
format: PassOrNotFormater,
},
]"
:editor="{
dialog: {
@ -258,7 +276,7 @@ import { onMounted, ref, useAttrs } from 'vue';
import { axios, Environment, EnumTools, Formater, Options, Tools } from 'platform-core';
import PassOrNotFormater from '@/utils/PassOrNotFormater';
const splitterRef = ref(400); //
const splitterRef = ref(350); //
const testcaseGridRef = ref();
const testcaseParameterGridRef = ref();
@ -268,6 +286,7 @@ const Enums = await EnumTools.fetch([
'io.sc.platform.core.enums.RoundingMode',
'io.sc.engine.rule.core.enums.ParameterType',
'io.sc.engine.rule.core.enums.DeployStatus',
'io.sc.engine.rule.core.enums.ResourceType',
]);
let ValueTypeMap = {};
let ValueTypeList = [];

15
io.sc.engine.rule.frontend/src/views/workflow/Workflow.vue

@ -6,7 +6,7 @@
<w-grid
ref="taskGridRef"
:title="$t('re.workflow.task.grid.title')"
:config-button="false"
:config-button="true"
selection="multiple"
:checkbox-selection="false"
:tree="false"
@ -88,6 +88,7 @@
}
},
},
'separator',
{
name: 'complete',
label: $t('re.workflow.task.grid.toolbar.complete'),
@ -111,10 +112,12 @@
click: (arg) => {
if (arg.selected) {
DialogManager.confirm($t('re.workflow.task.grid.toolbar.terminate.tip'), () => {
axios.post(Environment.apiContextPath('/api/flowable/process/operation/terminateProcessInstance/') + arg.selected.id).then(() => {
taskGridRef.refresh();
NotifyManager.success();
});
axios
.post(Environment.apiContextPath('/api/re/resource/workflow/task/terminate/') + arg.selected.taskId + '/' + arg.selected.resourceId)
.then(() => {
taskGridRef.refresh();
NotifyManager.success();
});
});
}
},
@ -199,7 +202,7 @@
ref="historyProcessTaskGridRef"
:title="$t('re.workflow.historyTask.grid.title')"
hide-bottom
:config-button="false"
:config-button="true"
selection="multiple"
:checkbox-selection="false"
:tree="false"

9
io.sc.engine.rule.sample/src/main/resources/META-INF/platform/plugins/rule-engine-sample-resource.json

@ -10,6 +10,15 @@
"id" :"re.engine.sample.resource.app.irs.hankou",
"file" :"classpath:/io/sc/engine/rule/sample/app/irs/hankou/汉口银行-内部评级模型(非零售).json"
},
////WHNS-()
{
"order" :200,
"parentId" :"re.engine.sample.resource.app.irs",
"id" :"re.engine.sample.resource.app.irs.whns",
"file" :"classpath:/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(模型).json",
"dictionary":"classpath:/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(元数据).json",
"lib" :"classpath:/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(特征库).json"
},
///
{"id":"re.engine.sample.resource.app.rirs","parentId":"re.engine.sample.resource.app","order":200},
////-()

3047
io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(元数据).json

File diff suppressed because it is too large

172917
io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(模型).json

File diff suppressed because one or more lines are too long

9238
io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(特征库).json

File diff suppressed because one or more lines are too long

4
io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages.properties

@ -4,8 +4,10 @@ re.engine.sample.resource.app.description=
# \u975E\u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.irs=IRS Model Sample
re.engine.sample.resource.app.irs.description=
re.engine.sample.resource.app.irs.hankou=Not Retail Rate Model
re.engine.sample.resource.app.irs.hankou=Not Retail Rate Model for HANKOU
re.engine.sample.resource.app.irs.hankou.description=Not Retail Rate Model
re.engine.sample.resource.app.irs.whns=Not Retail Rate Model for WHNS
re.engine.sample.resource.app.irs.whns.description=Not Retail Rate Model
# \u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.rirs=RIRS Model Sample

4
io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages_tw_CN.properties

@ -4,8 +4,10 @@ re.engine.sample.resource.app.description=
# \u975E\u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.irs=\u975E\u96F6\u552E\u5167\u8A55
re.engine.sample.resource.app.irs.description=
re.engine.sample.resource.app.irs.hankou=\u5167\u90E8\u8A55\u7D1A\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.hankou=HANKOU\u5167\u90E8\u8A55\u7D1A\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.hankou.description=\u975E\u96F6\u552E\u5167\u8A55\u6A21\u578B(\u91D1\u878D\u6A5F\u69CB\u3001\u767C\u50B5\u4F01\u696D\u3001\u4E00\u822C\u4F01\u696D)
re.engine.sample.resource.app.irs.whns=WHNS\u5167\u90E8\u8A55\u7D1A\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.whns.description=\u975E\u96F6\u552E\u5167\u8A55\u6A21\u578B(\u91D1\u878D\u6A5F\u69CB\u3001\u767C\u50B5\u4F01\u696D\u3001\u4E00\u822C\u4F01\u696D)
# \u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.rirs=\u96F6\u552E\u5167\u8A55

4
io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages_zh_CN.properties

@ -4,8 +4,10 @@ re.engine.sample.resource.app.description=
# \u975E\u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.irs=\u975E\u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.irs.description=
re.engine.sample.resource.app.irs.hankou=\u5185\u90E8\u8BC4\u7EA7\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.hankou=HANKOU\u5185\u90E8\u8BC4\u7EA7\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.hankou.description=\u975E\u96F6\u552E\u5185\u8BC4\u6A21\u578B(\u91D1\u878D\u673A\u6784\u3001\u53D1\u503A\u4F01\u4E1A\u3001\u4E00\u822C\u4F01\u4E1A)
re.engine.sample.resource.app.irs.whns=WHNS\u5185\u90E8\u8BC4\u7EA7\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.whns.description=\u975E\u96F6\u552E\u5185\u8BC4\u6A21\u578B(\u91D1\u878D\u673A\u6784\u3001\u53D1\u503A\u4F01\u4E1A\u3001\u4E00\u822C\u4F01\u4E1A)
# \u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.rirs=\u96F6\u552E\u5185\u8BC4

2
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/common/initializer/RuleEngineWorkFlowInitializer.java

@ -56,7 +56,7 @@ public class RuleEngineWorkFlowInitializer implements ApplicationInitializer{
entity.setName(applicationContext.getMessage(RuleEngineServerConfigurationService.RESOURCE_DEPLOY_WORKFLOW_CATEGORY + "." + RuleEngineServerConfigurationService.RESOURCE_DEPLOY_WORKFLOW_KEY, null, Locale.getDefault()));
entity.setStatus(ProcessStatus.RELEASE);
entity.setVersion(1);
entity.setCanClaimTask(true);
entity.setCanClaimTask(false);
entity.setXml(getRuleEngineWorkflowXmlContent());
entity = processEntityService.add(entity);
processEntityService.deploy(entity.getId());

34
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/dictionary/controller/UserDefinedJavaClassFieldWebController.java

@ -5,8 +5,18 @@ import io.sc.engine.rule.server.dictionary.repository.UserDefinedJavaClassFieldR
import io.sc.engine.rule.server.dictionary.service.DictionaryService;
import io.sc.engine.rule.server.dictionary.service.UserDefinedJavaClassFieldService;
import io.sc.engine.rule.server.dictionary.vo.UserDefinedJavaClassFieldVo;
import io.sc.engine.rule.server.model.entity.ParameterProcessorEntity;
import io.sc.engine.rule.server.util.CodeAndNameMapping;
import io.sc.engine.rule.server.util.VariableCodeAndNameReplacer;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.orm.entity.BaseEntity;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.orm.service.support.QueryResult;
import io.sc.platform.orm.service.support.criteria.Criteria;
import io.sc.platform.orm.util.EntityVoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
@ -14,6 +24,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
@ -23,7 +37,25 @@ import java.util.Map;
@RequestMapping("/api/re/dictionary/userDefinedJavaClassField")
public class UserDefinedJavaClassFieldWebController extends RestCrudController<UserDefinedJavaClassFieldVo,UserDefinedJavaClassFieldEntity,String,UserDefinedJavaClassFieldRepository,UserDefinedJavaClassFieldService> {
@Autowired private DictionaryService dictionaryService;
@Override
protected Page<UserDefinedJavaClassFieldVo> query(HttpServletRequest request, HttpServletResponse response, QueryParameter queryParameter) throws Exception {
Page<UserDefinedJavaClassFieldEntity> page =service.query(queryParameter);
if(page==null){
return QueryResult.emptyPage();
}
List<UserDefinedJavaClassFieldEntity> entities =page.getContent();
List<UserDefinedJavaClassFieldVo> vos =new ArrayList<>(entities.size());
CodeAndNameMapping mapping =dictionaryService.loadCodeAndNameMappingByUserDefinedJavaClassDictionaryId(request.getParameter("dictionary"));
VariableCodeAndNameReplacer.replace(entities,mapping.getCode2NameMapping());
for(UserDefinedJavaClassFieldEntity entity : entities){
if(entity instanceof BaseEntity){
vos.add(((BaseEntity<UserDefinedJavaClassFieldVo>)entity).toVo());
}
}
return new PageImpl<>(vos,page.getPageable(),page.getTotalElements());
}
@RequestMapping(value="importFromCsv",method=RequestMethod.POST)
@ResponseBody
public void importFromCsv(@RequestBody Map<String,String> request) throws Exception{

7
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/dictionary/service/impl/DictionaryServiceImpl.java

@ -60,6 +60,11 @@ public class DictionaryServiceImpl extends DaoServiceImpl<DictionaryEntity, Stri
@Autowired private DictionaryService dictionaryService;
@Autowired private JdbcTemplate jdbcTemplate;
@Override
public String[] getDefaultSortBy() {
return new String[]{"order"};
}
@Override
@Transactional
public DictionaryEntity add(DictionaryEntity entity) throws Exception {
@ -414,7 +419,7 @@ public class DictionaryServiceImpl extends DaoServiceImpl<DictionaryEntity, Stri
List<UserDefinedJavaClassFieldEntity> fieldEntities =dictionaryEntity.getFields();
if(fieldEntities!=null && fieldEntities.size()>0) {
for(UserDefinedJavaClassFieldEntity fieldEntity : fieldEntities) {
hints.addParameterName("${" + fieldEntity.getName() + "}");
hints.addParameterName(fieldEntity.getName());
}
}
}

5
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/dictionary/service/impl/UserDefinedJavaClassFieldServiceImpl.java

@ -11,11 +11,14 @@ import io.sc.engine.rule.server.dictionary.repository.UserDefinedJavaClassFieldR
import io.sc.engine.rule.server.dictionary.service.DictionaryService;
import io.sc.engine.rule.server.dictionary.service.UserDefinedJavaClassFieldService;
import io.sc.engine.rule.server.dictionary.service.support.UserDefinedJavaClassFieldEntityChangedEvent;
import io.sc.engine.rule.server.dictionary.vo.UserDefinedJavaClassFieldVo;
import io.sc.engine.rule.server.model.entity.ParameterProcessorEntity;
import io.sc.engine.rule.server.util.CodeAndNameMapping;
import io.sc.engine.rule.server.util.VariableCodeAndNameReplacer;
import io.sc.platform.orm.entity.support.EntityChangedEventType;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.orm.util.EntityVoUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
@ -33,7 +36,7 @@ import java.util.UUID;
public class UserDefinedJavaClassFieldServiceImpl extends DaoServiceImpl<UserDefinedJavaClassFieldEntity, String, UserDefinedJavaClassFieldRepository> implements UserDefinedJavaClassFieldService{
@Autowired private ApplicationContext applicationContext;
@Autowired private DictionaryService dictionaryService;
@Override
@Transactional
public void importFromCsv(String dictionaryId, String csvContent, String splitChar) throws Exception {

2
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/jpa/listener/handler/LibEntityEventHandler.java

@ -97,7 +97,7 @@ public class LibEntityEventHandler extends AbstractJpaEntityPersistentEventHandl
if(oldEntity!=null) {
String ownerId =oldEntity.getId();
if(ownerId!=null) {
String sql ="delete from RE_TEST_CASE where FD_OWNER_ID=?";
String sql ="delete from RE_TEST_CASE where OWNER_ID_=?";
jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {

34
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/controller/IndicatorProcessorWebController.java

@ -1,18 +1,52 @@
package io.sc.engine.rule.server.lib.controller;
import io.sc.engine.rule.server.dictionary.entity.UserDefinedJavaClassFieldEntity;
import io.sc.engine.rule.server.dictionary.vo.UserDefinedJavaClassFieldVo;
import io.sc.engine.rule.server.lib.entity.IndicatorProcessorEntity;
import io.sc.engine.rule.server.lib.repository.IndicatorProcessorRepository;
import io.sc.engine.rule.server.lib.service.IndicatorProcessorService;
import io.sc.engine.rule.server.lib.service.IndicatorService;
import io.sc.engine.rule.server.lib.vo.IndicatorProcessorVo;
import io.sc.engine.rule.server.util.CodeAndNameMapping;
import io.sc.engine.rule.server.util.VariableCodeAndNameReplacer;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.orm.entity.BaseEntity;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.orm.service.support.QueryResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* 指标处理器 Controller
*/
@Controller
@RequestMapping("/api/re/indicator/processor")
public class IndicatorProcessorWebController extends RestCrudController<IndicatorProcessorVo,IndicatorProcessorEntity,String,IndicatorProcessorRepository,IndicatorProcessorService> {
@Autowired private IndicatorService indicatorService;
@Override
protected Page<IndicatorProcessorVo> query(HttpServletRequest request, HttpServletResponse response, QueryParameter queryParameter) throws Exception {
Page<IndicatorProcessorEntity> page =service.query(queryParameter);
if(page==null){
return QueryResult.emptyPage();
}
List<IndicatorProcessorEntity> entities =page.getContent();
List<IndicatorProcessorVo> vos =new ArrayList<>(entities.size());
CodeAndNameMapping mapping =indicatorService.loadCodeAndNameMappingByIndicatorId(request.getParameter("indicator"));
VariableCodeAndNameReplacer.replace(entities,mapping.getCode2NameMapping());
for(IndicatorProcessorEntity entity : entities){
if(entity instanceof BaseEntity){
vos.add(((BaseEntity<IndicatorProcessorVo>)entity).toVo());
}
}
return new PageImpl<>(vos,page.getPageable(),page.getTotalElements());
}
}

5
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/controller/LibWebController.java

@ -14,6 +14,7 @@ import io.sc.engine.rule.server.plugins.item.wrapper.LibExampleWrapper;
import io.sc.platform.core.util.ObjectMapper4Json;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.mvc.support.FileDownloader;
import io.sc.platform.orm.util.EntityVoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -113,8 +114,8 @@ public class LibWebController extends RestCrudController<LibVo,LibEntity,String,
*/
@RequestMapping(value="deploy/{id}",method=RequestMethod.POST)
@ResponseBody
public LibEntity deploy(@PathVariable(name="id",required=true)String id) throws Exception{
return service.deploy(id);
public LibVo deploy(@PathVariable(name="id",required=true)String id) throws Exception{
return service.deploy(id).toVo();
}
@RequestMapping(value="import",method= {RequestMethod.POST})

4
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/entity/IndicatorEntity.java

@ -283,8 +283,8 @@ public class IndicatorEntity extends AuditorEntity<IndicatorVo> implements DeepC
wrapper.setParameterType(null);
wrapper.setScoreCardVarType(null);
wrapper.setIndicatorType(this.getType());
wrapper.setValueType(null);
wrapper.setDefaultValue(null);
wrapper.setValueType(this.getValueType());
wrapper.setDefaultValue(this.getDefaultValue());
wrapper.setOrder(this.getOrder());
return wrapper;

2
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/repository/IndicatorRepository.java

@ -26,7 +26,7 @@ public interface IndicatorRepository extends DaoRepository<IndicatorEntity,Strin
@Query("select e from IndicatorEntity e where e.lib.code=:libCode and e.lib.version=:libVersion and e.code=:indicatorCode")
public IndicatorEntity findByLibCodeAndVersionAndIndicatorCode(@Param("libCode")String libCode,@Param("libVersion")Integer libVersion,@Param("indicatorCode")String indicatorCode);
@Query("select e from IndicatorEntity e where e.lib.id=:libId")
@Query("select e from IndicatorEntity e where e.lib.id=:libId order by e.order")
public List<IndicatorEntity> findByLibId(@Param("libId")String libId);

11
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/impl/LibServiceImpl.java

@ -44,7 +44,12 @@ public class LibServiceImpl extends DaoServiceImpl<LibEntity, String, LibReposit
@Autowired private IndicatorService indicatorService;
@Autowired private ResourceService resourceService;
@Autowired private ModelService modelService;
@Override
public String[] getDefaultSortBy() {
return new String[]{"order","-lastModifyDate"};
}
@Override
@Transactional
public LibEntity add(LibEntity entity) throws Exception {
@ -150,7 +155,7 @@ public class LibServiceImpl extends DaoServiceImpl<LibEntity, String, LibReposit
releasableLibEntity.setVersion(nextVersion==null?1:nextVersion);
releasableLibEntity.setStatus(DeployStatus.SKETCH);
}
return this.add(cloneEntity);
return repository.save(cloneEntity);
}
}
return null;
@ -172,7 +177,7 @@ public class LibServiceImpl extends DaoServiceImpl<LibEntity, String, LibReposit
releasableLibEntity.setVersion(nextVersion==null?1:nextVersion);
releasableLibEntity.setStatus(DeployStatus.SKETCH);
}
return this.add(cloneEntity);
return repository.save(cloneEntity);
}
}
return null;

2
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/controller/ModelWebController.java

@ -5,6 +5,7 @@ import io.sc.engine.rule.server.model.entity.ModelEntity;
import io.sc.engine.rule.server.model.repository.ModelRepository;
import io.sc.engine.rule.server.model.service.ModelService;
import io.sc.engine.rule.server.model.vo.ModelVo;
import io.sc.platform.core.annotation.IgnoreResponseBodyAdvice;
import io.sc.platform.mvc.controller.support.RestCrudController;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
@ -40,6 +41,7 @@ public class ModelWebController extends RestCrudController<ModelVo, ModelEntity,
@RequestMapping(value="getModeAbstractByParameterProcessor/{parameterProcessorId}",method=RequestMethod.GET)
@ResponseBody
@IgnoreResponseBodyAdvice
public List<ModelAbstract> getModeAbstractByParameterProcessor(@PathVariable(name="parameterProcessorId")String parameterProcessorId) throws Exception{
List<ModelAbstract> list =service.getModeAbstractByParameterProcessor(parameterProcessorId);
if(list==null) {

2
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/controller/ParameterWebController.java

@ -7,6 +7,7 @@ import io.sc.engine.rule.server.model.repository.ParameterRepository;
import io.sc.engine.rule.server.model.service.ParameterService;
import io.sc.engine.rule.server.model.service.support.ParameterIndicatorsWrapper;
import io.sc.engine.rule.server.model.service.support.ParemterHints;
import io.sc.engine.rule.server.model.vo.ModelVo;
import io.sc.engine.rule.server.model.vo.ParameterVo;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.mvc.support.One2Many;
@ -104,7 +105,6 @@ public class ParameterWebController extends RestCrudController<ParameterVo,Param
public ParemterHints listParemterHintsByParameterId(@PathVariable(name="parameterId",required=true)String parameterId) throws Exception{
return service.listParemterHintsByParameterId(parameterId);
}
@RequestMapping(value="move", method=RequestMethod.POST)
@ResponseBody

1
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/entity/ParameterProcessorEntity.java

@ -28,6 +28,7 @@ import java.util.Map;
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type",defaultImpl=EmptyParameterProcessorEntity.class)
@JsonSubTypes({
@JsonSubTypes.Type(value=OptionValueParameterProcessorEntity.class), //选项值处理器
@JsonSubTypes.Type(value=MathFormulaParameterProcessorEntity.class), //数学公式处理器
@JsonSubTypes.Type(value=ArithmeticParameterProcessorEntity.class), //算数操作处理器
@JsonSubTypes.Type(value=ConditionRangeParameterProcessorEntity.class), //条件范围处理器
@JsonSubTypes.Type(value=DecisionTable2CParameterProcessorEntity.class),//简单决策表处理器

58
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/entity/processor/MathFormulaParameterProcessorEntity.java

@ -0,0 +1,58 @@
package io.sc.engine.rule.server.model.entity.processor;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.sc.engine.rule.core.enums.ProcessorType;
import io.sc.engine.rule.core.util.ExpressionReplacer;
import io.sc.engine.rule.server.model.entity.ParameterProcessorEntity;
import io.sc.engine.rule.server.model.vo.processor.ArithmeticParameterProcessorVo;
import io.sc.engine.rule.server.model.vo.processor.MathFormulaParameterProcessorVo;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import java.util.Map;
/**
* 模型参数处理器算数运算操作实体类
*/
@Entity
@DiscriminatorValue("MATH_FORMULA")
@JsonTypeName("MATH_FORMULA")
public class MathFormulaParameterProcessorEntity extends ParameterProcessorEntity {
//算数表达式
@Column(name="MATH_FORMULA_")
private String mathFormula;
@Override
public MathFormulaParameterProcessorVo toVo() {
MathFormulaParameterProcessorVo vo =new MathFormulaParameterProcessorVo();
super.toVo(vo);
vo.setMathFormula(this.getMathFormula());
return vo;
}
@Override
public ProcessorType getType() {
return ProcessorType.MATH_FORMULA;
}
public String getMathFormula() {
return mathFormula;
}
public void setMathFormula(String mathFormula) {
this.mathFormula = mathFormula;
}
@Override
public boolean replace(Map<String, String> mapping) {
String replaced =ExpressionReplacer.replace(this.mathFormula, mapping);
replaced =(replaced==null?"":replaced);
boolean result =false;
if(!replaced.equals(this.mathFormula)) {
result =true;
}
this.mathFormula =replaced;
return result;
}
}

4
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/ParameterService.java

@ -5,7 +5,9 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import io.sc.engine.rule.server.model.vo.ModelVo;
import io.sc.engine.rule.server.model.vo.ParameterVo;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.multipart.MultipartFile;
import io.sc.engine.rule.server.model.entity.ParameterEntity;
import io.sc.engine.rule.server.model.entity.parameter.OutParameterEntity;
@ -80,7 +82,7 @@ public interface ParameterService extends DaoService<ParameterEntity, String, Pa
* @throws Exception 违例
*/
public ParemterHints listParemterHintsByProcessorId(String processorId) throws Exception;
/**
* 将参数移动到新的模型下便于参数在不同子模型间转移
* @param targetModelId 目标模型ID

1
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/impl/ModelServiceImpl.java

@ -19,6 +19,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

11
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/impl/ParameterServiceImpl.java

@ -35,6 +35,7 @@ import io.sc.engine.rule.server.model.service.support.ParameterEntityChangedEven
import io.sc.engine.rule.server.model.service.support.ParameterIndicatorsWrapper;
import io.sc.engine.rule.server.model.service.support.ParemterHints;
import io.sc.engine.rule.server.model.service.support.PmmlDataTypeConvertor;
import io.sc.engine.rule.server.model.vo.ModelVo;
import io.sc.engine.rule.server.model.vo.ParameterVo;
import io.sc.engine.rule.server.util.CodeAndNameMapping;
import io.sc.platform.core.Environment;
@ -228,9 +229,11 @@ public class ParameterServiceImpl extends DaoServiceImpl<ParameterEntity, String
if(parameter!=null) {
ParameterEntity entity =(ParameterEntity)parameter.deepClone();
entity.clearId();
entity.setCode(null);
entity.setCode("P"+System.currentTimeMillis());
entity.setName("clone_" + entity.getName());
return add(entity);
Integer nextOrder =repository.getNextOrder(entity.getModel().getId());
entity.setOrder(nextOrder==null?1:nextOrder);
return repository.save(entity);
}
}
return null;
@ -396,10 +399,10 @@ public class ParameterServiceImpl extends DaoServiceImpl<ParameterEntity, String
}
return new ParemterHints();
}
@Override
public void moveParameters(String targetModelId, Set<String> parameterIds) throws Exception {
String sql ="update RE_MODEL_PARAMETER set FD_MODEL_ID=:targetModelId where FD_ID in (:parameterIds)";
String sql ="update RE_MODEL_PARAMETER set MODEL_ID_=:targetModelId where ID_ in (:parameterIds)";
Map<String, Object> params = new HashMap<String, Object>();
params.put("targetModelId", targetModelId);
params.put("parameterIds", parameterIds);

26
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/vo/processor/MathFormulaParameterProcessorVo.java

@ -0,0 +1,26 @@
package io.sc.engine.rule.server.model.vo.processor;
import io.sc.engine.rule.core.enums.ProcessorType;
import io.sc.engine.rule.server.model.vo.ParameterProcessorVo;
/**
* 模型参数处理器数学公式操作Vo
*/
public class MathFormulaParameterProcessorVo extends ParameterProcessorVo {
//数学公式
private String mathFormula;
@Override
public ProcessorType getType() {
return ProcessorType.MATH_FORMULA;
}
public String getMathFormula() {
return mathFormula;
}
public void setMathFormula(String mathFormula) {
this.mathFormula = mathFormula;
}
}

9
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/controller/ResourceWebController.java

@ -18,6 +18,7 @@ import io.sc.engine.rule.server.resource.entity.ResourceEntity;
import io.sc.engine.rule.server.resource.repository.ResourceRepository;
import io.sc.engine.rule.server.resource.service.ResourceService;
import io.sc.engine.rule.server.resource.vo.ResourceVo;
import io.sc.platform.core.annotation.IgnoreResponseBodyAdvice;
import io.sc.platform.core.util.FileUtil;
import io.sc.platform.core.util.ObjectMapper4Json;
import io.sc.platform.core.util.StringUtil;
@ -49,6 +50,7 @@ public class ResourceWebController extends RestCrudController<ResourceVo, Resour
@RequestMapping(value="getDefineById",method=RequestMethod.GET)
@ResponseBody
@IgnoreResponseBodyAdvice
public ResourceWrapper getDefineById(@RequestParam(name="id",required=true)String resourceId) throws Exception{
ResourceWrapper wrapper =service.getDefineById(resourceId);
return wrapper;
@ -56,12 +58,14 @@ public class ResourceWebController extends RestCrudController<ResourceVo, Resour
@RequestMapping(value="getLastModifyDateById",method=RequestMethod.GET)
@ResponseBody
@IgnoreResponseBodyAdvice
public Long getLastModifyDateById(@RequestParam(name="id",required=true)String resourceId) throws Exception{
return service.getLastModifyDateById(resourceId);
}
@RequestMapping(value="getDefineById2",method=RequestMethod.GET)
@ResponseBody
@IgnoreResponseBodyAdvice
public ResourceWrapper getDefineById2(@RequestParam(name="id",required=true)String resourceId) throws Exception{
ResourceWrapper wrapper =service.getDefineById2(resourceId);
return wrapper;
@ -69,6 +73,7 @@ public class ResourceWebController extends RestCrudController<ResourceVo, Resour
@RequestMapping(value="getDefineByCode",method=RequestMethod.GET)
@ResponseBody
@IgnoreResponseBodyAdvice
public ResourceWrapper getDefineByCode(@RequestParam(name="code",required=true)String resourceCode,@RequestParam(name="version",required=false)Integer version) throws Exception{
ResourceWrapper wrapper =service.getDefineByCode(resourceCode, version);
return wrapper;
@ -76,12 +81,14 @@ public class ResourceWebController extends RestCrudController<ResourceVo, Resour
@RequestMapping(value="getLastModifyDateByCode",method=RequestMethod.GET)
@ResponseBody
@IgnoreResponseBodyAdvice
public Long getLastModifyDateByCode(@RequestParam(name="code",required=true)String resourceCode,@RequestParam(name="version",required=false)Integer version) throws Exception{
return service.getLastModifyDateByCode(resourceCode,version);
}
@RequestMapping(value="executeById",method=RequestMethod.POST)
@ResponseBody
@IgnoreResponseBodyAdvice
public ResourceResult executeById(
@RequestParam(name="resourceId") String resourceId,
@RequestParam(name="subModelCode",required=false) String subModelCode,
@ -96,6 +103,7 @@ public class ResourceWebController extends RestCrudController<ResourceVo, Resour
@RequestMapping(value="executeByCode",method=RequestMethod.POST)
@ResponseBody
@IgnoreResponseBodyAdvice
public ResourceResult executeByCode(
@RequestParam(name="resourceCode") String resourceCode,
@RequestParam(name="version",required=false) Integer version,
@ -199,6 +207,7 @@ public class ResourceWebController extends RestCrudController<ResourceVo, Resour
@RequestMapping(value="getAllReleasableResourceAbstract",method=RequestMethod.GET)
@ResponseBody
@IgnoreResponseBodyAdvice
public List<ResourceAbstract> getAllReleasableResourceAbstract() throws Exception{
List<ResourceAbstract> list =service.getAllReleasableResourceAbstract();
if(list==null) {

5
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/entity/FolderResourceEntity.java

@ -24,9 +24,12 @@ public class FolderResourceEntity extends ResourceEntity {
return vo;
}
public FolderResourceEntity() {}
public FolderResourceEntity() {
this.setType(ResourceType.FOLDER);
}
public FolderResourceEntity(String id) {
this.id =id;
this.setType(ResourceType.FOLDER);
}
@Override

7
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/service/impl/ResourceServiceImpl.java

@ -90,7 +90,12 @@ public class ResourceServiceImpl extends DaoServiceImpl<ResourceEntity, String,
@Autowired
private ProcessEngine processEngine;
@Override
@Override
public String[] getDefaultSortBy() {
return new String[]{"order","-lastModifyDate"};
}
@Override
@Transactional
public ResourceEntity add(ResourceEntity entity) throws Exception {
if (entity == null) {

3
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/resource/vo/ModelResourceVo.java

@ -1,5 +1,6 @@
package io.sc.engine.rule.server.resource.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.sc.engine.rule.core.enums.ResourceType;
import io.sc.engine.rule.server.model.entity.ModelEntity;
@ -8,6 +9,7 @@ import io.sc.engine.rule.server.model.entity.ModelEntity;
*/
public class ModelResourceVo extends ReleasableResourceVo {
//模型
@JsonIgnore
private String model;
@Override
@ -21,5 +23,4 @@ public class ModelResourceVo extends ReleasableResourceVo {
public void setModel(String model) {
this.model = model;
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save