Browse Source

update

main
wangshaoping 7 months ago
parent
commit
766fba20ce
  1. 14
      app.platform/src/main/java/app/platform/Application.java
  2. 2
      erm.frontend/package.json
  3. 2
      gradle.properties
  4. 2
      io.sc.engine.mv.frontend/package.json
  5. 184
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/code/impl/support/processor/MathFormula.java
  6. 4
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/function/ArithmeticFunction.java
  7. 62
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/function/SpecialValueFunction.java
  8. 330
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/math/MathType.java
  9. 60
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/math/ObjectFactory.java
  10. 9
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/math/package-info.java
  11. 12
      io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/po/lib/IndicatorProcessor.java
  12. 5
      io.sc.engine.rule.core/src/main/resources/io/sc/engine/rule/core/code/template/groovy/groovy.ftl
  13. 2
      io.sc.engine.rule.frontend/package.json
  14. 2
      io.sc.engine.rule.frontend/src/views/lib/IndicatorGrid.vue
  15. 60
      io.sc.engine.rule.frontend/src/views/lib/ProcessorGrid.vue
  16. 2
      io.sc.engine.rule.frontend/src/views/lib/TestCaseParameter.vue
  17. 3
      io.sc.engine.rule.frontend/src/views/resources/Resources.vue
  18. 6
      io.sc.engine.rule.frontend/src/views/resources/designer/Option.vue
  19. 55
      io.sc.engine.rule.frontend/src/views/resources/designer/Processor.vue
  20. 2
      io.sc.engine.rule.frontend/src/views/resources/designer/TestCaseParameter.vue
  21. 4
      io.sc.engine.rule.frontend/src/views/resources/designer/Testcase.vue
  22. 1
      io.sc.engine.rule.frontend/src/views/shared/SelectIndicatorDialog.vue
  23. 9
      io.sc.engine.rule.sample/src/main/resources/META-INF/platform/plugins/rule-engine-sample-resource.json
  24. 2
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages.properties
  25. 2
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages_tw_CN.properties
  26. 2
      io.sc.engine.rule.sample/src/main/resources/io/sc/engine/rule/sample/i18n/messages_zh_CN.properties
  27. 6
      io.sc.engine.rule.server/build.gradle
  28. 5
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/dictionary/service/impl/DictionaryServiceImpl.java
  29. 8
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/controller/IndicatorProcessorWebController.java
  30. 2
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/controller/IndicatorWebController.java
  31. 3
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/IndicatorProcessorService.java
  32. 26
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/impl/IndicatorProcessorServiceImpl.java
  33. 4
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/impl/IndicatorServiceImpl.java
  34. 2
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/impl/ParameterProcessorServiceImpl.java
  35. 10
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/impl/ParameterServiceImpl.java
  36. 69
      io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/testcase/service/impl/TestCaseServiceImpl.java
  37. 2
      io.sc.engine.st.frontend/package.json
  38. 2
      io.sc.platform.core.frontend/package.json
  39. 22
      io.sc.platform.core.frontend/src/platform/components/expression/WExpression.vue
  40. 0
      io.sc.platform.core.frontend/src/platform/components/expression/editor/ConstEditor.vue
  41. 58
      io.sc.platform.core.frontend/src/platform/components/expression/editor/VariableEditor.vue
  42. 7
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/Toolbar.vue
  43. 4
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Comma.vue
  44. 16
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Const.vue
  45. 12
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Division.vue
  46. 2
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/LeftParenthesis.vue
  47. 2
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/RightParenthesis.vue
  48. 2
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Variable.vue
  49. 54
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/SpecialValue.vue
  50. 12
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/number/Abs.vue
  51. 46
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsInfinite.vue
  52. 46
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsNaN.vue
  53. 46
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsNil.vue
  54. 46
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsZero.vue
  55. 2
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/trigonometric/hyperbolic/Csch.vue
  56. 2
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/trigonometric/hyperbolic/Sech.vue
  57. 8
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Exp.vue
  58. 8
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Power.vue
  59. 8
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Power2.vue
  60. 35
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Root.vue
  61. 14
      io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Sqrt.vue
  62. 8
      io.sc.platform.core.frontend/src/platform/components/form/elements/WCodeMirror.vue
  63. 11
      io.sc.platform.core.frontend/src/platform/i18n/messages.json
  64. 7
      io.sc.platform.core.frontend/src/platform/i18n/messages_tw_CN.json
  65. 7
      io.sc.platform.core.frontend/src/platform/i18n/messages_zh_CN.json
  66. 114
      io.sc.platform.core.frontend/src/platform/layout/sub-layout/ChangePasswordDialog.vue
  67. 17
      io.sc.platform.core.frontend/src/views/testcase/code-mirror/AutoCompletionManager.ts
  68. 190
      io.sc.platform.core.frontend/src/views/testcase/code-mirror/AutoCompletionManager2.ts
  69. 28
      io.sc.platform.core.frontend/src/views/testcase/code-mirror/code-mirror.vue
  70. 2
      io.sc.platform.core.frontend/src/views/testcase/math/MathEditor.vue
  71. 4
      io.sc.platform.core.frontend/template-project/package.json
  72. 17
      io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/AutoCompletionManager.ts
  73. 190
      io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/AutoCompletionManager2.ts
  74. 28
      io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/code-mirror.vue
  75. 2
      io.sc.platform.core.frontend/template-project/src/views/testcase/math/MathEditor.vue
  76. 10
      io.sc.platform.core/src/main/java/io/sc/platform/core/exception/PasswordStrengthException.java
  77. 6
      io.sc.platform.core/src/main/java/io/sc/platform/core/response/ValidateException.java
  78. 8
      io.sc.platform.core/src/main/java/io/sc/platform/core/service/Desensitizer.java
  79. 30
      io.sc.platform.core/src/main/java/io/sc/platform/core/service/support/DesensitizerProperties.java
  80. 122
      io.sc.platform.core/src/main/java/io/sc/platform/core/util/JaxbUtil.java
  81. 2
      io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/exception.properties
  82. 2
      io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/exception_tw_CN.properties
  83. 2
      io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/exception_zh_CN.properties
  84. 2
      io.sc.platform.developer.frontend/package.json
  85. 21
      io.sc.platform.gradle/templates/pgp/app/src/main/java/app/platform/Application.java.txt
  86. 3
      io.sc.platform.gradle/templates/pgp/setup/gradle.properties
  87. 2
      io.sc.platform.lcdp.frontend/package.json
  88. 2
      io.sc.platform.mvc.frontend/package.json
  89. 7
      io.sc.platform.mvc/src/main/java/io/sc/platform/mvc/autoconfigure/support/AuditLogAspectorBean.java
  90. 4
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/annotation/Desensitizeable.java
  91. 33
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/DesensitizeAndEncodeStringCoverter.java
  92. 31
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/DesensitizeStringCoverter.java
  93. 2
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/EncodeStringConverter.java
  94. 39
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/support/DesensitizeConvertWrapper.java
  95. 36
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/desensitizer/DefaultDesensitizer.java
  96. 4
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/entity/BaseEntity.java
  97. 30
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/plugins/PluginManager.java
  98. 3
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/repository/DaoRepository.java
  99. 4
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/repository/impl/DaoRepositoryImpl.java
  100. 5
      io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/DesensitizerAuthorizerService.java

14
app.platform/src/main/java/app/platform/Application.java

@ -2,9 +2,16 @@ package app.platform;
import io.sc.platform.core.ApplicationLauncher; import io.sc.platform.core.ApplicationLauncher;
import io.sc.platform.core.PlatformSpringBootServletInitializer; import io.sc.platform.core.PlatformSpringBootServletInitializer;
import io.sc.platform.orm.entity.BaseEntity;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.web.WebApplicationInitializer; import org.springframework.web.WebApplicationInitializer;
import java.util.Locale;
import java.util.Set;
/** /**
* 应用程序入口 * 应用程序入口
*/ */
@ -12,5 +19,12 @@ import org.springframework.web.WebApplicationInitializer;
public class Application extends PlatformSpringBootServletInitializer implements WebApplicationInitializer { public class Application extends PlatformSpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ApplicationLauncher.run(Application.class,args); ApplicationLauncher.run(Application.class,args);
// ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
// provider.addIncludeFilter(new AssignableTypeFilter(BaseEntity.class));
// Set<BeanDefinition> components = provider.findCandidateComponents("io.sc");
// for (BeanDefinition component : components)
// {
// System.out.println(component.getBeanClassName());
// }
} }
} }

2
erm.frontend/package.json

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.272", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

2
gradle.properties

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

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

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.273", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

184
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/code/impl/support/processor/MathFormula.java

@ -1,23 +1,195 @@
package io.sc.engine.rule.core.code.impl.support.processor; package io.sc.engine.rule.core.code.impl.support.processor;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.type.TypeReference; import io.sc.engine.rule.core.math.MathType;
import io.sc.engine.rule.core.po.lib.Indicator;
import io.sc.engine.rule.core.po.lib.processor.MathFormulaIndicatorProcessor;
import io.sc.engine.rule.core.po.model.Parameter; import io.sc.engine.rule.core.po.model.Parameter;
import io.sc.engine.rule.core.po.model.processor.MathFormulaParameterProcessor; import io.sc.engine.rule.core.po.model.processor.MathFormulaParameterProcessor;
import io.sc.engine.rule.core.util.JacksonObjectMapper; import org.springframework.util.StringUtils;
import java.util.List; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayDeque;
@JsonIgnoreProperties(ignoreUnknown=true) @JsonIgnoreProperties(ignoreUnknown=true)
public class MathFormula { public class MathFormula {
public static List<ConditionRange> parse(String json) throws Exception { public static MathType parse(String xml) throws Exception {
return JacksonObjectMapper.getDefaultObjectMapper().readValue(json, new TypeReference<List<ConditionRange>>(){}); if(!StringUtils.hasText(xml)){
return null;
}
Reader reader = new StringReader(xml);
XMLInputFactory factory = XMLInputFactory.newInstance(); // Or newFactory()
XMLStreamReader xmlReader = factory.createXMLStreamReader(reader);
JAXBContext decodeJAXBContext =JAXBContext.newInstance(MathType.class);
Unmarshaller unmarshaller =decodeJAXBContext.createUnmarshaller();
JAXBElement<MathType> obj =unmarshaller.unmarshal(xmlReader,MathType.class);
return obj.getValue();
}
public static String generateGroovyCode(Indicator indicator, MathFormulaIndicatorProcessor processor) throws Exception {
if (indicator == null || processor == null) {
return null;
}
String xml =processor.getMathFormula();
if(!StringUtils.hasText(xml)){
return null;
}
Reader reader = new StringReader(xml);
XMLInputFactory xmlInputFactory =XMLInputFactory.newFactory();
XMLEventReader xmlEventReader =xmlInputFactory.createXMLEventReader(reader);
StringBuilder sb =new StringBuilder();
while(xmlEventReader.hasNext()){
XMLEvent xmlEvent = xmlEventReader.nextEvent();
if (xmlEvent.isStartElement()){
StartElement startElement = xmlEvent.asStartElement();
if("mi".equalsIgnoreCase(startElement.getName().getLocalPart())){
}
} else if(xmlEvent.isCharacters()){
Characters characters = xmlEvent.asCharacters();
sb.append(characters.getData());
} else if(xmlEvent.isEndElement()){
EndElement endElement =xmlEvent.asEndElement();
if("mi".equalsIgnoreCase(endElement.getName().getLocalPart())) {
}
}
}
return sb.toString();
} }
public static String generateGroovyCode(Parameter parameter, MathFormulaParameterProcessor processor) throws Exception{ public static String generateGroovyCode(Parameter parameter, MathFormulaParameterProcessor processor) throws Exception{
if(parameter==null || processor==null){ if (parameter == null || processor == null) {
return null;
}
MathType math =parse(processor.getMathFormula());
if(math==null){
return null; return null;
} }
return null; return null;
} }
public static void main(String[] args)throws Exception {
String xml ="<math>\n" +
" <mspace/>\n" +
" <mi>x</mi>\n" +
" <mspace/>\n" +
" <mo>+</mo>\n" +
" <mspace/>\n" +
" <mn>c</mn>\n" +
" <mspace/>\n" +
"</math>";
Reader reader = new StringReader(xml);
XMLInputFactory xmlInputFactory =XMLInputFactory.newFactory();
XMLEventReader xmlEventReader =xmlInputFactory.createXMLEventReader(reader);
StringBuilder sb =new StringBuilder();
ArrayDeque<String> deque =new ArrayDeque<>();
ArrayDeque<Boolean> twoPartDeque =new ArrayDeque<>();
while(xmlEventReader.hasNext()){
XMLEvent xmlEvent = xmlEventReader.nextEvent();
if (xmlEvent.isStartElement()){
StartElement startElement = xmlEvent.asStartElement();
deque.push(startElement.getName().getLocalPart());
String tagName =deque.peek();
switch (tagName){
case "mspace":
break;
case "mrow":
sb.append("(");
break;
case "mfrac":
twoPartDeque.push(true);
break;
case "msqrt":
sb.append("sqrt(");
break;
case "mroot":
twoPartDeque.push(true);
sb.append("root(");
break;
case "msup":
twoPartDeque.push(true);
sb.append("pow(");
break;
}
} else if(xmlEvent.isCharacters()){
String tagName =deque.peek();
Characters characters = xmlEvent.asCharacters();
String text =characters.getData().trim();
switch (tagName){
case "mi":
sb.append("${").append(text);
break;
case "mo":
switch (text){
case "×":
sb.append("*");
break;
case "≥":
sb.append(">=");
break;
case "≤":
sb.append("<=");
break;
case "=":
sb.append("==");
break;
default:
sb.append(text);
}
break;
case "mn":
sb.append(text);
break;
}
} else if(xmlEvent.isEndElement()) {
EndElement endElement = xmlEvent.asEndElement();
String tagName = deque.peek();
deque.pop();
switch (tagName) {
case "mi":
sb.append("}");
break;
case "mspace":
break;
case "mrow":
sb.append(")");
if (twoPartDeque.peek()!=null && twoPartDeque.peek() && deque.peek()!=null) {
switch (deque.peek()){
case "mfrac":
sb.append("/");
break;
case "mroot":
case "msup":
sb.append(",");
break;
}
twoPartDeque.pop();
}
break;
case "mfrac":
break;
case "msqrt":
case "mroot":
case "msup":
sb.append(")");
break;
}
}
}
System.out.println(sb.toString());
}
} }

4
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/function/ArithmeticFunction.java

@ -140,4 +140,8 @@ public class ArithmeticFunction {
public static Double ln(Double x){ public static Double ln(Double x){
return Math.log(x); return Math.log(x);
} }
public static Double root(Double x,Double y){
return Math.pow(x,1/y);
}
} }

62
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/function/SpecialValueFunction.java

@ -12,6 +12,68 @@ import java.util.Random;
* *
*/ */
public class SpecialValueFunction { public class SpecialValueFunction {
/**
* 是否为 null 或空字符串
* @param value
* @return 是否为 null 或空字符串
*/
public static boolean isNil(Object value){
if(value==null) return true;
if(value instanceof String) {
return !StringUtils.hasText((String)value);
}
return false;
}
/**
* 是否非数字
* @param value
* @return 是否非数字
*/
public static boolean isNan(Object value){
if(value instanceof Float){
if(Float.isNaN((float)value)){
return true;
}
}else if(value instanceof Double){
if(Double.isNaN((double)value)){
return true;
}
}
return false;
}
/**
* 是否无穷
* @param value
* @return 是否无穷
*/
public static boolean isInfinite(Object value){
if(value instanceof Float){
if(Float.isInfinite((float)value)){
return true;
}
}else if(value instanceof Double){
if(Double.isInfinite((double)value)){
return true;
}
}
return false;
}
/**
* 是否等于0
* @param value
* @return 是否等于0
*/
public static boolean isZero(Object value){
if((value instanceof Number) && new BigDecimal(value.toString()).equals(BigDecimal.valueOf(0))){
return true;
}
return false;
}
/** /**
* 空值处理函数, 如果值为 null 或空字符串, 返回 nullValue, 否则返回 value * 空值处理函数, 如果值为 null 或空字符串, 返回 nullValue, 否则返回 value
* @param value * @param value

330
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/math/MathType.java

@ -0,0 +1,330 @@
//
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2024.07.16 时间 03:39:28 PM CST
//
package io.sc.engine.rule.core.math;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
/**
* <p>mathType complex type的 Java
*
* <p>以下模式片段指定包含在此类中的预期内容
*
* <pre>
* &lt;complexType name="mathType">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="mi" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="mn" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="mo" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="mspace" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="msqrt" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="mroot" type="{http://www.sc.io/engine/rule/core/math}mathType" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="mrow" type="{http://www.sc.io/engine/rule/core/math}mathType" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="msup" type="{http://www.sc.io/engine/rule/core/math}mathType" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element name="mfrac" type="{http://www.sc.io/engine/rule/core/math}mathType" maxOccurs="unbounded" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "mathType", propOrder = {
"mi",
"mn",
"mo",
"mspace",
"msqrt",
"mroot",
"mrow",
"msup",
"mfrac"
})
public class MathType {
protected List<String> mi;
protected List<String> mn;
protected List<String> mo;
protected List<String> mspace;
protected List<String> msqrt;
protected List<MathType> mroot;
protected List<MathType> mrow;
protected List<MathType> msup;
protected List<MathType> mfrac;
/**
* Gets the value of the mi property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the mi property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMi().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link String }
*
*
*/
public List<String> getMi() {
if (mi == null) {
mi = new ArrayList<String>();
}
return this.mi;
}
/**
* Gets the value of the mn property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the mn property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMn().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link String }
*
*
*/
public List<String> getMn() {
if (mn == null) {
mn = new ArrayList<String>();
}
return this.mn;
}
/**
* Gets the value of the mo property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the mo property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMo().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link String }
*
*
*/
public List<String> getMo() {
if (mo == null) {
mo = new ArrayList<String>();
}
return this.mo;
}
/**
* Gets the value of the mspace property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the mspace property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMspace().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link String }
*
*
*/
public List<String> getMspace() {
if (mspace == null) {
mspace = new ArrayList<String>();
}
return this.mspace;
}
/**
* Gets the value of the msqrt property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the msqrt property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMsqrt().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link String }
*
*
*/
public List<String> getMsqrt() {
if (msqrt == null) {
msqrt = new ArrayList<String>();
}
return this.msqrt;
}
/**
* Gets the value of the mroot property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the mroot property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMroot().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link MathType }
*
*
*/
public List<MathType> getMroot() {
if (mroot == null) {
mroot = new ArrayList<MathType>();
}
return this.mroot;
}
/**
* Gets the value of the mrow property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the mrow property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMrow().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link MathType }
*
*
*/
public List<MathType> getMrow() {
if (mrow == null) {
mrow = new ArrayList<MathType>();
}
return this.mrow;
}
/**
* Gets the value of the msup property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the msup property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMsup().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link MathType }
*
*
*/
public List<MathType> getMsup() {
if (msup == null) {
msup = new ArrayList<MathType>();
}
return this.msup;
}
/**
* Gets the value of the mfrac property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the mfrac property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getMfrac().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link MathType }
*
*
*/
public List<MathType> getMfrac() {
if (mfrac == null) {
mfrac = new ArrayList<MathType>();
}
return this.mfrac;
}
}

60
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/math/ObjectFactory.java

@ -0,0 +1,60 @@
//
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2024.07.16 时间 03:39:28 PM CST
//
package io.sc.engine.rule.core.math;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the io.sc.engine.rule.core.math package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
@XmlRegistry
public class ObjectFactory {
private final static QName _Math_QNAME = new QName("http://www.sc.io/engine/rule/core/math", "math");
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: io.sc.engine.rule.core.math
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {@link MathType }
*
*/
public MathType createMathType() {
return new MathType();
}
/**
* Create an instance of {@link JAXBElement }{@code <}{@link MathType }{@code >}}
*
*/
@XmlElementDecl(namespace = "http://www.sc.io/engine/rule/core/math", name = "math")
public JAXBElement<MathType> createMath(MathType value) {
return new JAXBElement<MathType>(_Math_QNAME, MathType.class, null, value);
}
}

9
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/math/package-info.java

@ -0,0 +1,9 @@
//
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2024.07.16 时间 03:39:28 PM CST
//
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.sc.io/engine/rule/core/math")
package io.sc.engine.rule.core.math;

12
io.sc.engine.rule.core/src/main/java/io/sc/engine/rule/core/po/lib/IndicatorProcessor.java

@ -1,15 +1,7 @@
package io.sc.engine.rule.core.po.lib; package io.sc.engine.rule.core.po.lib;
import io.sc.engine.rule.core.enums.ProcessorType; import io.sc.engine.rule.core.enums.ProcessorType;
import io.sc.engine.rule.core.po.lib.processor.ArithmeticIndicatorProcessor; import io.sc.engine.rule.core.po.lib.processor.*;
import io.sc.engine.rule.core.po.lib.processor.ConditionRangeIndicatorProcessor;
import io.sc.engine.rule.core.po.lib.processor.EmptyIndicatorProcessor;
import io.sc.engine.rule.core.po.lib.processor.GroovyScriptIndicatorProcessor;
import io.sc.engine.rule.core.po.lib.processor.HttpRequestIndicatorProcessor;
import io.sc.engine.rule.core.po.lib.processor.NumberRangeIndicatorProcessor;
import io.sc.engine.rule.core.po.lib.processor.SqlIndicatorProcessor;
import io.sc.engine.rule.core.po.lib.processor.TernaryIndicatorProcessor;
import io.sc.engine.rule.core.po.lib.processor.WhenThenIndicatorProcessor;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes;
@ -23,6 +15,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type",defaultImpl=EmptyIndicatorProcessor.class) @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type",defaultImpl=EmptyIndicatorProcessor.class)
@JsonSubTypes({ @JsonSubTypes({
@JsonSubTypes.Type(value=EmptyIndicatorProcessor.class), //空处理器 @JsonSubTypes.Type(value=EmptyIndicatorProcessor.class), //空处理器
@JsonSubTypes.Type(value=ObjectPropertiesIndicatorProcessor.class), //对象属性
@JsonSubTypes.Type(value=MathFormulaIndicatorProcessor.class), //数学公式
@JsonSubTypes.Type(value=TernaryIndicatorProcessor.class), //三元操作处理器 @JsonSubTypes.Type(value=TernaryIndicatorProcessor.class), //三元操作处理器
@JsonSubTypes.Type(value=ArithmeticIndicatorProcessor.class), //算数操作处理器 @JsonSubTypes.Type(value=ArithmeticIndicatorProcessor.class), //算数操作处理器
@JsonSubTypes.Type(value=WhenThenIndicatorProcessor.class), //When-Then 操作处理器 @JsonSubTypes.Type(value=WhenThenIndicatorProcessor.class), //When-Then 操作处理器

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

@ -72,6 +72,7 @@ import static io.sc.engine.rule.core.function.ArithmeticFunction.sum;
import static io.sc.engine.rule.core.function.ArithmeticFunction.log; import static io.sc.engine.rule.core.function.ArithmeticFunction.log;
import static io.sc.engine.rule.core.function.ArithmeticFunction.ln; import static io.sc.engine.rule.core.function.ArithmeticFunction.ln;
import static io.sc.engine.rule.core.function.ArithmeticFunction.lg; import static io.sc.engine.rule.core.function.ArithmeticFunction.lg;
import static io.sc.engine.rule.core.function.ArithmeticFunction.root;
import static io.sc.engine.rule.core.function.ArithmeticFunction.transformSequencing; 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.now;
@ -88,6 +89,10 @@ import static io.sc.engine.rule.core.function.StringFunction.join;
import static io.sc.engine.rule.core.function.NormalDistributionFunction.G; import static io.sc.engine.rule.core.function.NormalDistributionFunction.G;
import static io.sc.engine.rule.core.function.NormalDistributionFunction.iG; import static io.sc.engine.rule.core.function.NormalDistributionFunction.iG;
import static io.sc.engine.rule.core.function.SpecialValueFunction.isNil;
import static io.sc.engine.rule.core.function.SpecialValueFunction.isZero;
import static io.sc.engine.rule.core.function.SpecialValueFunction.isNan;
import static io.sc.engine.rule.core.function.SpecialValueFunction.isInfinite;
import static io.sc.engine.rule.core.function.SpecialValueFunction.nil; import static io.sc.engine.rule.core.function.SpecialValueFunction.nil;
import static io.sc.engine.rule.core.function.SpecialValueFunction.zero; import static io.sc.engine.rule.core.function.SpecialValueFunction.zero;
import static io.sc.engine.rule.core.function.SpecialValueFunction.nan; import static io.sc.engine.rule.core.function.SpecialValueFunction.nan;

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

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.273", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

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

@ -189,6 +189,7 @@
name: 'valueScale', name: 'valueScale',
label: $t('re.resources.designer.parameter.grid.entity.valueScale'), label: $t('re.resources.designer.parameter.grid.entity.valueScale'),
type: 'number', type: 'number',
defaultValue: 6,
showIf: (arg) => { showIf: (arg) => {
const valueType = arg.form.getFieldValue('valueType'); const valueType = arg.form.getFieldValue('valueType');
const type = arg.form.getFieldValue('type'); const type = arg.form.getFieldValue('type');
@ -203,6 +204,7 @@
label: $t('re.resources.designer.parameter.grid.entity.valueRoundingMode'), label: $t('re.resources.designer.parameter.grid.entity.valueRoundingMode'),
type: 'select', type: 'select',
options: Options.enum(Enums.RoundingMode), options: Options.enum(Enums.RoundingMode),
defaultValue: 'HALF_UP',
showIf: (arg) => { showIf: (arg) => {
const valueType = arg.form.getFieldValue('valueType'); const valueType = arg.form.getFieldValue('valueType');
const type = arg.form.getFieldValue('type'); const type = arg.form.getFieldValue('type');

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

@ -279,6 +279,17 @@
return ''; return '';
} else if ('GROOVY_SCRIPT' === type) { } else if ('GROOVY_SCRIPT' === type) {
return transfromContent(row.groovyScript); return transfromContent(row.groovyScript);
} else if ('SQL' === type) {
return {
componentType: 'w-code-mirror',
attrs: {
lang: 'sql',
rows: 4,
editable: false,
modelValue: row.sql,
placeholder: true,
},
};
} }
}, },
}, },
@ -346,7 +357,37 @@
objectPropertiesMatcherDialogRef.open(objectProperties); objectPropertiesMatcherDialogRef.open(objectProperties);
}, },
}, },
'separator',
'edit', 'edit',
{
extend: 'remove',
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('objectProperties');
const selecteds = arg.selecteds;
for (const selected of selecteds) {
selected.expression = '';
grid.replaceRow(selected);
}
},
},
'separator',
{
extend: 'remove',
name: 'removeAll',
label: $t('removeAll'),
icon: 'bi-trash3',
enableIf: () => {
return true;
},
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('objectProperties');
const rows = grid.getLocalData();
for (const row of rows) {
row.expression = '';
}
grid.setLocalData(rows);
},
},
], ],
primaryKey: 'code', primaryKey: 'code',
columns: [ columns: [
@ -928,12 +969,10 @@
icon: 'bi-caret-right', icon: 'bi-caret-right',
click: (arg) => { click: (arg) => {
const sql = gridRef.getEditorForm().getFieldValue('sql'); const sql = gridRef.getEditorForm().getFieldValue('sql');
let sqlParameterValues = gridRef.getEditorForm().getFieldValue('sqlParameterValues'); const grid = gridRef.getEditorForm().getFieldComponent('sqlParameterValues');
if (sqlParameterValues) { const sqlParameterValues = grid?.getLocalData();
sqlParameterValues = Tools.json2Object(sqlParameterValues);
}
axios axios
.post(Environment.apiContextPath('/api/re/model/parameter/processor/executeSql'), { .post(Environment.apiContextPath('/api/re/indicator/processor/executeSql'), {
sql: sql, sql: sql,
sqlParameterValues: sqlParameterValues, sqlParameterValues: sqlParameterValues,
}) })
@ -1032,7 +1071,7 @@
name: 'parameter', name: 'parameter',
label: $t('parameterName'), label: $t('parameterName'),
type: 'select', type: 'select',
options: autoCompletionOptionsRef, options: indicatorOptionsRef,
}, },
], ],
}, },
@ -1183,6 +1222,14 @@
grid?.setLocalData(properties); grid?.setLocalData(properties);
}); });
} }
//
axios.get(Environment.apiContextPath('api/re/indicator/findIndicatorsByIndicatorId?indicatorId=' + indicator.id)).then((response) => {
const options = [];
for (const indicator of response.data) {
options.push({ label: indicator.name, value: '${' + indicator.name + '}' });
}
indicatorOptionsRef = options;
});
const type = gridRef.getEditorForm().getFieldValue('type'); const type = gridRef.getEditorForm().getFieldValue('type');
if ('NUMBER_RANGE' === type) { if ('NUMBER_RANGE' === type) {
@ -1233,6 +1280,7 @@ const gridRef = ref();
const objectPropertiesMatcherDialogRef = ref(); const objectPropertiesMatcherDialogRef = ref();
const dsOptionsRef = ref([]); const dsOptionsRef = ref([]);
const sqlQueryResultFieldsRef = ref([]); const sqlQueryResultFieldsRef = ref([]);
const indicatorOptionsRef = ref();
const autoCompletionManager = new AutoCompletionManager(); const autoCompletionManager = new AutoCompletionManager();
const autoCompletion = (context) => { const autoCompletion = (context) => {

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

@ -35,7 +35,7 @@
label: $t('execute'), label: $t('execute'),
icon: 'bi-caret-right', icon: 'bi-caret-right',
click: () => { click: () => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + testCase.id)).then(() => { axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + testCase.id), {}, { loading: true }).then(() => {
gridRef?.refresh(); gridRef?.refresh();
}); });
}, },

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

@ -307,6 +307,9 @@
label: $t('re.resources.grid.entity.imports'), label: $t('re.resources.grid.entity.imports'),
type: 'code-mirror', type: 'code-mirror',
lang: 'java', lang: 'java',
lineWrap: true,
lineBreak: false,
toolbar: false,
showIf: (arg) => { showIf: (arg) => {
const type = arg.form.getFieldValue('type'); const type = arg.form.getFieldValue('type');
return type === 'MODEL' || type === 'SCORE_CARD'; return type === 'MODEL' || type === 'SCORE_CARD';

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

@ -22,6 +22,12 @@
return !readOnly; return !readOnly;
}, },
}, },
{
extend: 'clone',
enableIf: (arg) => {
return !readOnly && arg.selected;
},
},
{ {
extend: 'edit', extend: 'edit',
enableIf: (arg) => { enableIf: (arg) => {

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

@ -491,6 +491,35 @@
}, },
}, },
'edit', 'edit',
{
extend: 'remove',
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('objectProperties');
const selecteds = arg.selecteds;
for (const selected of selecteds) {
selected.expression = '';
grid.replaceRow(selected);
}
},
},
'separator',
{
extend: 'remove',
name: 'removeAll',
label: $t('removeAll'),
icon: 'bi-trash3',
enableIf: () => {
return true;
},
click: (arg) => {
const grid = gridRef.getEditorForm().getFieldComponent('objectProperties');
const rows = grid.getLocalData();
for (const row of rows) {
row.expression = '';
}
grid.setLocalData(rows);
},
},
], ],
primaryKey: 'code', primaryKey: 'code',
columns: [ columns: [
@ -757,7 +786,7 @@
sortable: false, sortable: false,
format: (value) => { format: (value) => {
if (value) { if (value) {
return '['; return ']';
} else { } else {
return ')'; return ')';
} }
@ -970,6 +999,10 @@
rows: 20, rows: 20,
lineNumber: true, lineNumber: true,
lang: 'java', lang: 'java',
lineWrap: false,
lineBreak: true,
placeholder: true,
autoCompletion: autoCompletion,
showIf: (arg) => { showIf: (arg) => {
return 'GROOVY_SCRIPT' === arg.form.getFieldValue('type'); return 'GROOVY_SCRIPT' === arg.form.getFieldValue('type');
}, },
@ -1138,10 +1171,8 @@
icon: 'bi-caret-right', icon: 'bi-caret-right',
click: (arg) => { click: (arg) => {
const sql = gridRef.getEditorForm().getFieldValue('sql'); const sql = gridRef.getEditorForm().getFieldValue('sql');
let sqlParameterValues = gridRef.getEditorForm().getFieldValue('sqlParameterValues'); const grid = gridRef.getEditorForm().getFieldComponent('sqlParameterValues');
if (sqlParameterValues) { const sqlParameterValues = grid?.getLocalData();
sqlParameterValues = Tools.json2Object(sqlParameterValues);
}
axios axios
.post(Environment.apiContextPath('/api/re/model/parameter/processor/executeSql'), { .post(Environment.apiContextPath('/api/re/model/parameter/processor/executeSql'), {
sql: sql, sql: sql,
@ -1242,7 +1273,7 @@
name: 'parameter', name: 'parameter',
label: $t('parameterName'), label: $t('parameterName'),
type: 'select', type: 'select',
options: autoCompletionOptionsRef, options: parameterOptionsRef,
}, },
], ],
}, },
@ -1407,6 +1438,15 @@
}); });
} }
//
axios.get(Environment.apiContextPath('api/re/model/parameter/findParametersByParameterId?parameterId=' + parameter.id)).then((response) => {
const options = [];
for (const indicator of response.data) {
options.push({ label: indicator.name, value: '${' + indicator.name + '}' });
}
parameterOptionsRef = options;
});
const type = gridRef.getEditorForm().getFieldValue('type'); const type = gridRef.getEditorForm().getFieldValue('type');
if ('OPTION_VALUE' === type) { if ('OPTION_VALUE' === type) {
editorDialogWidthRef = '40%'; editorDialogWidthRef = '40%';
@ -1472,7 +1512,6 @@
import { ref, onMounted, computed, toValue } from 'vue'; import { ref, onMounted, computed, toValue } from 'vue';
import { axios, Environment, Formater, Tools, EnumTools, Options } from 'platform-core'; import { axios, Environment, Formater, Tools, EnumTools, Options } from 'platform-core';
import { PlaceHolder } from '@/utils/PlaceHolder'; import { PlaceHolder } from '@/utils/PlaceHolder';
import GroovyFunctions from './GroovyFunctions';
import DecisionTreeDialog from './DecisionTreeDialog.vue'; import DecisionTreeDialog from './DecisionTreeDialog.vue';
import ExecutionFlowDialog from './ExecutionFlowDialog.vue'; import ExecutionFlowDialog from './ExecutionFlowDialog.vue';
import ObjectPropertiesMatcherDialog from './ObjectPropertiesMatcherDialog.vue'; import ObjectPropertiesMatcherDialog from './ObjectPropertiesMatcherDialog.vue';
@ -1491,10 +1530,10 @@ const emit = defineEmits<{
}>(); }>();
const gridRef = ref(); const gridRef = ref();
const autoCompletionOptionsRef = ref([]);
const optionOptionsRef = ref([]); const optionOptionsRef = ref([]);
const dsOptionsRef = ref([]); const dsOptionsRef = ref([]);
const sqlQueryResultFieldsRef = ref([]); const sqlQueryResultFieldsRef = ref([]);
const parameterOptionsRef = ref();
const editorDialogWidthRef = ref('50%'); const editorDialogWidthRef = ref('50%');
const decisionTreeDialogRef = ref(); const decisionTreeDialogRef = ref();
const executionFlowDialogRef = ref(); const executionFlowDialogRef = ref();

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

@ -41,7 +41,7 @@
label: $t('execute'), label: $t('execute'),
icon: 'bi-caret-right', icon: 'bi-caret-right',
click: () => { click: () => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + testCase.id)).then(() => { axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + testCase.id), {}, { loading: true }).then(() => {
gridRef?.refresh(); gridRef?.refresh();
}); });
}, },

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

@ -36,7 +36,7 @@
label: $t('execute'), label: $t('execute'),
icon: 'bi-caret-right', icon: 'bi-caret-right',
click: (arg) => { click: (arg) => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + arg.selected.id)).then((response) => { axios.post(Environment.apiContextPath('/api/re/testCase/executeTestCase/' + arg.selected.id), {}, { loading: true }).then((response) => {
gridRef.refresh(); gridRef.refresh();
}); });
}, },
@ -46,7 +46,7 @@
label: $t('executeAll'), label: $t('executeAll'),
icon: 'bi-fast-forward', icon: 'bi-fast-forward',
click: (arg) => { click: (arg) => {
axios.post(Environment.apiContextPath('/api/re/testCase/executeAllTestCase/' + model.resource), { loading: true }).then((response) => { axios.post(Environment.apiContextPath('/api/re/testCase/executeAllTestCase/' + model.resource), {}, { loading: true }).then((response) => {
gridRef.refresh(); gridRef.refresh();
}); });
}, },

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

@ -158,6 +158,7 @@ const indicatorGridRef = ref();
const open = () => { const open = () => {
dialogRef.value.show(); dialogRef.value.show();
libTreeGridRef.value?.refresh();
}; };
const close = () => { const close = () => {

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

@ -19,6 +19,15 @@
"dictionary":"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" "lib" :"classpath:/io/sc/engine/rule/sample/app/irs/whns/WHNS非零售内评(特征库).json"
}, },
////SHNS-()
{
"order" :300,
"parentId" :"re.engine.sample.resource.app.irs",
"id" :"re.engine.sample.resource.app.irs.shns",
"file" :"classpath:/io/sc/engine/rule/sample/app/irs/shns/SHNS非零售内评(模型).json",
"dictionary":"classpath:/io/sc/engine/rule/sample/app/irs/shns/SHNS非零售内评(元数据).json",
"lib" :"classpath:/io/sc/engine/rule/sample/app/irs/shns/SHNS非零售内评(特征库).json"
},
/// ///
{"id":"re.engine.sample.resource.app.rirs","parentId":"re.engine.sample.resource.app","order":200}, {"id":"re.engine.sample.resource.app.rirs","parentId":"re.engine.sample.resource.app","order":200},
////-() ////-()

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

@ -8,6 +8,8 @@ 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.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=Not Retail Rate Model for WHNS
re.engine.sample.resource.app.irs.whns.description=Not Retail Rate Model re.engine.sample.resource.app.irs.whns.description=Not Retail Rate Model
re.engine.sample.resource.app.irs.shns=Not Retail Rate Model for SHNS
re.engine.sample.resource.app.irs.shns.description=Not Retail Rate Model
# \u96F6\u552E\u5185\u8BC4 # \u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.rirs=RIRS Model Sample re.engine.sample.resource.app.rirs=RIRS Model Sample

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

@ -8,6 +8,8 @@ re.engine.sample.resource.app.irs.hankou=HANKOU\u5167\u90E8\u8A55\u7D1A\u6A21\u5
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.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=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) 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)
re.engine.sample.resource.app.irs.shns=SHNS\u5167\u90E8\u8A55\u7D1A\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.shns.description=\u975E\u96F6\u552E\u5167\u8A55\u6A21\u578B(A,B,K\u8A55\u5206\u5361,\u7070\u5EA6\u8A55\u5206\u5361)
# \u96F6\u552E\u5185\u8BC4 # \u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.rirs=\u96F6\u552E\u5167\u8A55 re.engine.sample.resource.app.rirs=\u96F6\u552E\u5167\u8A55

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

@ -8,6 +8,8 @@ re.engine.sample.resource.app.irs.hankou=HANKOU\u5185\u90E8\u8BC4\u7EA7\u6A21\u5
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.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=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) 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)
re.engine.sample.resource.app.irs.shns=SHNS\u5185\u90E8\u8BC4\u7EA7\u6A21\u578B(\u975E\u96F6\u552E)
re.engine.sample.resource.app.irs.shns.description=\u975E\u96F6\u552E\u5185\u8BC4\u6A21\u578B(A,B,K\u8BC4\u5206\u5361,\u7070\u5EA6\u8BC4\u5206\u5361)
# \u96F6\u552E\u5185\u8BC4 # \u96F6\u552E\u5185\u8BC4
re.engine.sample.resource.app.rirs=\u96F6\u552E\u5185\u8BC4 re.engine.sample.resource.app.rirs=\u96F6\u552E\u5185\u8BC4

6
io.sc.engine.rule.server/build.gradle

@ -13,9 +13,9 @@ dependencies {
project(":io.sc.engine.rule.client.spring"), project(":io.sc.engine.rule.client.spring"),
project(":io.sc.engine.rule.frontend"), project(":io.sc.engine.rule.frontend"),
project(":org.webjars.codemirror-5.37.0"), "org.webjars:org.webjars.codemirror:5.37.0",
project(":org.webjars.mxgraph-3.9.12"), "org.webjars:org.webjars.mxgraph:3.9.12",
project(":org.webjars.jquery-1.12.4"), "org.webjars:org.webjars.jquery:1.12.4",
) )
} }

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

@ -306,8 +306,6 @@ public class DictionaryServiceImpl extends DaoServiceImpl<DictionaryEntity, Stri
if(!ValueType.isBaseType(parameter.getValueType())) { if(!ValueType.isBaseType(parameter.getValueType())) {
String code =parameter.getValueType(); String code =parameter.getValueType();
Integer version =parameter.getValueTypeVersion(); Integer version =parameter.getValueTypeVersion();
//modify by wspsc
//ReleasableDictionaryEntity dictionary =repository.findReleasableDictionaryByCodeAndVersion(code, version);
ReleasableDictionaryEntity dictionary =this.findReleasableDictionaryByCodeAndVersion(code, version); ReleasableDictionaryEntity dictionary =this.findReleasableDictionaryByCodeAndVersion(code, version);
if(dictionary!=null) { if(dictionary!=null) {
result.add(dictionary); result.add(dictionary);
@ -345,10 +343,7 @@ public class DictionaryServiceImpl extends DaoServiceImpl<DictionaryEntity, Stri
if(!ValueType.isBaseType(indicator.getValueType())) { if(!ValueType.isBaseType(indicator.getValueType())) {
String code =indicator.getValueType(); String code =indicator.getValueType();
Integer version =indicator.getValueTypeVersion(); Integer version =indicator.getValueTypeVersion();
//modify by wspsc
//ReleasableDictionaryEntity dictionary =repository.findReleasableDictionaryByCodeAndVersion(code, version);
ReleasableDictionaryEntity dictionary =this.findReleasableDictionaryByCodeAndVersion(code, version); ReleasableDictionaryEntity dictionary =this.findReleasableDictionaryByCodeAndVersion(code, version);
//ReleasableDictionaryEntity dictionary =repository.findReleasableDictionaryByCodeAndVersion(code, version);
if(dictionary!=null) { if(dictionary!=null) {
result.add(dictionary); result.add(dictionary);
} }

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

@ -9,6 +9,8 @@ import io.sc.engine.rule.server.lib.service.IndicatorService;
import io.sc.engine.rule.server.lib.vo.IndicatorProcessorVo; import io.sc.engine.rule.server.lib.vo.IndicatorProcessorVo;
import io.sc.engine.rule.server.model.service.support.AutoMatchObjectProperties; import io.sc.engine.rule.server.model.service.support.AutoMatchObjectProperties;
import io.sc.engine.rule.server.model.service.support.ObjectProperty; import io.sc.engine.rule.server.model.service.support.ObjectProperty;
import io.sc.engine.rule.server.model.support.processor.SqlQueryRequest;
import io.sc.engine.rule.server.model.support.processor.SqlQueryResult;
import io.sc.engine.rule.server.util.CodeAndNameMapping; import io.sc.engine.rule.server.util.CodeAndNameMapping;
import io.sc.engine.rule.server.util.VariableCodeAndNameReplacer; import io.sc.engine.rule.server.util.VariableCodeAndNameReplacer;
import io.sc.platform.mvc.controller.support.RestCrudController; import io.sc.platform.mvc.controller.support.RestCrudController;
@ -63,4 +65,10 @@ public class IndicatorProcessorWebController extends RestCrudController<Indicato
public List<ObjectProperty> autoMatch(@RequestBody AutoMatchObjectProperties autoMatchObjectProperties) throws Exception { public List<ObjectProperty> autoMatch(@RequestBody AutoMatchObjectProperties autoMatchObjectProperties) throws Exception {
return service.autoMatch(autoMatchObjectProperties); return service.autoMatch(autoMatchObjectProperties);
} }
@RequestMapping(value="executeSql",method=RequestMethod.POST)
@ResponseBody
public SqlQueryResult executeSql(@RequestBody SqlQueryRequest request) throws Exception{
return service.executeSql(request);
}
} }

2
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/controller/IndicatorWebController.java

@ -32,7 +32,7 @@ public class IndicatorWebController extends RestCrudController<IndicatorVo,Indic
@GetMapping("findIndicatorsByIndicatorId") @GetMapping("findIndicatorsByIndicatorId")
@ResponseBody @ResponseBody
public List<ParameterVo> findIndicatorsByIndicatorId(@RequestParam(name="indicatorId",required = false)String indicatorId) throws Exception { public List<IndicatorVo> findIndicatorsByIndicatorId(@RequestParam(name="indicatorId",required = false)String indicatorId) throws Exception {
return EntityVoUtil.toVo(service.findIndicatorsByIndicatorId(indicatorId)); return EntityVoUtil.toVo(service.findIndicatorsByIndicatorId(indicatorId));
} }

3
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/IndicatorProcessorService.java

@ -4,6 +4,8 @@ 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.repository.IndicatorProcessorRepository;
import io.sc.engine.rule.server.model.service.support.AutoMatchObjectProperties; import io.sc.engine.rule.server.model.service.support.AutoMatchObjectProperties;
import io.sc.engine.rule.server.model.service.support.ObjectProperty; import io.sc.engine.rule.server.model.service.support.ObjectProperty;
import io.sc.engine.rule.server.model.support.processor.SqlQueryRequest;
import io.sc.engine.rule.server.model.support.processor.SqlQueryResult;
import io.sc.platform.orm.service.DaoService; import io.sc.platform.orm.service.DaoService;
import java.util.List; import java.util.List;
@ -14,4 +16,5 @@ import java.util.List;
public interface IndicatorProcessorService extends DaoService<IndicatorProcessorEntity, String, IndicatorProcessorRepository>{ public interface IndicatorProcessorService extends DaoService<IndicatorProcessorEntity, String, IndicatorProcessorRepository>{
public List<ObjectProperty> listObejctPropertiesByProcessorId(String processorId) throws Exception; public List<ObjectProperty> listObejctPropertiesByProcessorId(String processorId) throws Exception;
public List<ObjectProperty> autoMatch(AutoMatchObjectProperties autoMatchObjectProperties) throws Exception; public List<ObjectProperty> autoMatch(AutoMatchObjectProperties autoMatchObjectProperties) throws Exception;
public SqlQueryResult executeSql(SqlQueryRequest request);
} }

26
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/impl/IndicatorProcessorServiceImpl.java

@ -2,6 +2,7 @@ package io.sc.engine.rule.server.lib.service.impl;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import io.sc.engine.rule.core.po.lib.processor.ObjectPropertiesIndicatorProcessor; import io.sc.engine.rule.core.po.lib.processor.ObjectPropertiesIndicatorProcessor;
import io.sc.engine.rule.core.util.ExpressionReplacer;
import io.sc.engine.rule.server.dictionary.entity.DictionaryEntity; import io.sc.engine.rule.server.dictionary.entity.DictionaryEntity;
import io.sc.engine.rule.server.dictionary.entity.ReleasableDictionaryEntity; import io.sc.engine.rule.server.dictionary.entity.ReleasableDictionaryEntity;
import io.sc.engine.rule.server.dictionary.entity.UserDefinedJavaClassDictionaryEntity; import io.sc.engine.rule.server.dictionary.entity.UserDefinedJavaClassDictionaryEntity;
@ -18,6 +19,8 @@ import io.sc.engine.rule.server.lib.vo.processor.ObjectPropertiesIndicatorProces
import io.sc.engine.rule.server.model.entity.ParameterEntity; import io.sc.engine.rule.server.model.entity.ParameterEntity;
import io.sc.engine.rule.server.model.service.support.AutoMatchObjectProperties; import io.sc.engine.rule.server.model.service.support.AutoMatchObjectProperties;
import io.sc.engine.rule.server.model.service.support.ObjectProperty; import io.sc.engine.rule.server.model.service.support.ObjectProperty;
import io.sc.engine.rule.server.model.support.processor.SqlQueryRequest;
import io.sc.engine.rule.server.model.support.processor.SqlQueryResult;
import io.sc.engine.rule.server.model.vo.ParameterProcessorVo; import io.sc.engine.rule.server.model.vo.ParameterProcessorVo;
import io.sc.engine.rule.server.model.vo.processor.ObjectPropertiesParameterProcessorVo; import io.sc.engine.rule.server.model.vo.processor.ObjectPropertiesParameterProcessorVo;
import io.sc.engine.rule.server.util.CodeAndNameMapping; import io.sc.engine.rule.server.util.CodeAndNameMapping;
@ -27,9 +30,14 @@ import io.sc.platform.orm.entity.support.EntityChangedEventType;
import io.sc.platform.orm.service.impl.DaoServiceImpl; import io.sc.platform.orm.service.impl.DaoServiceImpl;
import org.apache.commons.text.similarity.LongestCommonSubsequenceDistance; import org.apache.commons.text.similarity.LongestCommonSubsequenceDistance;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -39,6 +47,7 @@ import java.util.Map;
public class IndicatorProcessorServiceImpl extends DaoServiceImpl<IndicatorProcessorEntity, String, IndicatorProcessorRepository> implements IndicatorProcessorService{ public class IndicatorProcessorServiceImpl extends DaoServiceImpl<IndicatorProcessorEntity, String, IndicatorProcessorRepository> implements IndicatorProcessorService{
@Autowired private IndicatorService indicatorService; @Autowired private IndicatorService indicatorService;
@Autowired private DictionaryService dictionaryService; @Autowired private DictionaryService dictionaryService;
@Autowired private JdbcTemplate jdbcTemplate;
@Override @Override
public String[] getDefaultSortBy() { public String[] getDefaultSortBy() {
@ -259,4 +268,21 @@ public class IndicatorProcessorServiceImpl extends DaoServiceImpl<IndicatorProce
} }
return result; return result;
} }
public SqlQueryResult executeSql(SqlQueryRequest request) {
if(request!=null) {
String sql =request.getSql();
if(StringUtils.hasText(sql)) {
Map<String,String> mapping =request.getSqlParameterValueMap();
String replacedSql = ExpressionReplacer.replace(sql, mapping);
return jdbcTemplate.query(replacedSql, new Object[] {}, new ResultSetExtractor<SqlQueryResult>() {
@Override
public SqlQueryResult extractData(ResultSet rs) throws SQLException, DataAccessException {
return SqlQueryResult.from(rs);
}
});
}
}
return null;
}
} }

4
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/lib/service/impl/IndicatorServiceImpl.java

@ -340,8 +340,6 @@ public class IndicatorServiceImpl extends DaoServiceImpl<IndicatorEntity, String
for(IndicatorEntity indicator : indicators) { for(IndicatorEntity indicator : indicators) {
hints.addParameterName(ExpressionReplacer.placeholder(indicator.getName(),null)); hints.addParameterName(ExpressionReplacer.placeholder(indicator.getName(),null));
if(!ValueType.isBaseType(indicator.getValueType())) { if(!ValueType.isBaseType(indicator.getValueType())) {
//modify by wspsc
//ReleasableDictionaryEntity dictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(indicator.getValueType(), indicator.getValueTypeVersion());
ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicator.getValueType(), indicator.getValueTypeVersion()); ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicator.getValueType(), indicator.getValueTypeVersion());
if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) { if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) {
UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId()); UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId());
@ -420,8 +418,6 @@ public class IndicatorServiceImpl extends DaoServiceImpl<IndicatorEntity, String
result.addCode2Name(ExpressionReplacer.placeholder(indicator.getCode(),null),ExpressionReplacer.placeholder(indicator.getName(),null)); result.addCode2Name(ExpressionReplacer.placeholder(indicator.getCode(),null),ExpressionReplacer.placeholder(indicator.getName(),null));
result.addName2Code(ExpressionReplacer.placeholder(indicator.getName(),null),ExpressionReplacer.placeholder(indicator.getCode(),null)); result.addName2Code(ExpressionReplacer.placeholder(indicator.getName(),null),ExpressionReplacer.placeholder(indicator.getCode(),null));
if(!ValueType.isBaseType(indicator.getValueType())) { if(!ValueType.isBaseType(indicator.getValueType())) {
//modify by wspsc
//ReleasableDictionaryEntity dictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(indicator.getValueType(), indicator.getValueTypeVersion());
ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicator.getValueType(), indicator.getValueTypeVersion()); ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicator.getValueType(), indicator.getValueTypeVersion());
if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) { if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) {
UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId()); UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId());

2
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/model/service/impl/ParameterProcessorServiceImpl.java

@ -144,8 +144,6 @@ public class ParameterProcessorServiceImpl
){ ){
return objectProperties; return objectProperties;
} }
//modify by wspsc
//ReleasableDictionaryEntity releasableDictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(valueType,valueTypeVersion);
ReleasableDictionaryEntity releasableDictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(valueType,valueTypeVersion); ReleasableDictionaryEntity releasableDictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(valueType,valueTypeVersion);
if(releasableDictionaryEntity==null){ if(releasableDictionaryEntity==null){
return objectProperties; return objectProperties;

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

@ -330,8 +330,6 @@ public class ParameterServiceImpl extends DaoServiceImpl<ParameterEntity, String
IndicatorEntity indicatorEntity =indicatorService.getRepository().findByLibCodeAndVersionAndIndicatorCode(indicatorParameterEntity.getLibCode(), indicatorParameterEntity.getLibVersion(),indicatorParameterEntity.getIndicatorCode()); IndicatorEntity indicatorEntity =indicatorService.getRepository().findByLibCodeAndVersionAndIndicatorCode(indicatorParameterEntity.getLibCode(), indicatorParameterEntity.getLibVersion(),indicatorParameterEntity.getIndicatorCode());
if(indicatorEntity!=null) { if(indicatorEntity!=null) {
if(!ValueType.isBaseType(indicatorEntity.getValueType())) { if(!ValueType.isBaseType(indicatorEntity.getValueType())) {
//modify by wspsc
//ReleasableDictionaryEntity dictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(indicatorEntity.getValueType(), indicatorEntity.getValueTypeVersion());
ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicatorEntity.getValueType(), indicatorEntity.getValueTypeVersion()); ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicatorEntity.getValueType(), indicatorEntity.getValueTypeVersion());
if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) { if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) {
UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId()); UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId());
@ -351,8 +349,6 @@ public class ParameterServiceImpl extends DaoServiceImpl<ParameterEntity, String
result.addCode2Name(ExpressionReplacer.placeholder(parameter.getCode(),null),ExpressionReplacer.placeholder(parameter.getName(),null)); result.addCode2Name(ExpressionReplacer.placeholder(parameter.getCode(),null),ExpressionReplacer.placeholder(parameter.getName(),null));
result.addName2Code(ExpressionReplacer.placeholder(parameter.getName(),null),ExpressionReplacer.placeholder(parameter.getCode(),null)); result.addName2Code(ExpressionReplacer.placeholder(parameter.getName(),null),ExpressionReplacer.placeholder(parameter.getCode(),null));
if(!ValueType.isBaseType(parameter.getValueType())) { if(!ValueType.isBaseType(parameter.getValueType())) {
//modify by wspsc
//ReleasableDictionaryEntity dictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(parameter.getValueType(), parameter.getValueTypeVersion());
ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(parameter.getValueType(), parameter.getValueTypeVersion()); ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(parameter.getValueType(), parameter.getValueTypeVersion());
if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) { if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) {
UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId()); UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId());
@ -461,8 +457,6 @@ public class ParameterServiceImpl extends DaoServiceImpl<ParameterEntity, String
){ ){
return Collections.emptyList(); return Collections.emptyList();
} }
//modify by wspsc
//ReleasableDictionaryEntity releasableDictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(valueType,valueTypeVersion);
ReleasableDictionaryEntity releasableDictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(valueType,valueTypeVersion); ReleasableDictionaryEntity releasableDictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(valueType,valueTypeVersion);
if(releasableDictionaryEntity==null){ if(releasableDictionaryEntity==null){
return Collections.emptyList(); return Collections.emptyList();
@ -610,8 +604,6 @@ public class ParameterServiceImpl extends DaoServiceImpl<ParameterEntity, String
IndicatorEntity indicatorEntity =indicatorService.getRepository().findByLibCodeAndVersionAndIndicatorCode(indicatorParameterEntity.getLibCode(), indicatorParameterEntity.getLibVersion(),indicatorParameterEntity.getIndicatorCode()); IndicatorEntity indicatorEntity =indicatorService.getRepository().findByLibCodeAndVersionAndIndicatorCode(indicatorParameterEntity.getLibCode(), indicatorParameterEntity.getLibVersion(),indicatorParameterEntity.getIndicatorCode());
if(indicatorEntity!=null) { if(indicatorEntity!=null) {
if(!ValueType.isBaseType(indicatorEntity.getValueType())) { if(!ValueType.isBaseType(indicatorEntity.getValueType())) {
//modify by wspsc
//ReleasableDictionaryEntity dictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(indicatorEntity.getValueType(), indicatorEntity.getValueTypeVersion());
ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicatorEntity.getValueType(), indicatorEntity.getValueTypeVersion()); ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(indicatorEntity.getValueType(), indicatorEntity.getValueTypeVersion());
if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) { if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) {
UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId()); UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId());
@ -628,8 +620,6 @@ public class ParameterServiceImpl extends DaoServiceImpl<ParameterEntity, String
} }
}else { }else {
if(!ValueType.isBaseType(parameterEntity.getValueType())) { if(!ValueType.isBaseType(parameterEntity.getValueType())) {
//modify by wspsc
//ReleasableDictionaryEntity dictionaryEntity =dictionaryService.getRepository().findReleasableDictionaryByCodeAndVersion(parameterEntity.getValueType(), parameterEntity.getValueTypeVersion());
ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(parameterEntity.getValueType(), parameterEntity.getValueTypeVersion()); ReleasableDictionaryEntity dictionaryEntity =dictionaryService.findReleasableDictionaryByCodeAndVersion(parameterEntity.getValueType(), parameterEntity.getValueTypeVersion());
if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) { if(dictionaryEntity!=null && DictionaryType.UD_JAVA_CLASS.equals(dictionaryEntity.getType())) {
UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId()); UserDefinedJavaClassDictionaryEntity userDefinedJavaClassDictionaryEntity =dictionaryService.getRepository().findUserDefinedJavaClassDictionaryById(dictionaryEntity.getId());

69
io.sc.engine.rule.server/src/main/java/io/sc/engine/rule/server/testcase/service/impl/TestCaseServiceImpl.java

@ -1,7 +1,14 @@
package io.sc.engine.rule.server.testcase.service.impl; package io.sc.engine.rule.server.testcase.service.impl;
import io.sc.engine.rule.client.Executor; import io.sc.engine.rule.client.Executor;
import io.sc.engine.rule.client.runtime.EngineRuntime;
import io.sc.engine.rule.client.runtime.impl.groovy.GroovyScriptEngineService;
import io.sc.engine.rule.client.runtime.impl.groovy.GroovyScriptEngineServiceImpl;
import io.sc.engine.rule.client.runtime.impl.groovy.GroovyScriptExecutor;
import io.sc.engine.rule.client.spring.service.ExecutorFactoryService; import io.sc.engine.rule.client.spring.service.ExecutorFactoryService;
import io.sc.engine.rule.core.code.CodeGenerator;
import io.sc.engine.rule.core.code.SourceCode;
import io.sc.engine.rule.core.code.impl.GroovySourceCodeGenerator;
import io.sc.engine.rule.core.code.impl.support.ParameterResult; 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.code.impl.support.ResourceResult;
import io.sc.engine.rule.core.code.impl.support.ResourceWrapper; import io.sc.engine.rule.core.code.impl.support.ResourceWrapper;
@ -22,6 +29,7 @@ import io.sc.engine.rule.server.model.entity.ModelEntity;
import io.sc.engine.rule.server.model.entity.ParameterEntity; import io.sc.engine.rule.server.model.entity.ParameterEntity;
import io.sc.engine.rule.server.model.entity.ParameterInOptionItemEntity; import io.sc.engine.rule.server.model.entity.ParameterInOptionItemEntity;
import io.sc.engine.rule.server.model.entity.parameter.InOptionParameterEntity; import io.sc.engine.rule.server.model.entity.parameter.InOptionParameterEntity;
import io.sc.engine.rule.server.model.entity.parameter.IndicatorParameterEntity;
import io.sc.engine.rule.server.model.service.ModelService; import io.sc.engine.rule.server.model.service.ModelService;
import io.sc.engine.rule.server.resource.entity.ModelResourceEntity; import io.sc.engine.rule.server.resource.entity.ModelResourceEntity;
import io.sc.engine.rule.server.resource.entity.ReleasableResourceEntity; import io.sc.engine.rule.server.resource.entity.ReleasableResourceEntity;
@ -79,6 +87,7 @@ public class TestCaseServiceImpl extends DaoServiceImpl<TestCaseEntity, String,
@Autowired private LibTestCaseRepository libTestCaseRepository; @Autowired private LibTestCaseRepository libTestCaseRepository;
@Autowired private JdbcTemplate jdbcTemplate; @Autowired private JdbcTemplate jdbcTemplate;
@Autowired private MessageSource messageSource; @Autowired private MessageSource messageSource;
private GroovyScriptEngineService groovyScriptEngineService =new GroovyScriptEngineServiceImpl();
@Override @Override
public Page<TestCaseEntity> findByOwnerId(String ownerId,QueryParameter queryParameter) throws Exception { public Page<TestCaseEntity> findByOwnerId(String ownerId,QueryParameter queryParameter) throws Exception {
@ -278,7 +287,7 @@ public class TestCaseServiceImpl extends DaoServiceImpl<TestCaseEntity, String,
//通过资源ID查询模型(模型和资源是一对一关系) //通过资源ID查询模型(模型和资源是一对一关系)
ModelEntity modelEntity =modelService.findRootModelByResourceId(resourceId); ModelEntity modelEntity =modelService.findRootModelByResourceId(resourceId);
//通过模型所定义的结构构建测试用例参数树(包含所有的输入输出参数) //通过模型所定义的结构构建测试用例参数树(包含所有的输入输出参数)
buildTestCaseParameterTree(wrappers,null,modelEntity); buildTestCaseParameterTree4Excel(wrappers,null,modelEntity);
//抽取输入参数 //抽取输入参数
List<TestCaseParameterWrapper> inputs =new ArrayList<TestCaseParameterWrapper>(); List<TestCaseParameterWrapper> inputs =new ArrayList<TestCaseParameterWrapper>();
@ -458,7 +467,12 @@ public class TestCaseServiceImpl extends DaoServiceImpl<TestCaseEntity, String,
sheet.addValidationData(validation); sheet.addValidationData(validation);
} }
}else{ }else{
cell.setCellValue(messageSource.getMessage(wrapper.getValueType(), null, locale)); try{
String typeName =messageSource.getMessage(wrapper.getValueType(), null, locale);
cell.setCellValue(typeName);
}catch (Exception e) {
cell.setCellValue(wrapper.getValueType());
}
} }
cell.setCellStyle(styleBuilder.clean().align("left").backgroundColor(IndexedColors.GREEN).color(IndexedColors.WHITE).border().build()); cell.setCellStyle(styleBuilder.clean().align("left").backgroundColor(IndexedColors.GREEN).color(IndexedColors.WHITE).border().build());
if(ParameterType.OUT.equals(wrapper.getParameterType())) { if(ParameterType.OUT.equals(wrapper.getParameterType())) {
@ -519,6 +533,8 @@ public class TestCaseServiceImpl extends DaoServiceImpl<TestCaseEntity, String,
cell.setCellStyle(styleBuilder.clean().backgroundColor(IndexedColors.RED).build()); cell.setCellStyle(styleBuilder.clean().backgroundColor(IndexedColors.RED).build());
}else{ }else{
ResourceWrapper resourceWrapper =executor.getLoader().getResourceById(resourceId); ResourceWrapper resourceWrapper =executor.getLoader().getResourceById(resourceId);
SourceCode groovySourceCode =new GroovySourceCodeGenerator().generateSourceCodeById(resourceId,resourceWrapper);
if(resourceWrapper==null){ if(resourceWrapper==null){
Cell cell =row.getCell(1); Cell cell =row.getCell(1);
cell.setCellValue(""); cell.setCellValue("");
@ -593,8 +609,12 @@ public class TestCaseServiceImpl extends DaoServiceImpl<TestCaseEntity, String,
} }
} }
} }
//ResourceResult result =executor.executeById(resourceId,parameters);
ResourceResult result =executor.executeById(resourceId,parameters); Map<String,Object> executeParameter =new HashMap<String,Object>(2);
executeParameter.put("executor", executor);
executeParameter.put("subModelCode", null);
executeParameter.put("argument", parameters);
ResourceResult result =(ResourceResult)groovyScriptEngineService.eval(groovySourceCode.getSource(),"INPUT_PARAMETER",executeParameter);
if(result!=null){ if(result!=null){
for(int i =2;i<names.size();i++) { for(int i =2;i<names.size();i++) {
String name = names.get(i); String name = names.get(i);
@ -905,4 +925,45 @@ public class TestCaseServiceImpl extends DaoServiceImpl<TestCaseEntity, String,
} }
} }
} }
private void buildTestCaseParameterTree4Excel(List<TestCaseParameterWrapper> tree, TestCaseParameterWrapper parentNode, ModelEntity modelEntity) {
if(tree!=null && modelEntity!=null) {
//添加模型
TestCaseParameterWrapper modelNode =modelEntity.toTestCaseParameterWrapper();
modelNode.setParent(parentNode==null?null:parentNode.getId());
tree.add(modelNode);
//添加模型包含的子模型
List<ModelEntity> children =modelEntity.getChildren();
if(children!=null && children.size()>0) {
for(ModelEntity child : children) {
buildTestCaseParameterTree(tree,modelNode,child);
}
}
//添加模型包含的参数
List<ParameterEntity> parameters =modelEntity.getParameters();
if(parameters!=null && parameters.size()>0) {
for(ParameterEntity parameter : parameters) {
TestCaseParameterWrapper wrapper =parameter.toTestCaseParameterWrapper();
wrapper.setParent(modelNode==null?null:modelNode.getId());
if(parameter instanceof InOptionParameterEntity){
InOptionParameterEntity inOptionParameterEntity =(InOptionParameterEntity)parameter;
List<ParameterInOptionItemEntity> optionItemEntities =inOptionParameterEntity.getOptions();
List<Option> options =new ArrayList<>();
if(optionItemEntities!=null && !optionItemEntities.isEmpty()){
for(ParameterInOptionItemEntity optionItemEntity : optionItemEntities){
options.add(new Option(optionItemEntity.getInputValue(),optionItemEntity.getValue(),optionItemEntity.getTitle()));
}
}
wrapper.setOptions(options);
}else if(parameter instanceof IndicatorParameterEntity){
IndicatorParameterEntity indicatorParameterEntity =(IndicatorParameterEntity)parameter;
wrapper.setCode(indicatorParameterEntity.getIndicatorCode());
wrapper.setValueType(indicatorParameterEntity.getValueType());
}
tree.add(wrapper);
}
}
}
}
} }

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

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.272", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

2
io.sc.platform.core.frontend/package.json

@ -1,6 +1,6 @@
{ {
"name": "platform-core", "name": "platform-core",
"version": "8.1.273", "version": "8.1.275",
"description": "前端核心包,用于快速构建前端的脚手架", "description": "前端核心包,用于快速构建前端的脚手架",
"//main": "库的主文件", "//main": "库的主文件",
"main": "dist/platform-core.js", "main": "dist/platform-core.js",

22
io.sc.platform.core.frontend/src/platform/components/expression/WExpression.vue

@ -7,7 +7,7 @@
<math <math
ref="mathEditorRef" ref="mathEditorRef"
display="inline" display="inline"
:class="`p-2 select-none text-${zoom}`" :class="`math p-2 select-none text-${zoom}`"
@contextmenu="contextmenu" @contextmenu="contextmenu"
@mouseover="mouseover" @mouseover="mouseover"
@mouseout="mouseout" @mouseout="mouseout"
@ -19,7 +19,8 @@
</math> </math>
</div> </div>
<ContextMenu ref="contextMenuRef" @changed="contentChanged"></ContextMenu> <ContextMenu ref="contextMenuRef" @changed="contentChanged"></ContextMenu>
<Editor ref="editorRef" @changed="contentChanged"></Editor> <ConstEditor ref="constEditorRef" @changed="contentChanged"></ConstEditor>
<VariableEditor ref="variableEditorRef" :auto-completion="autoCompletion" @changed="contentChanged"></VariableEditor>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -28,7 +29,8 @@ import { ZoomLevels } from '@/platform/components/expression/utils/ZoomLevels';
import { VueTools } from '@/platform'; import { VueTools } from '@/platform';
import Toolbar from './toolbar/Toolbar.vue'; import Toolbar from './toolbar/Toolbar.vue';
import ContextMenu from './context-menu/ContextMenu.vue'; import ContextMenu from './context-menu/ContextMenu.vue';
import Editor from './editor/Editor.vue'; import ConstEditor from './editor/ConstEditor.vue';
import VariableEditor from './editor/VariableEditor.vue';
const props = defineProps({ const props = defineProps({
readOnly: { type: Boolean, default: false }, readOnly: { type: Boolean, default: false },
@ -61,6 +63,10 @@ const props = defineProps({
return false; return false;
}, },
}, },
autoCompletion: {
type: Function,
default: undefined,
},
}); });
const emit = defineEmits(['update:modelValue', 'change']); const emit = defineEmits(['update:modelValue', 'change']);
@ -70,7 +76,8 @@ const zoomModelValueRef = defineModel('zoom', { type: Number, default: ZoomLevel
const mathEditorRef = ref(); const mathEditorRef = ref();
const contextMenuRef = ref(); const contextMenuRef = ref();
const editorRef = ref(); const constEditorRef = ref();
const variableEditorRef = ref();
const selectedElementClass = ''; const selectedElementClass = '';
const selectedElementHighLightClass = 'bg-gray-300'; const selectedElementHighLightClass = 'bg-gray-300';
const mathMsSpaceClass = 'mathMsSpaceClass'; const mathMsSpaceClass = 'mathMsSpaceClass';
@ -127,8 +134,10 @@ const dblclick = (event) => {
return; return;
} }
const tagName = event.target.tagName.toLowerCase(); const tagName = event.target.tagName.toLowerCase();
if (tagName === 'mi' || tagName === 'mo') { if (tagName === 'mi') {
editorRef.value.show(event.srcElement); variableEditorRef.value.open(event.srcElement);
} else if (tagName === 'mn') {
constEditorRef.value.show(event.srcElement);
} }
}; };
@ -203,6 +212,7 @@ const init = () => {
mathEditorRef.value.style.fontSize = font['font-size']; mathEditorRef.value.style.fontSize = font['font-size'];
mathEditorRef.value.style.lineHeight = font['line-height']; mathEditorRef.value.style.lineHeight = font['line-height'];
mathEditorRef.value.innerHTML = modelValueRef.value || '<mspace></mspace>'; mathEditorRef.value.innerHTML = modelValueRef.value || '<mspace></mspace>';
refresh();
}; };
const getElementLevel = (element): number => { const getElementLevel = (element): number => {

0
io.sc.platform.core.frontend/src/platform/components/expression/editor/Editor.vue → io.sc.platform.core.frontend/src/platform/components/expression/editor/ConstEditor.vue

58
io.sc.platform.core.frontend/src/platform/components/expression/editor/VariableEditor.vue

@ -0,0 +1,58 @@
<template>
<w-dialog
ref="dialogRef"
width="900px"
:can-maximize="false"
:buttons="[
{
label: $t('confirm'),
noCaps: true,
click: () => {
targetElementRef.innerHTML = modelValueRef;
close();
},
},
]"
>
<w-code-mirror
v-model="modelValueRef"
lang="java"
:rows="2"
:placeholder="true"
:line-wrap="true"
:line-break="false"
:auto-completion="autoCompletion"
@confirm="blur"
@cancel="cancel"
></w-code-mirror>
</w-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const props = defineProps({
autoCompletion: {
type: Function,
default: undefined,
},
});
const dialogRef = ref();
const targetElementRef = ref();
const modelValueRef = ref();
const open = (element) => {
targetElementRef.value = element;
modelValueRef.value = element.innerHTML;
dialogRef.value.show();
};
const close = () => {
dialogRef.value.hide();
};
defineExpose({
open,
close,
});
</script>

7
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/Toolbar.vue

@ -1,5 +1,6 @@
<template> <template>
<q-toolbar style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px"> <q-toolbar style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px">
<input style="width: 0px" /><!--采用宽度为0的输入框,避免第一按钮默认获得焦点-->
<template v-if="!sourceCodeEditor"> <template v-if="!sourceCodeEditor">
<!-- 操作 --> <!-- 操作 -->
<Xml v-model="modelValueRef"></Xml> <Xml v-model="modelValueRef"></Xml>
@ -15,6 +16,7 @@
<!-- 基本 --> <!-- 基本 -->
<Variable v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Variable> <Variable v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Variable>
<Const v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Const>
<Addition v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Addition> <Addition v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Addition>
<Subtraction v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Subtraction> <Subtraction v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Subtraction>
<Multiply v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Multiply> <Multiply v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Multiply>
@ -66,7 +68,7 @@
<q-item-section><Sqrt v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Sqrt></q-item-section> <q-item-section><Sqrt v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Sqrt></q-item-section>
</q-item> </q-item>
<q-item v-close-popup clickable> <q-item v-close-popup clickable>
<q-item-section><Extracting v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Extracting></q-item-section> <q-item-section><Root v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Root></q-item-section>
</q-item> </q-item>
<q-separator inset spaced /> <q-separator inset spaced />
<q-item v-close-popup clickable> <q-item v-close-popup clickable>
@ -123,6 +125,7 @@ import ZoomOut from './actions/ZoomOut.vue';
import Undo from './actions/Undo.vue'; import Undo from './actions/Undo.vue';
import Redo from './actions/Redo.vue'; import Redo from './actions/Redo.vue';
import Const from './base/Const.vue';
import Variable from './base/Variable.vue'; import Variable from './base/Variable.vue';
import Addition from './base/Addition.vue'; import Addition from './base/Addition.vue';
import Subtraction from './base/Subtraction.vue'; import Subtraction from './base/Subtraction.vue';
@ -144,7 +147,7 @@ import Le from './base/Le.vue';
import Comma from './base/Comma.vue'; import Comma from './base/Comma.vue';
import E from './math/E.vue'; import E from './math/E.vue';
import Extracting from './math/Extracting.vue'; import Root from './math/Root.vue';
import Lg from './math/Lg.vue'; import Lg from './math/Lg.vue';
import Ln from './math/Ln.vue'; import Ln from './math/Ln.vue';
import Log from './math/Log.vue'; import Log from './math/Log.vue';

4
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Comma.vue

@ -1,14 +1,14 @@
<template> <template>
<q-btn :title="$t('math.toolbar.base.comma')" stretch flat size="16px" padding="0px 6px" draggable="true" @dragstart="dragstart" @click="append"> <q-btn :title="$t('math.toolbar.base.comma')" stretch flat size="16px" padding="0px 6px" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<mi>,</mi> <mo>,</mo>
</math> </math>
</q-btn> </q-btn>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<mi>,</mi> <mo>,</mo>
<mspace></mspace> <mspace></mspace>
`; `;

16
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Extracting.vue → io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Const.vue

@ -1,20 +1,14 @@
<template> <template>
<div v-close-popup :title="$t('math.toolbar.math.extracting')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append"> <q-btn :title="$t('math.toolbar.base.const')" stretch flat size="16px" padding="0px 10px" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<mroot> <mn>c</mn>
<mrow><mi>x</mi></mrow>
<mrow><mi>y</mi></mrow>
</mroot>
</math> </math>
</div> </q-btn>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<mroot> <mn>c</mn>
<mrow><mi>x</mi></mrow>
<mrow><mi>y</mi></mrow>
</mroot>
<mspace></mspace> <mspace></mspace>
`; `;
@ -29,7 +23,7 @@ const dragstart = (event) => {
}; };
const append = () => { const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('power(x,1/y)')); props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('${x}'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', ''); modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
}; };
</script> </script>

12
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Division.vue

@ -2,8 +2,16 @@
<q-btn :title="$t('math.toolbar.base.division')" stretch flat size="16px" padding="0px 10px" draggable="true" @dragstart="dragstart" @click="append"> <q-btn :title="$t('math.toolbar.base.division')" stretch flat size="16px" padding="0px 10px" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<mfrac> <mfrac>
<mi>x</mi> <mrow>
<mi>y</mi> <mspace></mspace>
<mi>x</mi>
<mspace></mspace>
</mrow>
<mrow>
<mspace></mspace>
<mi>y</mi>
<mspace></mspace>
</mrow>
</mfrac> </mfrac>
</math> </math>
</q-btn> </q-btn>

2
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/LeftParenthesis.vue

@ -1,7 +1,7 @@
<template> <template>
<q-btn :title="$t('math.toolbar.base.leftParenthesis')" stretch flat size="16px" padding="0px 10px" draggable="true" @dragstart="dragstart" @click="append"> <q-btn :title="$t('math.toolbar.base.leftParenthesis')" stretch flat size="16px" padding="0px 10px" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<mi>(</mi> <mo>(</mo>
</math> </math>
</q-btn> </q-btn>
</template> </template>

2
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/RightParenthesis.vue

@ -1,7 +1,7 @@
<template> <template>
<q-btn :title="$t('math.toolbar.base.rightParenthesis')" stretch flat size="16px" padding="0px 10px" draggable="true" @dragstart="dragstart" @click="append"> <q-btn :title="$t('math.toolbar.base.rightParenthesis')" stretch flat size="16px" padding="0px 10px" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<mi>)</mi> <mo>)</mo>
</math> </math>
</q-btn> </q-btn>
</template> </template>

2
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/base/Variable.vue

@ -8,7 +8,7 @@
<script setup lang="ts"> <script setup lang="ts">
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<mi title="xxx">x</mi> <mi>x</mi>
<mspace></mspace> <mspace></mspace>
`; `;

54
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/SpecialValue.vue

@ -8,6 +8,47 @@
</q-item-section> </q-item-section>
<q-menu anchor="top end" self="top start"> <q-menu anchor="top end" self="top start">
<q-list dense> <q-list dense>
<q-item
v-close-popup
clickable
:title="$t('math.toolbar.functions.specialValue.isNil')"
draggable="true"
@dragstart="isNilRef?.dragstart"
@click="isNilRef?.append"
>
<q-item-section><IsNil ref="isNilRef" v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></IsNil></q-item-section>
</q-item>
<q-item
v-close-popup
clickable
:title="$t('math.toolbar.functions.specialValue.isZero')"
draggable="true"
@dragstart="isZeroRef?.dragstart"
@click="isZeroRef?.append"
>
<q-item-section><IsZero ref="isZeroRef" v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></IsZero></q-item-section>
</q-item>
<q-item
v-close-popup
clickable
:title="$t('math.toolbar.functions.specialValue.isNan')"
draggable="true"
@dragstart="isNanRef?.dragstart"
@click="isNanRef?.append"
>
<q-item-section><IsNan ref="isNanRef" v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></IsNan></q-item-section>
</q-item>
<q-item
v-close-popup
clickable
:title="$t('math.toolbar.functions.specialValue.isInfinite')"
draggable="true"
@dragstart="isInfiniteRef?.dragstart"
@click="isInfiniteRef?.append"
>
<q-item-section><IsInfinite ref="isInfiniteRef" v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></IsInfinite></q-item-section>
</q-item>
<q-separator inset spaced />
<q-item <q-item
v-close-popup v-close-popup
clickable clickable
@ -36,7 +77,7 @@
@dragstart="nanRef?.dragstart" @dragstart="nanRef?.dragstart"
@click="nanRef?.append" @click="nanRef?.append"
> >
<q-item-section><NaN ref="nanRef" v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></NaN></q-item-section> <q-item-section><Nan ref="nanRef" v-model="modelValueRef" :source-code-editor="sourceCodeEditor"></Nan></q-item-section>
</q-item> </q-item>
<q-item <q-item
v-close-popup v-close-popup
@ -54,9 +95,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import IsNil from './specialValue/IsNil.vue';
import IsZero from './specialValue/IsZero.vue';
import IsNan from './specialValue/IsNan.vue';
import IsInfinite from './specialValue/IsInfinite.vue';
import Nil from './specialValue/Nil.vue'; import Nil from './specialValue/Nil.vue';
import Zero from './specialValue/Zero.vue'; import Zero from './specialValue/Zero.vue';
import NaN from './specialValue/NaN.vue'; import Nan from './specialValue/Nan.vue';
import Infinite from './specialValue/Infinite.vue'; import Infinite from './specialValue/Infinite.vue';
const modelValueRef = defineModel({ type: String, default: '' }); const modelValueRef = defineModel({ type: String, default: '' });
@ -64,6 +109,11 @@ const props = defineProps({
sourceCodeEditor: { type: Object, default: undefined }, sourceCodeEditor: { type: Object, default: undefined },
}); });
const isNilRef = ref();
const isZeroRef = ref();
const isNanRef = ref();
const isInfiniteRef = ref();
const nilRef = ref(); const nilRef = ref();
const zeroRef = ref(); const zeroRef = ref();
const nanRef = ref(); const nanRef = ref();

12
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/number/Abs.vue

@ -3,9 +3,12 @@
<math display="inline"> <math display="inline">
<mspace></mspace> <mspace></mspace>
<mrow> <mrow>
<mi>|</mi> <mo>abs</mo>
<mi>(</mi>
<mspace></mspace>
<mi>x</mi> <mi>x</mi>
<mi>|</mi> <mspace></mspace>
<mi>)</mi>
</mrow> </mrow>
<mspace></mspace> <mspace></mspace>
</math> </math>
@ -15,11 +18,12 @@
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<mrow> <mrow>
<mi>|</mi> <mo>abs</mo>
<mi>(</mi>
<mspace></mspace> <mspace></mspace>
<mi>x</mi> <mi>x</mi>
<mspace></mspace> <mspace></mspace>
<mi>|</mi> <mi>)</mi>
</mrow> </mrow>
<mspace></mspace> <mspace></mspace>
`; `;

46
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsInfinite.vue

@ -0,0 +1,46 @@
<template>
<span>
<math display="inline">
<mrow>
<mo>isInfinite</mo>
<mi>(</mi>
<mi>x</mi>
<mi>)</mi>
</mrow>
</math>
</span>
</template>
<script setup lang="ts">
const xmlData = `
<mspace></mspace>
<mrow>
<mo>isInfinite</mo>
<mi>(</mi>
<mspace></mspace>
<mi>x</mi>
<mspace></mspace>
<mi>)</mi>
</mrow>
<mspace></mspace>
`;
const modelValueRef = defineModel({ type: String, default: '' });
const props = defineProps({
sourceCodeEditor: { type: Object, default: undefined },
});
const dragstart = (event) => {
event.dataTransfer.setData('math', xmlData);
event.dataTransfer.setDragImage(event.srcElement, 0, 0);
};
const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('isInfinite(x)'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
};
defineExpose({
dragstart,
append,
});
</script>

46
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsNaN.vue

@ -0,0 +1,46 @@
<template>
<span>
<math display="isNan">
<mrow>
<mo>isNan</mo>
<mi>(</mi>
<mi>x</mi>
<mi>)</mi>
</mrow>
</math>
</span>
</template>
<script setup lang="ts">
const xmlData = `
<mspace></mspace>
<mrow>
<mo>isNan</mo>
<mi>(</mi>
<mspace></mspace>
<mi>x</mi>
<mspace></mspace>
<mi>)</mi>
</mrow>
<mspace></mspace>
`;
const modelValueRef = defineModel({ type: String, default: '' });
const props = defineProps({
sourceCodeEditor: { type: Object, default: undefined },
});
const dragstart = (event) => {
event.dataTransfer.setData('math', xmlData);
event.dataTransfer.setDragImage(event.srcElement, 0, 0);
};
const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('isNan(x)'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
};
defineExpose({
dragstart,
append,
});
</script>

46
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsNil.vue

@ -0,0 +1,46 @@
<template>
<span>
<math display="inline">
<mrow>
<mo>isNil</mo>
<mi>(</mi>
<mi>x</mi>
<mi>)</mi>
</mrow>
</math>
</span>
</template>
<script setup lang="ts">
const xmlData = `
<mspace></mspace>
<mrow>
<mo>isNil</mo>
<mi>(</mi>
<mspace></mspace>
<mi>x</mi>
<mspace></mspace>
<mi>)</mi>
</mrow>
<mspace></mspace>
`;
const modelValueRef = defineModel({ type: String, default: '' });
const props = defineProps({
sourceCodeEditor: { type: Object, default: undefined },
});
const dragstart = (event) => {
event.dataTransfer.setData('math', xmlData);
event.dataTransfer.setDragImage(event.srcElement, 0, 0);
};
const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('isNil(x)'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
};
defineExpose({
dragstart,
append,
});
</script>

46
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/specialValue/IsZero.vue

@ -0,0 +1,46 @@
<template>
<span>
<math display="inline">
<mrow>
<mo>isZero</mo>
<mi>(</mi>
<mi>x</mi>
<mi>)</mi>
</mrow>
</math>
</span>
</template>
<script setup lang="ts">
const xmlData = `
<mspace></mspace>
<mrow>
<mo>isZero</mo>
<mi>(</mi>
<mspace></mspace>
<mi>x</mi>
<mspace></mspace>
<mi>)</mi>
</mrow>
<mspace></mspace>
`;
const modelValueRef = defineModel({ type: String, default: '' });
const props = defineProps({
sourceCodeEditor: { type: Object, default: undefined },
});
const dragstart = (event) => {
event.dataTransfer.setData('math', xmlData);
event.dataTransfer.setDragImage(event.srcElement, 0, 0);
};
const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('isZero(x)'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
};
defineExpose({
dragstart,
append,
});
</script>

2
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/trigonometric/hyperbolic/Csch.vue

@ -35,7 +35,7 @@ const dragstart = (event) => {
}; };
const append = () => { const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('csch')); props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('csch(x)'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', ''); modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
}; };

2
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/functions/trigonometric/hyperbolic/Sech.vue

@ -35,7 +35,7 @@ const dragstart = (event) => {
}; };
const append = () => { const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('sech')); props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('sech(x)'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', ''); modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
}; };

8
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Exp.vue

@ -2,8 +2,8 @@
<div v-close-popup :title="$t('math.toolbar.math.exp')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append"> <div v-close-popup :title="$t('math.toolbar.math.exp')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<msup> <msup>
<mi>e</mi> <mrow><mspace></mspace><mi>e</mi><mspace></mspace></mrow>
<mi>x</mi> <mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
</msup> </msup>
</math> </math>
</div> </div>
@ -12,8 +12,8 @@
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<msup> <msup>
<mi>e</mi> <mrow><mspace></mspace><mi>e</mi><mspace></mspace></mrow>
<mi>x</mi> <mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
</msup> </msup>
<mspace></mspace> <mspace></mspace>
`; `;

8
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Power.vue

@ -2,8 +2,8 @@
<div v-close-popup :title="$t('math.toolbar.math.power')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append"> <div v-close-popup :title="$t('math.toolbar.math.power')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<msup> <msup>
<mi>x</mi> <mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
<mi>y</mi> <mrow><mspace></mspace><mi>y</mi><mspace></mspace></mrow>
</msup> </msup>
</math> </math>
</div> </div>
@ -12,8 +12,8 @@
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<msup> <msup>
<mi>x</mi> <mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
<mi>y</mi> <mrow><mspace></mspace><mi>y</mi><mspace></mspace></mrow>
</msup> </msup>
<mspace></mspace> <mspace></mspace>
`; `;

8
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Power2.vue

@ -2,8 +2,8 @@
<div v-close-popup :title="$t('math.toolbar.math.power2')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append"> <div v-close-popup :title="$t('math.toolbar.math.power2')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<msup> <msup>
<mi>x</mi> <mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
<mi>2</mi> <mrow><mi>2</mi></mrow>
</msup> </msup>
</math> </math>
</div> </div>
@ -12,8 +12,8 @@
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<msup> <msup>
<mi>x</mi> <mrow><mi>x</mi></mrow>
<mi>2</mi> <mrow><mi>2</mi></mrow>
</msup> </msup>
<mspace></mspace> <mspace></mspace>
`; `;

35
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Root.vue

@ -0,0 +1,35 @@
<template>
<div v-close-popup :title="$t('math.toolbar.math.root')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline">
<mroot>
<mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
<mrow><mspace></mspace><mi>y</mi><mspace></mspace></mrow>
</mroot>
</math>
</div>
</template>
<script setup lang="ts">
const xmlData = `
<mspace></mspace>
<mroot>
<mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
<mrow><mspace></mspace><mi>y</mi><mspace></mspace></mrow>
</mroot>
<mspace></mspace>
`;
const modelValueRef = defineModel({ type: String, default: '' });
const props = defineProps({
sourceCodeEditor: { type: Object, default: undefined },
});
const dragstart = (event) => {
event.dataTransfer.setData('math', xmlData);
event.dataTransfer.setDragImage(event.srcElement, 0, 0);
};
const append = () => {
props.sourceCodeEditor?.dispatch(props.sourceCodeEditor?.state?.replaceSelection('root(x,y)'));
modelValueRef.value = modelValueRef.value + xmlData.replace('<mspace></mspace>', '');
};
</script>

14
io.sc.platform.core.frontend/src/platform/components/expression/toolbar/math/Sqrt.vue

@ -1,20 +1,18 @@
<template> <template>
<div v-close-popup :title="$t('math.toolbar.math.sqrt')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append"> <div v-close-popup :title="$t('math.toolbar.math.sqrt')" class="text-xl" draggable="true" @dragstart="dragstart" @click="append">
<math display="inline"> <math display="inline">
<mroot> <msqrt>
<mrow><mi>x</mi></mrow> <mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
<mrow><mi></mi></mrow> </msqrt>
</mroot>
</math> </math>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const xmlData = ` const xmlData = `
<mspace></mspace> <mspace></mspace>
<mroot> <msqrt>
<mrow><mi>x</mi></mrow> <mrow><mspace></mspace><mi>x</mi><mspace></mspace></mrow>
<mrow><mi></mi></mrow> </msqrt>
</mroot>
<mspace></mspace> <mspace></mspace>
`; `;

8
io.sc.platform.core.frontend/src/platform/components/form/elements/WCodeMirror.vue

@ -108,6 +108,10 @@ const props = defineProps({
type: Function, type: Function,
default: undefined, default: undefined,
}, },
activateOnCompletion: {
type: Function,
default: undefined,
},
// //
autoCompletionOptions: { autoCompletionOptions: {
type: Array, type: Array,
@ -270,7 +274,9 @@ if (props.lineNumber) {
if (props.autoCompletion) { if (props.autoCompletion) {
// //
basicSetup.push(autocomplete.closeBrackets()); basicSetup.push(autocomplete.closeBrackets());
basicSetup.push(autocomplete.autocompletion({ override: [props.autoCompletion], maxRenderedOptions: 1000 })); basicSetup.push(
autocomplete.autocompletion({ override: [props.autoCompletion], activateOnCompletion: props.activateOnCompletion, maxRenderedOptions: 1000 }),
);
} }
if (props.placeholder) { if (props.placeholder) {
// //

11
io.sc.platform.core.frontend/src/platform/i18n/messages.json

@ -159,6 +159,7 @@
"math.toolbar.actions.redo": "Redo", "math.toolbar.actions.redo": "Redo",
"math.toolbar.base.variable": "Variable", "math.toolbar.base.variable": "Variable",
"math.toolbar.base.const": "Const",
"math.toolbar.base.addition": "Addition", "math.toolbar.base.addition": "Addition",
"math.toolbar.base.subtraction": "Subtraction", "math.toolbar.base.subtraction": "Subtraction",
"math.toolbar.base.multiply": "Multiply", "math.toolbar.base.multiply": "Multiply",
@ -183,7 +184,7 @@
"math.toolbar.math.power2": "value of the x raised to the power of the 2", "math.toolbar.math.power2": "value of the x raised to the power of the 2",
"math.toolbar.math.exp": "e raised to the power of x", "math.toolbar.math.exp": "e raised to the power of x",
"math.toolbar.math.sqrt": "square root of x", "math.toolbar.math.sqrt": "square root of x",
"math.toolbar.math.extracting": "y root of x", "math.toolbar.math.root": "y root of x",
"math.toolbar.math.lg": "base 10 logarithm of x", "math.toolbar.math.lg": "base 10 logarithm of x",
"math.toolbar.math.ln": "base e logarithm of x", "math.toolbar.math.ln": "base e logarithm of x",
"math.toolbar.math.log": "base y logarithm of x", "math.toolbar.math.log": "base y logarithm of x",
@ -192,10 +193,14 @@
"math.toolbar.functions": "Function", "math.toolbar.functions": "Function",
"math.toolbar.functions.specialValue": "Special Value", "math.toolbar.functions.specialValue": "Special Value",
"math.toolbar.functions.specialValue.isNil": "x is null or empty?",
"math.toolbar.functions.specialValue.isZero": "x is 0?",
"math.toolbar.functions.specialValue.isNan": "x is not a number?",
"math.toolbar.functions.specialValue.isInfinite": "x is infinite?",
"math.toolbar.functions.specialValue.nil": "Empty, when x is null or empty, return y; else return x", "math.toolbar.functions.specialValue.nil": "Empty, when x is null or empty, return y; else return x",
"math.toolbar.functions.specialValue.zero": "Zero, when x is 0, return y; else return x", "math.toolbar.functions.specialValue.zero": "Zero, when x is 0, return y; else return x",
"math.toolbar.functions.specialValue.nan": "NaN, when x is NaN, return y; else return x", "math.toolbar.functions.specialValue.nan": "Not number, when x is not a number, return y; else return x",
"math.toolbar.functions.specialValue.infinite": "Infinite, when x is Infinite, return y; else return x", "math.toolbar.functions.specialValue.infinite": "Infinite, when x is infinite, return y; else return x",
"math.toolbar.functions.number": "Number", "math.toolbar.functions.number": "Number",
"math.toolbar.functions.number.abs": "Absolute value", "math.toolbar.functions.number.abs": "Absolute value",
"math.toolbar.functions.number.max": "Maximum", "math.toolbar.functions.number.max": "Maximum",

7
io.sc.platform.core.frontend/src/platform/i18n/messages_tw_CN.json

@ -159,6 +159,7 @@
"math.toolbar.actions.redo": "重做", "math.toolbar.actions.redo": "重做",
"math.toolbar.base.variable": "變量", "math.toolbar.base.variable": "變量",
"math.toolbar.base.const": "常量",
"math.toolbar.base.addition": "加法", "math.toolbar.base.addition": "加法",
"math.toolbar.base.subtraction": "減法", "math.toolbar.base.subtraction": "減法",
"math.toolbar.base.multiply": "乘法", "math.toolbar.base.multiply": "乘法",
@ -183,7 +184,7 @@
"math.toolbar.math.power2": "x 的平方", "math.toolbar.math.power2": "x 的平方",
"math.toolbar.math.exp": "自然對數 e 的 x 次方", "math.toolbar.math.exp": "自然對數 e 的 x 次方",
"math.toolbar.math.sqrt": "x 的開平方", "math.toolbar.math.sqrt": "x 的開平方",
"math.toolbar.math.extracting": "x 開 y 次方", "math.toolbar.math.root": "x 開 y 次方",
"math.toolbar.math.lg": "以 10 為底的對數", "math.toolbar.math.lg": "以 10 為底的對數",
"math.toolbar.math.ln": "以自然對數 e 為底的對數", "math.toolbar.math.ln": "以自然對數 e 為底的對數",
"math.toolbar.math.log": "以 y 為底的對數", "math.toolbar.math.log": "以 y 為底的對數",
@ -192,6 +193,10 @@
"math.toolbar.functions": "函數", "math.toolbar.functions": "函數",
"math.toolbar.functions.specialValue": "特殊值處理函數", "math.toolbar.functions.specialValue": "特殊值處理函數",
"math.toolbar.functions.specialValue.isNil": "判斷 x 是否為 null 或者空字符串?",
"math.toolbar.functions.specialValue.isZero": "判斷 x 是否為零?",
"math.toolbar.functions.specialValue.isNan": "判斷 x 是否為非數字?",
"math.toolbar.functions.specialValue.isInfinite": "判斷 x 是否為無窮?",
"math.toolbar.functions.specialValue.nil": "空值處理, 當 x 為 null 或者空字符串時, 返回 y; 否則返回 x", "math.toolbar.functions.specialValue.nil": "空值處理, 當 x 為 null 或者空字符串時, 返回 y; 否則返回 x",
"math.toolbar.functions.specialValue.zero": "零值處理, 當 x 為 0 時, 返回 y; 否則返回 x", "math.toolbar.functions.specialValue.zero": "零值處理, 當 x 為 0 時, 返回 y; 否則返回 x",
"math.toolbar.functions.specialValue.nan": "非數字處理, 當 x 為非數字時, 返回 y; 否則返回 x", "math.toolbar.functions.specialValue.nan": "非數字處理, 當 x 為非數字時, 返回 y; 否則返回 x",

7
io.sc.platform.core.frontend/src/platform/i18n/messages_zh_CN.json

@ -159,6 +159,7 @@
"math.toolbar.actions.redo": "重做", "math.toolbar.actions.redo": "重做",
"math.toolbar.base.variable": "变量", "math.toolbar.base.variable": "变量",
"math.toolbar.base.const": "常量",
"math.toolbar.base.addition": "加法", "math.toolbar.base.addition": "加法",
"math.toolbar.base.subtraction": "减法", "math.toolbar.base.subtraction": "减法",
"math.toolbar.base.multiply": "乘法", "math.toolbar.base.multiply": "乘法",
@ -183,7 +184,7 @@
"math.toolbar.math.power2": "x 的平方", "math.toolbar.math.power2": "x 的平方",
"math.toolbar.math.exp": "自然对数 e 的 x 次方", "math.toolbar.math.exp": "自然对数 e 的 x 次方",
"math.toolbar.math.sqrt": "x 的开平方", "math.toolbar.math.sqrt": "x 的开平方",
"math.toolbar.math.extracting": "x 开 y 次方", "math.toolbar.math.root": "x 开 y 次方",
"math.toolbar.math.lg": "以 10 为底的对数", "math.toolbar.math.lg": "以 10 为底的对数",
"math.toolbar.math.ln": "以自然对数 e 为底的对数", "math.toolbar.math.ln": "以自然对数 e 为底的对数",
"math.toolbar.math.log": "以 y 为底的对数", "math.toolbar.math.log": "以 y 为底的对数",
@ -192,6 +193,10 @@
"math.toolbar.functions": "函数", "math.toolbar.functions": "函数",
"math.toolbar.functions.specialValue": "特殊值处理函数", "math.toolbar.functions.specialValue": "特殊值处理函数",
"math.toolbar.functions.specialValue.isNil": "判断 x 是否为 null 或者空字符串?",
"math.toolbar.functions.specialValue.isZero": "判断 x 是否为零?",
"math.toolbar.functions.specialValue.isNan": "判断 x 是否为非数字?",
"math.toolbar.functions.specialValue.isInfinite": "判断 x 是否为无穷?",
"math.toolbar.functions.specialValue.nil": "空值处理, 当 x 为 null 或者空字符串时, 返回 y; 否则返回 x", "math.toolbar.functions.specialValue.nil": "空值处理, 当 x 为 null 或者空字符串时, 返回 y; 否则返回 x",
"math.toolbar.functions.specialValue.zero": "零值处理, 当 x 为 0 时, 返回 y; 否则返回 x", "math.toolbar.functions.specialValue.zero": "零值处理, 当 x 为 0 时, 返回 y; 否则返回 x",
"math.toolbar.functions.specialValue.nan": "非数字处理, 当 x 为非数字时, 返回 y; 否则返回 x", "math.toolbar.functions.specialValue.nan": "非数字处理, 当 x 为非数字时, 返回 y; 否则返回 x",

114
io.sc.platform.core.frontend/src/platform/layout/sub-layout/ChangePasswordDialog.vue

@ -2,74 +2,84 @@
<w-dialog <w-dialog
ref="changePasswordDialogRef" ref="changePasswordDialogRef"
width="500px" width="500px"
height="300px"
:title="$t('changePassword')" :title="$t('changePassword')"
:can-maximize="false" :can-maximize="false"
:buttons="[ :buttons="[
{ {
label: $t('submit'), label: $t('submit'),
noCaps: true, noCaps: true,
click: changePassword, click: () => {
changePasswordFormRef.validate().then((result) => {
if (result) {
noErrorAxios
.post(Environment.apiContextPath('/api/system/user/changePassword'), changePasswordFormRef.getData())
.then(() => {
close();
NotifyManager.success();
})
.catch((error) => {
const response = error?.response;
const status = response?.status;
const data = response?.data;
if (data?.code === 1001) {
//
if (error.response.data.data) {
changePasswordFormRef.setValidationErrors(error.response.data.data);
}
} else {
//
if (status === 500) {
NotifyManager.error($t(data?.errorMessageI18nKey));
} else {
NotifyManager.error($t(status));
}
}
});
}
});
},
}, },
]" ]"
> >
<w-form ref="changePasswordFormRef" :cols-num="1" :fields="computedFormFields" class="p-2"></w-form> <w-form
ref="changePasswordFormRef"
:cols-num="1"
class="p-2"
:fields="[
{
name: 'rawPassword',
label: $t('rawPassword'),
type: 'password',
required: true,
},
{
name: 'newPassword',
label: $t('newPassword'),
type: 'password',
required: true,
},
{
name: 'confirmNewPassword',
label: $t('confirmNewPassword'),
type: 'password',
required: true,
rules: [
(value) => {
return changePasswordFormRef.getData().newPassword != value ? $t('passwordAndConfirmPasswordMustEqual') : true;
},
],
},
]"
></w-form>
</w-dialog> </w-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from 'vue'; import { ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { PConst, Environment, noErrorAxios, NotifyManager } from '@/platform';
import { PConst, Environment, axios, NotifyManager } from '@/platform';
const { t } = useI18n();
const changePasswordDialogRef = ref(); const changePasswordDialogRef = ref();
const changePasswordFormRef = ref(); const changePasswordFormRef = ref();
const computedFormFields = computed(() => {
return [
{
name: 'rawPassword',
label: t('rawPassword'),
type: 'password',
required: true,
},
{
name: 'newPassword',
label: t('newPassword'),
type: 'password',
required: true,
},
{
name: 'confirmNewPassword',
label: t('confirmNewPassword'),
type: 'password',
required: true,
rules: [
(value) => {
return changePasswordFormRef.value.data.newPassword != value ? t('passwordAndConfirmPasswordMustEqual') : true;
},
],
},
];
});
const changePassword = async () => {
const result = await changePasswordFormRef.value.validate();
if (result) {
axios
.post(Environment.apiContextPath('/api/system/user/changePassword'), changePasswordFormRef.value.getData())
.then(() => {
close();
NotifyManager.success();
})
.catch((error) => {
if (error.code === PConst.REQUEST_PARAMETER_VALIDATE_ERROR_CODE) {
changePasswordFormRef.value.setValidationErrors(error.data);
}
});
}
};
const open = () => { const open = () => {
changePasswordDialogRef.value.show(); changePasswordDialogRef.value.show();
}; };

17
io.sc.platform.core.frontend/src/views/testcase/code-mirror/AutoCompletionManager.ts

@ -112,7 +112,12 @@ class AutoCompletionManager {
if (parameterType.properties && parameterType.properties.length > 0) { if (parameterType.properties && parameterType.properties.length > 0) {
const options = []; const options = [];
for (const property of parameterType.properties) { for (const property of parameterType.properties) {
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', detail: this.findValueTypeInfo(property.valueType) }); options.push({
label: property.name,
type: 'property',
apply: '${' + property.name + '}',
detail: this.findValueTypeInfo(property.valueType),
});
} }
return options; return options;
} }
@ -122,7 +127,10 @@ class AutoCompletionManager {
return { return {
from: to, from: to,
options: this.getParameterOptions(), options: this.getParameterOptions(),
validFor: /(.*)?/, //validFor: /(.*)?/,
validFor: (text, from, to, state) => {
console.log(text);
},
}; };
} }
@ -145,7 +153,10 @@ class AutoCompletionManager {
return { return {
from: to, from: to,
options: options, options: options,
validFor: /^(.*)?$/, //validFor: /(.*)?/,
validFor: (text, from, to, state) => {
console.log(text, from, to, state);
},
}; };
} }

190
io.sc.platform.core.frontend/src/views/testcase/code-mirror/AutoCompletionManager2.ts

@ -0,0 +1,190 @@
import { Tools } from '@/platform';
class AutoCompletionManager2 {
parameters: object[];
valueTypes: object[];
public setParameters(parameters) {
this.parameters = parameters;
}
public setValueTypes(valueTypes) {
this.valueTypes = valueTypes;
}
public getOptions(path: string): any {
if (!path) {
return this.getParameterOptions();
}
if (path.endsWith('.')) {
path = path.substring(0, path.length - 1);
}
const names = path.split('.');
if (!names) {
return this.getParameterOptions();
}
//参数
const parameter = this.findParmeter(names[0]);
if (!parameter) {
return null;
}
const valueTypeString = parameter.valueType;
const valueTypeVersion = parameter.valueTypeVersion;
let valueType = this.findValueType(valueTypeString, valueTypeVersion);
if (!valueType || !valueType.properties || valueType.properties.length <= 0) {
return null;
}
let index = 1;
let lastNameIsNotCompleted = false;
while (index < names.length) {
const _valueType = this.findValueTypeByProperty(valueType.code, valueType.version, names[index]);
if (_valueType) {
valueType = _valueType;
} else {
lastNameIsNotCompleted = true;
}
index++;
}
const options = [];
if (lastNameIsNotCompleted) {
for (const property of valueType.properties) {
if (property.name.indexOf(names[names.length - 1]) != -1) {
const propertyValueType = this.findValueType(property.valueType, property.valueTypeVersion);
if (!propertyValueType) {
continue;
}
const info = propertyValueType.version ? propertyValueType.name + '(V' + propertyValueType.version + ')' : propertyValueType.name;
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', info: info });
}
}
return options;
} else {
for (const property of valueType.properties) {
const propertyValueType = this.findValueType(property.valueType, property.valueTypeVersion);
if (!propertyValueType) {
continue;
}
const info = propertyValueType.version ? propertyValueType.name + '(V' + propertyValueType.version + ')' : propertyValueType.name;
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', info: info });
}
return options;
}
}
public findParmeter(parameterName) {
for (const parameter of this.parameters) {
if (parameter.name === parameterName) {
return parameter;
}
}
return null;
}
public findValueType(valueTypeString, valueTypeVersion) {
for (const valueType of this.valueTypes) {
if (valueType.code === valueTypeString && valueType.version === valueTypeVersion) {
return valueType;
}
}
return null;
}
public findValueTypeByProperty(valueTypeString, valueTypeVersion, propertyName) {
const valueType = this.findValueType(valueTypeString, valueTypeVersion);
if (!valueType) {
return null;
}
for (const property of valueType.properties) {
if (property.name === propertyName) {
return this.findValueType(property.valueType, property.valueTypeVersion);
}
}
}
public getParameterOptions(): any {
const options = [];
for (const parameter of this.parameters) {
const valueType = this.findValueType(parameter.valueType, parameter.valueTypeVersion);
const info = valueType.version ? valueType.name + '(V' + valueType.version + ')' : valueType.name;
options.push({ label: parameter.name, type: 'variable', apply: '${' + parameter.name + '}', info: info });
}
return options;
}
public getPropertyOptions(parameterName: string): any {
let parameterType = undefined;
for (const parameter of this.parameters) {
if (parameter.name === parameterName) {
parameterType = parameter.valueType;
}
}
if (!parameterType) {
return null;
}
for (const type of this.valueTypes) {
if (type.code === parameterType) {
parameterType = type;
}
}
if (!parameterType) {
return null;
}
if (parameterType.properties && parameterType.properties.length > 0) {
const options = [];
for (const property of parameterType.properties) {
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', detail: this.findValueTypeInfo(property.valueType) });
}
return options;
}
}
public autoCompletionParameters(to, matchedText): any {
return {
from: to,
options: this.getParameterOptions(),
validFor: /(.*)?/,
};
}
public autoCompletionProperties(to, matchedText): any {
const matchedTextReverse = Tools.reverseString(matchedText);
const regReverse = /((.*)?\}(.+?)\{\$)+/g; //匹配 'xxx.}xxx{$' 模式
const matcheds = matchedTextReverse.match(regReverse);
if (Tools.isUndefinedOrNull(matcheds) || matcheds.length <= 0) {
return null;
}
const matched = Tools.reverseString(matcheds[0]);
const parameterName = matched.replace(/\$\{(.+?)\}/g, '$1');
console.log(parameterName);
if (Tools.isUndefinedOrNull(parameterName)) {
return null;
}
const options = this.getOptions(parameterName);
if (Tools.isUndefinedOrNull(options)) {
return null;
}
return {
from: to,
options: options,
//validFor: /^(.*)?$/,
};
}
public autoCompletion(context): any {
const beforeMatched = context.matchBefore(/(.+?)/g);
if (Tools.isUndefinedOrNull(beforeMatched)) {
return null;
}
const beforeText = beforeMatched.text || '';
if (beforeText.endsWith(' ')) {
//匹配参数
return this.autoCompletionParameters(beforeMatched.to);
} else {
//匹配属性
return this.autoCompletionProperties(beforeMatched.to, beforeText);
}
}
}
export { AutoCompletionManager2 };

28
io.sc.platform.core.frontend/src/views/testcase/code-mirror/code-mirror.vue

@ -1,12 +1,20 @@
<template> <template>
<w-code-mirror lang="sql" :rows="20" :placeholder="true" :auto-completion="autoCompletion" :editable="true"></w-code-mirror> <w-code-mirror
lang="sql"
:rows="20"
:placeholder="true"
:auto-completion="autoCompletion"
:activate-on-completion="activateOnCompletion"
:editable="true"
></w-code-mirror>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { axios, Environment, Tools } from '@/platform'; import { axios, Environment, Tools } from '@/platform';
import { AutoCompletionManager } from './AutoCompletionManager'; import { AutoCompletionManager } from './AutoCompletionManager';
import { AutoCompletionManager2 } from './AutoCompletionManager2';
const autoCompletionManager = new AutoCompletionManager(); const autoCompletionManager = new AutoCompletionManager();
axios.get(Environment.apiContextPath('/api/re/common/listParameterAndValueTypeByIndicatorId/5c2bc795-359a-4d9a-84bd-cb4e058fc184')).then((response) => { axios.get(Environment.apiContextPath('/api/re/common/listParameterAndValueTypeByIndicatorId/bc8add2e-df95-44f3-96f5-e9d106a48729')).then((response) => {
autoCompletionManager.setParameters(response.data.parameters); autoCompletionManager.setParameters(response.data.parameters);
autoCompletionManager.setValueTypes(response.data.valueTypes); autoCompletionManager.setValueTypes(response.data.valueTypes);
}); });
@ -14,13 +22,17 @@ axios.get(Environment.apiContextPath('/api/re/common/listParameterAndValueTypeBy
const autoCompletion = (context) => { const autoCompletion = (context) => {
return autoCompletionManager.autoCompletion(context); return autoCompletionManager.autoCompletion(context);
}; };
const activateOnCompletion = (completion) => {
console.log(completion);
};
const reg = /\$\{(.+?)\}\.$/g; const reg = /\$\{(.+?)\}\.$/g;
const regReverse = /(\.\}(.+?)\{\$)+/g; //const regReverse = /(\.\}(.+?)\{\$)+/g;
let str = ' ${对象}.${属性}+${对象2}.'; let str = ' ${对象}.${属性}+${对象2}.';
console.log(str); //console.log(str);
str = Tools.reverseString(str); //str = Tools.reverseString(str);
console.log(str); //console.log(str);
const matched = str.match(regReverse); const matched = str.match(reg);
console.log(Tools.reverseString(matched[0])); console.log(matched);
//console.log(Tools.reverseString(matched[0]));
</script> </script>

2
io.sc.platform.core.frontend/src/views/testcase/math/MathEditor.vue

@ -5,6 +5,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import { axios, Environment } from '@/platform';
const zoomRef = ref(10); const zoomRef = ref(10);
const formula = ''; const formula = '';
const formulaRef = ref(` const formulaRef = ref(`

4
io.sc.platform.core.frontend/template-project/package.json

@ -1,6 +1,6 @@
{ {
"name": "platform-core", "name": "platform-core",
"version": "8.1.273", "version": "8.1.275",
"description": "前端核心包,用于快速构建前端的脚手架", "description": "前端核心包,用于快速构建前端的脚手架",
"private": false, "private": false,
"keywords": [], "keywords": [],
@ -104,7 +104,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.273", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

17
io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/AutoCompletionManager.ts

@ -112,7 +112,12 @@ class AutoCompletionManager {
if (parameterType.properties && parameterType.properties.length > 0) { if (parameterType.properties && parameterType.properties.length > 0) {
const options = []; const options = [];
for (const property of parameterType.properties) { for (const property of parameterType.properties) {
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', detail: this.findValueTypeInfo(property.valueType) }); options.push({
label: property.name,
type: 'property',
apply: '${' + property.name + '}',
detail: this.findValueTypeInfo(property.valueType),
});
} }
return options; return options;
} }
@ -122,7 +127,10 @@ class AutoCompletionManager {
return { return {
from: to, from: to,
options: this.getParameterOptions(), options: this.getParameterOptions(),
validFor: /(.*)?/, //validFor: /(.*)?/,
validFor: (text, from, to, state) => {
console.log(text);
},
}; };
} }
@ -145,7 +153,10 @@ class AutoCompletionManager {
return { return {
from: to, from: to,
options: options, options: options,
validFor: /^(.*)?$/, //validFor: /(.*)?/,
validFor: (text, from, to, state) => {
console.log(text, from, to, state);
},
}; };
} }

190
io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/AutoCompletionManager2.ts

@ -0,0 +1,190 @@
import { Tools } from '@/platform';
class AutoCompletionManager2 {
parameters: object[];
valueTypes: object[];
public setParameters(parameters) {
this.parameters = parameters;
}
public setValueTypes(valueTypes) {
this.valueTypes = valueTypes;
}
public getOptions(path: string): any {
if (!path) {
return this.getParameterOptions();
}
if (path.endsWith('.')) {
path = path.substring(0, path.length - 1);
}
const names = path.split('.');
if (!names) {
return this.getParameterOptions();
}
//参数
const parameter = this.findParmeter(names[0]);
if (!parameter) {
return null;
}
const valueTypeString = parameter.valueType;
const valueTypeVersion = parameter.valueTypeVersion;
let valueType = this.findValueType(valueTypeString, valueTypeVersion);
if (!valueType || !valueType.properties || valueType.properties.length <= 0) {
return null;
}
let index = 1;
let lastNameIsNotCompleted = false;
while (index < names.length) {
const _valueType = this.findValueTypeByProperty(valueType.code, valueType.version, names[index]);
if (_valueType) {
valueType = _valueType;
} else {
lastNameIsNotCompleted = true;
}
index++;
}
const options = [];
if (lastNameIsNotCompleted) {
for (const property of valueType.properties) {
if (property.name.indexOf(names[names.length - 1]) != -1) {
const propertyValueType = this.findValueType(property.valueType, property.valueTypeVersion);
if (!propertyValueType) {
continue;
}
const info = propertyValueType.version ? propertyValueType.name + '(V' + propertyValueType.version + ')' : propertyValueType.name;
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', info: info });
}
}
return options;
} else {
for (const property of valueType.properties) {
const propertyValueType = this.findValueType(property.valueType, property.valueTypeVersion);
if (!propertyValueType) {
continue;
}
const info = propertyValueType.version ? propertyValueType.name + '(V' + propertyValueType.version + ')' : propertyValueType.name;
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', info: info });
}
return options;
}
}
public findParmeter(parameterName) {
for (const parameter of this.parameters) {
if (parameter.name === parameterName) {
return parameter;
}
}
return null;
}
public findValueType(valueTypeString, valueTypeVersion) {
for (const valueType of this.valueTypes) {
if (valueType.code === valueTypeString && valueType.version === valueTypeVersion) {
return valueType;
}
}
return null;
}
public findValueTypeByProperty(valueTypeString, valueTypeVersion, propertyName) {
const valueType = this.findValueType(valueTypeString, valueTypeVersion);
if (!valueType) {
return null;
}
for (const property of valueType.properties) {
if (property.name === propertyName) {
return this.findValueType(property.valueType, property.valueTypeVersion);
}
}
}
public getParameterOptions(): any {
const options = [];
for (const parameter of this.parameters) {
const valueType = this.findValueType(parameter.valueType, parameter.valueTypeVersion);
const info = valueType.version ? valueType.name + '(V' + valueType.version + ')' : valueType.name;
options.push({ label: parameter.name, type: 'variable', apply: '${' + parameter.name + '}', info: info });
}
return options;
}
public getPropertyOptions(parameterName: string): any {
let parameterType = undefined;
for (const parameter of this.parameters) {
if (parameter.name === parameterName) {
parameterType = parameter.valueType;
}
}
if (!parameterType) {
return null;
}
for (const type of this.valueTypes) {
if (type.code === parameterType) {
parameterType = type;
}
}
if (!parameterType) {
return null;
}
if (parameterType.properties && parameterType.properties.length > 0) {
const options = [];
for (const property of parameterType.properties) {
options.push({ label: property.name, type: 'property', apply: '${' + property.name + '}', detail: this.findValueTypeInfo(property.valueType) });
}
return options;
}
}
public autoCompletionParameters(to, matchedText): any {
return {
from: to,
options: this.getParameterOptions(),
validFor: /(.*)?/,
};
}
public autoCompletionProperties(to, matchedText): any {
const matchedTextReverse = Tools.reverseString(matchedText);
const regReverse = /((.*)?\}(.+?)\{\$)+/g; //匹配 'xxx.}xxx{$' 模式
const matcheds = matchedTextReverse.match(regReverse);
if (Tools.isUndefinedOrNull(matcheds) || matcheds.length <= 0) {
return null;
}
const matched = Tools.reverseString(matcheds[0]);
const parameterName = matched.replace(/\$\{(.+?)\}/g, '$1');
console.log(parameterName);
if (Tools.isUndefinedOrNull(parameterName)) {
return null;
}
const options = this.getOptions(parameterName);
if (Tools.isUndefinedOrNull(options)) {
return null;
}
return {
from: to,
options: options,
//validFor: /^(.*)?$/,
};
}
public autoCompletion(context): any {
const beforeMatched = context.matchBefore(/(.+?)/g);
if (Tools.isUndefinedOrNull(beforeMatched)) {
return null;
}
const beforeText = beforeMatched.text || '';
if (beforeText.endsWith(' ')) {
//匹配参数
return this.autoCompletionParameters(beforeMatched.to);
} else {
//匹配属性
return this.autoCompletionProperties(beforeMatched.to, beforeText);
}
}
}
export { AutoCompletionManager2 };

28
io.sc.platform.core.frontend/template-project/src/views/testcase/code-mirror/code-mirror.vue

@ -1,12 +1,20 @@
<template> <template>
<w-code-mirror lang="sql" :rows="20" :placeholder="true" :auto-completion="autoCompletion" :editable="true"></w-code-mirror> <w-code-mirror
lang="sql"
:rows="20"
:placeholder="true"
:auto-completion="autoCompletion"
:activate-on-completion="activateOnCompletion"
:editable="true"
></w-code-mirror>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { axios, Environment, Tools } from '@/platform'; import { axios, Environment, Tools } from '@/platform';
import { AutoCompletionManager } from './AutoCompletionManager'; import { AutoCompletionManager } from './AutoCompletionManager';
import { AutoCompletionManager2 } from './AutoCompletionManager2';
const autoCompletionManager = new AutoCompletionManager(); const autoCompletionManager = new AutoCompletionManager();
axios.get(Environment.apiContextPath('/api/re/common/listParameterAndValueTypeByIndicatorId/5c2bc795-359a-4d9a-84bd-cb4e058fc184')).then((response) => { axios.get(Environment.apiContextPath('/api/re/common/listParameterAndValueTypeByIndicatorId/bc8add2e-df95-44f3-96f5-e9d106a48729')).then((response) => {
autoCompletionManager.setParameters(response.data.parameters); autoCompletionManager.setParameters(response.data.parameters);
autoCompletionManager.setValueTypes(response.data.valueTypes); autoCompletionManager.setValueTypes(response.data.valueTypes);
}); });
@ -14,13 +22,17 @@ axios.get(Environment.apiContextPath('/api/re/common/listParameterAndValueTypeBy
const autoCompletion = (context) => { const autoCompletion = (context) => {
return autoCompletionManager.autoCompletion(context); return autoCompletionManager.autoCompletion(context);
}; };
const activateOnCompletion = (completion) => {
console.log(completion);
};
const reg = /\$\{(.+?)\}\.$/g; const reg = /\$\{(.+?)\}\.$/g;
const regReverse = /(\.\}(.+?)\{\$)+/g; //const regReverse = /(\.\}(.+?)\{\$)+/g;
let str = ' ${对象}.${属性}+${对象2}.'; let str = ' ${对象}.${属性}+${对象2}.';
console.log(str); //console.log(str);
str = Tools.reverseString(str); //str = Tools.reverseString(str);
console.log(str); //console.log(str);
const matched = str.match(regReverse); const matched = str.match(reg);
console.log(Tools.reverseString(matched[0])); console.log(matched);
//console.log(Tools.reverseString(matched[0]));
</script> </script>

2
io.sc.platform.core.frontend/template-project/src/views/testcase/math/MathEditor.vue

@ -5,6 +5,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import { axios, Environment } from '@/platform';
const zoomRef = ref(10); const zoomRef = ref(10);
const formula = ''; const formula = '';
const formulaRef = ref(` const formulaRef = ref(`

10
io.sc.platform.core/src/main/java/io/sc/platform/core/exception/PasswordStrengthException.java

@ -0,0 +1,10 @@
package io.sc.platform.core.exception;
public class PasswordStrengthException extends RuntimeException {
public PasswordStrengthException() {
}
public PasswordStrengthException(String message) {
super(message);
}
}

6
io.sc.platform.core/src/main/java/io/sc/platform/core/response/ValidateException.java

@ -6,10 +6,16 @@ import java.util.List;
public class ValidateException extends RuntimeException{ public class ValidateException extends RuntimeException{
private List<ValidationError> errors =new ArrayList<ValidationError>(); private List<ValidationError> errors =new ArrayList<ValidationError>();
public ValidateException(){}
public ValidateException(List<ValidationError> errors){ public ValidateException(List<ValidationError> errors){
this.errors =errors; this.errors =errors;
} }
public void addError(ValidationError error){
this.errors.add(error);
}
public List<ValidationError> getErrors() { public List<ValidationError> getErrors() {
return errors; return errors;
} }

8
io.sc.platform.core/src/main/java/io/sc/platform/core/service/Desensitizer.java

@ -0,0 +1,8 @@
package io.sc.platform.core.service;
public interface Desensitizer {
public String desensitizer(String string);
public boolean isEnable();
public void setEnable(boolean enable);
}

30
io.sc.platform.core/src/main/java/io/sc/platform/core/service/support/DesensitizerProperties.java

@ -0,0 +1,30 @@
package io.sc.platform.core.service.support;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 脱敏配置属性类
* application.desensitizer.enable = true
* application.desensitizer.implementClassName = io.sc.platform.orm.desensitizer.DefaultDesensitizer
*/
@ConfigurationProperties("application.desensitizer")
public class DesensitizerProperties {
private boolean enable;
private String implementClassName;
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getImplementClassName() {
return implementClassName;
}
public void setImplementClassName(String implementClassName) {
this.implementClassName = implementClassName;
}
}

122
io.sc.platform.core/src/main/java/io/sc/platform/core/util/JaxbUtil.java

@ -0,0 +1,122 @@
package io.sc.platform.core.util;
import io.sc.platform.core.Environment;
import java.io.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
/**
* jaxb 辅助类
* 主要用于序列化和反序列化 xml
*
*/
public class JaxbUtil {
/**
* 解析 xml
* @param xml xml 内容
* @param type 对象类型
* @return 解析后的对象
* @throws JAXBException 违例
*
* @param <T> 数据类型
*/
public static <T> T unmarshal(String xml,Class<T> type) throws JAXBException{
try {
InputStream in = new ByteArrayInputStream(xml.getBytes(Environment.DEFAULT_CHARSET_NAME));
return unmarshal(in, type);
}catch (Exception e){
throw new JAXBException(e);
}
}
/**
* 解析 xml (文件)
* @param file 文件路径
* @param type 对象类型
* @return 解析后的对象
* @throws JAXBException 违例
*
* @param <T> 数据类型
*/
public static <T> T unmarshal(File file,Class<T> type) throws JAXBException{
return unmarshal(new StreamSource(file),type);
}
/**
* 解析 xml (输入流)
* @param inputStream 输入流
* @param type 对象类型
* @return 解析后的对象
* @throws JAXBException 违例
*
* @param <T> 数据类型
*/
public static <T> T unmarshal(InputStream inputStream,Class<T> type) throws JAXBException{
return unmarshal(new StreamSource(inputStream),type);
}
/**
* 解析 xml (StreamSource)
* @param streamSource StreamSource
* @param type 对象类型
* @return 解析后的对象
* @throws JAXBException 违例
*
* @param <T> 数据类型
*/
public static <T> T unmarshal(StreamSource streamSource,Class<T> type) throws JAXBException{
JAXBContext decodeJAXBContext =JAXBContext.newInstance(type);
Unmarshaller unmarshaller =decodeJAXBContext.createUnmarshaller();
JAXBElement<T> obj =unmarshaller.unmarshal(streamSource,type);
return obj.getValue();
}
/**
* 将对象序列化成 xml
* @param object 对象
* @param type 对象类型
* @return xml
* @throws JAXBException 违例
*
* @param <T> 数据类型
*/
public static <T> String marshal(Object object,Class<T> type) throws JAXBException{
StringWriter writer =new StringWriter();
marshal(object,type,writer);
return writer.toString();
}
/**
* 将对象序列化成 xml,并写入 OutputStream
* @param object 对象
* @param type 对象类型
* @param outputStream 输出流
* @throws JAXBException 违例
*
* @param <T> 数据类型
*/
public static <T> void marshal(Object object,Class<T> type,OutputStream outputStream) throws JAXBException{
marshal(object,type,new OutputStreamWriter(outputStream));
}
/**
* 将对象序列化成 xml,并写入 Writer
* @param object 对象
* @param type 对象类型
* @param writer 输出流
* @throws JAXBException 违例
*
* @param <T> 数据类型
*/
public static <T> void marshal(Object object,Class<T> type,Writer writer) throws JAXBException{
JAXBContext decodeJAXBContext =JAXBContext.newInstance(type);
Marshaller marshaller =decodeJAXBContext.createMarshaller();
marshaller.marshal(object, writer);
}
}

2
io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/exception.properties

@ -1,2 +1,2 @@
io.sc.platform.core.response.ValidateException=Request Parameter Validate Error io.sc.platform.core.response.ValidateException=Request Parameter Validate Error
io.sc.platform.orm.api.exception.UserRawPasswordNotMatchException=Raw Password Error io.sc.platform.core.exception.PasswordStrengthException=Password must contain uppercase, lowercase, numbers, special characters, and must be greater than or equal to {0} in length.

2
io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/exception_tw_CN.properties

@ -1,2 +1,2 @@
io.sc.platform.core.response.ValidateException=\u8ACB\u6C42\u53C3\u6578\u9A57\u8B49\u932F\u8AA4 io.sc.platform.core.response.ValidateException=\u8ACB\u6C42\u53C3\u6578\u9A57\u8B49\u932F\u8AA4
io.sc.platform.orm.api.exception.UserRawPasswordNotMatchException=\u539F\u5BC6\u78BC\u932F\u8AA4 io.sc.platform.core.exception.PasswordStrengthException=\u5BC6\u78BC\u5FC5\u9808\u5305\u542B:\u5927\u5BEB\u5B57\u6BCD\u3001\u5C0F\u5BEB\u5B57\u6BCD\u3001\u6578\u5B57\u3001\u7279\u6B8A\u5B57\u7B26, \u4E14\u9577\u5EA6\u5FC5\u9808\u5927\u65BC\u7B49\u65BC {0} \u4E2A\u3002

2
io.sc.platform.core/src/main/resources/io/sc/platform/core/i18n/exception_zh_CN.properties

@ -1,2 +1,2 @@
io.sc.platform.core.response.ValidateException=\u8BF7\u6C42\u53C2\u6570\u9A8C\u8BC1\u9519\u8BEF io.sc.platform.core.response.ValidateException=\u8BF7\u6C42\u53C2\u6570\u9A8C\u8BC1\u9519\u8BEF
io.sc.platform.orm.api.exception.UserRawPasswordNotMatchException=\u539F\u5BC6\u7801\u9519\u8BEF io.sc.platform.core.exception.PasswordStrengthException=\u5BC6\u7801\u5FC5\u987B\u5305\u542B:\u5927\u5199\u5B57\u6BCD\u3001\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u7279\u6B8A\u5B57\u7B26, \u4E14\u957F\u5EA6\u5FC5\u987B\u5927\u4E8E\u7B49\u4E8E {0} \u4E2A\u3002

2
io.sc.platform.developer.frontend/package.json

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.273", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

21
io.sc.platform.gradle/templates/pgp/app/src/main/java/app/platform/Application.java.txt

@ -2,12 +2,15 @@ package app.platform;
import io.sc.platform.core.ApplicationLauncher; import io.sc.platform.core.ApplicationLauncher;
import io.sc.platform.core.PlatformSpringBootServletInitializer; import io.sc.platform.core.PlatformSpringBootServletInitializer;
import io.sc.platform.core.util.FileUtil; import io.sc.platform.orm.entity.BaseEntity;
import io.sc.platform.core.util.StringUtil; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.web.WebApplicationInitializer; import org.springframework.web.WebApplicationInitializer;
import java.io.IOException; import java.util.Locale;
import java.util.Set;
/** /**
* 应用程序入口 * 应用程序入口
@ -16,10 +19,12 @@ import java.io.IOException;
public class Application extends PlatformSpringBootServletInitializer implements WebApplicationInitializer { public class Application extends PlatformSpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ApplicationLauncher.run(Application.class,args); ApplicationLauncher.run(Application.class,args);
// ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
// provider.addIncludeFilter(new AssignableTypeFilter(BaseEntity.class));
// Set<BeanDefinition> components = provider.findCandidateComponents("io.sc");
// for (BeanDefinition component : components)
// {
// System.out.println(component.getBeanClassName());
// }
} }
// public static void main(String[] args) throws IOException {
// String s =FileUtil.readString("classpath:/poc/REPORT_RECORD.sql","GBK");
// FileUtil.writeString("/Users/wangshaoping/wspsc/workspace/wangshaoping/v8/platform/app.platform/src/main/resources/poc/REPORT_RECORD.sql",s,"UTF-8");
// }
} }

3
io.sc.platform.gradle/templates/pgp/setup/gradle.properties

@ -38,7 +38,7 @@ application_version=1.0.0
platform_group=io.sc platform_group=io.sc
platform_version=8.1.44 platform_version=8.1.44
platform_plugin_version=8.1.44 platform_plugin_version=8.1.44
platform_core_frontend_version=8.1.264 platform_core_frontend_version=8.1.275
########################################################### ###########################################################
# dependencies version # dependencies version
@ -48,6 +48,7 @@ asm_version=9.7
checker_version=3.43.0 checker_version=3.43.0
commons_fileupload_version=1.4 commons_fileupload_version=1.4
commons_io_version=2.16.1 commons_io_version=2.16.1
commons_text_version=1.12.0
cxf_version=3.2.7 cxf_version=3.2.7
dm_hibernate_version=8.1.2.192 dm_hibernate_version=8.1.2.192
flowable_version=6.8.0 flowable_version=6.8.0

2
io.sc.platform.lcdp.frontend/package.json

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.273", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

2
io.sc.platform.mvc.frontend/package.json

@ -92,7 +92,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.273", "platform-core": "8.1.275",
"quasar": "2.15.4", "quasar": "2.15.4",
"tailwindcss": "3.4.4", "tailwindcss": "3.4.4",
"vue": "3.4.31", "vue": "3.4.31",

7
io.sc.platform.mvc/src/main/java/io/sc/platform/mvc/autoconfigure/support/AuditLogAspectorBean.java

@ -126,9 +126,10 @@ public class AuditLogAspectorBean {
String action =messageSource.getMessage(key, null, key, httpServletRequest.getLocale()); String action =messageSource.getMessage(key, null, key, httpServletRequest.getLocale());
auditLog.setAction(action); auditLog.setAction(action);
} }
if(auditorEntity!=null) { // modify by wspsc
auditLog.setOldValue(objectMapper.writeValueAsString(auditorEntity.desensitize())); // if(auditorEntity!=null) {
} // auditLog.setOldValue(objectMapper.writeValueAsString(auditorEntity.desensitize()));
// }
if(queryParameter!=null) { if(queryParameter!=null) {
auditLog.setNewValue(objectMapper.writeValueAsString(queryParameter)); auditLog.setNewValue(objectMapper.writeValueAsString(queryParameter));

4
io.sc.platform.orm/src/main/java/io/sc/platform/orm/annotation/Desensitizeable.java

@ -0,0 +1,4 @@
package io.sc.platform.orm.annotation;
public @interface Desensitizeable {
}

33
io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/DesensitizeAndEncodeStringCoverter.java

@ -0,0 +1,33 @@
package io.sc.platform.orm.converter;
import io.sc.platform.core.Environment;
import io.sc.platform.core.util.StringEncryptorUtil;
import io.sc.platform.orm.service.DesensitizerAuthorizerService;
import io.sc.platform.orm.service.DesensitizerManagerService;
import io.sc.platform.orm.service.support.Desensitizer;
import javax.persistence.AttributeConverter;
public interface DesensitizeAndEncodeStringCoverter extends AttributeConverter<String, String> {
public String getEntityClassName();
public String getEntityFieldName();
public String getDesensitizerName();
@Override
default public String convertToDatabaseColumn(String attribute) {
return StringEncryptorUtil.encrypt(attribute);
}
@Override
default public String convertToEntityAttribute(String dbData) {
String decryptData =StringEncryptorUtil.decrypt(dbData);
DesensitizerAuthorizerService authorizer =Environment.getInstance().getApplicationContext().getBean(DesensitizerAuthorizerService.class);
if(authorizer.authorize(getEntityClassName(),getEntityFieldName())){
// 通过脱敏管理器获取脱敏器
DesensitizerManagerService manager =Environment.getInstance().getApplicationContext().getBean(DesensitizerManagerService.class);
Desensitizer desensitizer =manager.getDesensitizer(getDesensitizerName());
return desensitizer.desensitize(decryptData);
}
return decryptData;
}
}

31
io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/DesensitizeStringCoverter.java

@ -0,0 +1,31 @@
package io.sc.platform.orm.converter;
import io.sc.platform.core.Environment;
import io.sc.platform.core.util.StringEncryptorUtil;
import io.sc.platform.orm.service.DesensitizerAuthorizerService;
import io.sc.platform.orm.service.DesensitizerManagerService;
import javax.persistence.AttributeConverter;
public interface DesensitizeStringCoverter extends AttributeConverter<String, String> {
public String getEntityClassName();
public String getEntityFieldName();
public String getDesensitizerName();
@Override
default public String convertToDatabaseColumn(String attribute) {
return StringEncryptorUtil.encrypt(attribute);
}
@Override
default public String convertToEntityAttribute(String dbData) {
DesensitizerAuthorizerService authorizer =Environment.getInstance().getApplicationContext().getBean(DesensitizerAuthorizerService.class);
if(authorizer.authorize(getEntityClassName(),getEntityFieldName())){
// 通过脱敏管理器获取脱敏器
DesensitizerManagerService manager =Environment.getInstance().getApplicationContext().getBean(DesensitizerManagerService.class);
io.sc.platform.orm.service.support.Desensitizer desensitizer =manager.getDesensitizer(getDesensitizerName());
return desensitizer.desensitize(dbData);
}
return dbData;
}
}

2
io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/EncoderStringConverter.java → io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/EncodeStringConverter.java

@ -4,7 +4,7 @@ import io.sc.platform.core.util.StringEncryptorUtil;
import javax.persistence.AttributeConverter; import javax.persistence.AttributeConverter;
public class EncoderStringConverter implements AttributeConverter<String, String> { public class EncodeStringConverter implements AttributeConverter<String, String> {
@Override @Override
public String convertToDatabaseColumn(String attribute) { public String convertToDatabaseColumn(String attribute) {
return StringEncryptorUtil.encrypt(attribute); return StringEncryptorUtil.encrypt(attribute);

39
io.sc.platform.orm/src/main/java/io/sc/platform/orm/converter/support/DesensitizeConvertWrapper.java

@ -0,0 +1,39 @@
package io.sc.platform.orm.converter.support;
public class DesensitizeConvertWrapper<T> {
private T value;
private String className;
private String fieldName;
public DesensitizeConvertWrapper(){}
public DesensitizeConvertWrapper(String className, String fieldName, T value){
this.className =className;
this.fieldName =fieldName;
this.value =value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
}

36
io.sc.platform.orm/src/main/java/io/sc/platform/orm/desensitizer/DefaultDesensitizer.java

@ -0,0 +1,36 @@
package io.sc.platform.orm.desensitizer;
import io.sc.platform.core.service.Desensitizer;
import org.springframework.util.StringUtils;
import java.util.Random;
public class DefaultDesensitizer implements Desensitizer {
private Random random =new Random();
private boolean enable = true;
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
@Override
public String desensitizer(String string) {
if(this.enable && StringUtils.hasText(string)) {
int length =string.length();
int cout =0;
if(length<=3){
return "***" + string + "***";
}else {
cout =(int)length/2; //需要脱敏的字符数
cout =Math.max(cout,3);
int index =random.nextInt(length-cout);
return "***" + string.substring(index,index+cout) + "***";
}
}
return string;
}
}

4
io.sc.platform.orm/src/main/java/io/sc/platform/orm/entity/BaseEntity.java

@ -15,8 +15,4 @@ public abstract class BaseEntity<V extends BaseVo> implements Serializable {
public V toVo(){ public V toVo(){
return null; return null;
} }
public V desensitize(){
return toVo();
}
} }

30
io.sc.platform.orm/src/main/java/io/sc/platform/orm/plugins/PluginManager.java

@ -3,6 +3,7 @@ package io.sc.platform.orm.plugins;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import io.sc.platform.core.plugins.Plugin; import io.sc.platform.core.plugins.Plugin;
import io.sc.platform.core.plugins.PluginParser; import io.sc.platform.core.plugins.PluginParser;
import io.sc.platform.core.plugins.item.Directory;
import io.sc.platform.orm.plugins.item.Repository; import io.sc.platform.orm.plugins.item.Repository;
import java.util.ArrayList; import java.util.ArrayList;
@ -13,9 +14,13 @@ import java.util.List;
*/ */
public class PluginManager { public class PluginManager {
private static final String REPOSITORY_LOCATION ="META-INF/platform/plugins/repositories.json"; private static final String REPOSITORY_LOCATION ="META-INF/platform/plugins/repositories.json";
private static final String DESENSITIZER_LOCATION ="META-INF/platform/plugins/desensitizer.json";
private List<Plugin<Repository>> repositoriesPlugins; private List<Plugin<Repository>> repositoriesPlugins;
private List<Repository> repositories; private List<Repository> repositories;
private List<Plugin<List<String>>> desensitizerPlugins;
private List<String> desensitizers;
/** /**
* 获取单例模式实例 * 获取单例模式实例
@ -32,6 +37,7 @@ public class PluginManager {
private PluginManager(){ private PluginManager(){
PluginParser parser =new PluginParser(); PluginParser parser =new PluginParser();
loadRepositoriesPlugins(parser); loadRepositoriesPlugins(parser);
loadDesensitizersPlugins(parser);
} }
public List<Plugin<Repository>> getRepositoriesPlugins() { public List<Plugin<Repository>> getRepositoriesPlugins() {
@ -47,6 +53,19 @@ public class PluginManager {
this.repositories = repositories; this.repositories = repositories;
} }
public List<Plugin<List<String>>> getDesensitizerPlugins() {
return desensitizerPlugins;
}
public void setDesensitizerPlugins(List<Plugin<List<String>>> desensitizerPlugins) {
this.desensitizerPlugins = desensitizerPlugins;
}
public List<String> getDesensitizers() {
return desensitizers;
}
public void setDesensitizers(List<String> desensitizers) {
this.desensitizers = desensitizers;
}
/* /*
public List<RepositoryWrapper> getrepositoryWrappers() { public List<RepositoryWrapper> getrepositoryWrappers() {
List<RepositoryWrapper> result =new ArrayList<RepositoryWrapper>(); List<RepositoryWrapper> result =new ArrayList<RepositoryWrapper>();
@ -93,4 +112,15 @@ public class PluginManager {
repositories =items; repositories =items;
} }
} }
private void loadDesensitizersPlugins(PluginParser parser){
desensitizerPlugins =parser.parse(DESENSITIZER_LOCATION,new TypeReference<List<String>>(){});
if(desensitizerPlugins!=null && !desensitizerPlugins.isEmpty()){
List<String> items =new ArrayList<String>();
desensitizerPlugins.forEach((plugin)->{
items.addAll(plugin.getValue());
});
desensitizers =items;
}
}
} }

3
io.sc.platform.orm/src/main/java/io/sc/platform/orm/repository/DaoRepository.java

@ -10,6 +10,7 @@ import javax.persistence.EntityManager;
import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.ManagedType;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map;
@NoRepositoryBean @NoRepositoryBean
public interface DaoRepository<E,ID extends Serializable> extends JpaRepository<E,ID>,JpaSpecificationExecutor<E>{ public interface DaoRepository<E,ID extends Serializable> extends JpaRepository<E,ID>,JpaSpecificationExecutor<E>{
@ -21,7 +22,7 @@ public interface DaoRepository<E,ID extends Serializable> extends JpaRepository<
public ManagedTypeAttributes getManagedTypeAttributes(); public ManagedTypeAttributes getManagedTypeAttributes();
public ManagedTypeAttributes getManagedTypeAttributes(Class<?> domainClass); public ManagedTypeAttributes getManagedTypeAttributes(Class<?> domainClass);
public String getIdName(); public String getIdName();
public ID getId(E entity); public ID getId(E entity);
public void setId(E entity,ID id); public void setId(E entity,ID id);

4
io.sc.platform.orm/src/main/java/io/sc/platform/orm/repository/impl/DaoRepositoryImpl.java

@ -20,9 +20,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.springframework.data.jpa.repository.query.QueryUtils.DELETE_ALL_QUERY_STRING; import static org.springframework.data.jpa.repository.query.QueryUtils.*;
import static org.springframework.data.jpa.repository.query.QueryUtils.applyAndBind;
import static org.springframework.data.jpa.repository.query.QueryUtils.getQueryString;
public class DaoRepositoryImpl<E,ID extends Serializable> extends SimpleJpaRepository<E,ID> implements DaoRepository<E,ID> { public class DaoRepositoryImpl<E,ID extends Serializable> extends SimpleJpaRepository<E,ID> implements DaoRepository<E,ID> {
private JpaEntityInformation<E, ID> jpaEntityInformation; private JpaEntityInformation<E, ID> jpaEntityInformation;

5
io.sc.platform.orm/src/main/java/io/sc/platform/orm/service/DesensitizerAuthorizerService.java

@ -0,0 +1,5 @@
package io.sc.platform.orm.service;
public interface DesensitizerAuthorizerService {
public boolean authorize(String className,String fieldName);
}

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

Loading…
Cancel
Save