diff --git a/auto-solution-admin/src/main/java/com/solution/web/core/BehaviortreeProcessor.java b/auto-solution-admin/src/main/java/com/solution/web/core/BehaviortreeProcessor.java index b857905..d91fd67 100644 --- a/auto-solution-admin/src/main/java/com/solution/web/core/BehaviortreeProcessor.java +++ b/auto-solution-admin/src/main/java/com/solution/web/core/BehaviortreeProcessor.java @@ -87,9 +87,12 @@ public class BehaviortreeProcessor { // 插入节点 treenodeinstance Map instanceKeyMap = new HashMap<>(); Map nodeKeyIndexMap = new HashMap<>(); + Map nodesMap = new HashMap<>(); if (graph.hasNodes()) { Long index = 0L; for (GraphNode node : graph.getNodes()) { + nodesMap.put(node.getKey(), node); + Treenodeinstance instance = createNodeInstance(behaviortree, node); treenodeinstanceService.insertTreenodeinstance(instance); instanceKeyMap.put(node.getKey(), instance); @@ -110,16 +113,18 @@ public class BehaviortreeProcessor { // 插入连线 nodeconnection if (graph.hasEdges()) { for (GraphEdge edge : graph.getEdges()) { - Nodeconnection connection = createConnection(behaviortree, edge, instanceKeyMap, nodeKeyIndexMap); + Nodeconnection connection = createConnection(behaviortree, edge, nodesMap, instanceKeyMap, nodeKeyIndexMap); nodeconnectionService.insertNodeconnection(connection); } } } private Nodeconnection createConnection(Behaviortree behaviortree, GraphEdge edge, + Map nodesMap, Map instanceKeyMap, Map nodeKeyIndexMap) { Nodeconnection connection = new Nodeconnection(); + Long orderIndex = 0L; connection.setTreeId(behaviortree.getId()); if (null != instanceKeyMap.get(edge.getSource().getCell())) { Treenodeinstance parent = instanceKeyMap.get(edge.getSource().getCell()); @@ -129,9 +134,17 @@ public class BehaviortreeProcessor { Treenodeinstance children = instanceKeyMap.get(edge.getTarget().getCell()); connection.setChildNodeId(children.getId()); } - if (null != nodeKeyIndexMap.get(edge.getSource().getCell())) { - connection.setOrderIndex(nodeKeyIndexMap.get(edge.getSource().getCell())); + + if (null != nodesMap.get(edge.getTarget().getCell())) { + orderIndex = nodesMap.get(edge.getTarget().getCell()).getOrder(); } + if(null == orderIndex){ + orderIndex = 0L; + } +// if (null != nodeKeyIndexMap.get(edge.getSource().getCell())) { +// connection.setOrderIndex(nodeKeyIndexMap.get(edge.getSource().getCell())); +// } + connection.setOrderIndex(orderIndex); return connection; } diff --git a/auto-solution-admin/src/main/java/com/solution/web/core/graph/GraphNode.java b/auto-solution-admin/src/main/java/com/solution/web/core/graph/GraphNode.java index e94aab3..71f3d2a 100644 --- a/auto-solution-admin/src/main/java/com/solution/web/core/graph/GraphNode.java +++ b/auto-solution-admin/src/main/java/com/solution/web/core/graph/GraphNode.java @@ -23,6 +23,8 @@ public class GraphNode implements Serializable { private String type; + private Long order; + private String key; private String name; @@ -139,4 +141,12 @@ public class GraphNode implements Serializable { this.variables = variables; } + public Long getOrder() { + return order; + } + + public void setOrder(Long order) { + this.order = order; + } + } diff --git a/modeler/src/assets/icons/card-head-blue.png b/modeler/src/assets/icons/card-head-blue.png new file mode 100644 index 0000000..dd45808 Binary files /dev/null and b/modeler/src/assets/icons/card-head-blue.png differ diff --git a/modeler/src/assets/icons/card-head-dark.png b/modeler/src/assets/icons/card-head-dark.png new file mode 100644 index 0000000..d156283 Binary files /dev/null and b/modeler/src/assets/icons/card-head-dark.png differ diff --git a/modeler/src/assets/icons/card-head-gray.png b/modeler/src/assets/icons/card-head-gray.png new file mode 100644 index 0000000..8fb34a3 Binary files /dev/null and b/modeler/src/assets/icons/card-head-gray.png differ diff --git a/modeler/src/assets/icons/card-head-green.png b/modeler/src/assets/icons/card-head-green.png new file mode 100644 index 0000000..0e6bbf4 Binary files /dev/null and b/modeler/src/assets/icons/card-head-green.png differ diff --git a/modeler/src/assets/icons/card-head-red.png b/modeler/src/assets/icons/card-head-red.png new file mode 100644 index 0000000..1c91dee Binary files /dev/null and b/modeler/src/assets/icons/card-head-red.png differ diff --git a/modeler/src/assets/icons/icon-action.svg b/modeler/src/assets/icons/icon-action.svg new file mode 100644 index 0000000..f411d99 --- /dev/null +++ b/modeler/src/assets/icons/icon-action.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modeler/src/assets/icons/icon-branch.svg b/modeler/src/assets/icons/icon-branch.svg new file mode 100644 index 0000000..28fb91c --- /dev/null +++ b/modeler/src/assets/icons/icon-branch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modeler/src/assets/icons/icon-node.svg b/modeler/src/assets/icons/icon-node.svg new file mode 100644 index 0000000..365c9c0 --- /dev/null +++ b/modeler/src/assets/icons/icon-node.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modeler/src/assets/icons/icon-parallel.svg b/modeler/src/assets/icons/icon-parallel.svg new file mode 100644 index 0000000..be16a0b --- /dev/null +++ b/modeler/src/assets/icons/icon-parallel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modeler/src/assets/icons/icon-root.svg b/modeler/src/assets/icons/icon-root.svg new file mode 100644 index 0000000..6da8c00 --- /dev/null +++ b/modeler/src/assets/icons/icon-root.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modeler/src/assets/icons/icon-sequence.svg b/modeler/src/assets/icons/icon-sequence.svg new file mode 100644 index 0000000..eae4744 --- /dev/null +++ b/modeler/src/assets/icons/icon-sequence.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modeler/src/assets/icons/lx.svg b/modeler/src/assets/icons/lx.svg new file mode 100644 index 0000000..b0b9a03 --- /dev/null +++ b/modeler/src/assets/icons/lx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modeler/src/assets/icons/point.svg b/modeler/src/assets/icons/point.svg index b1daa24..c8b24d8 100644 --- a/modeler/src/assets/icons/point.svg +++ b/modeler/src/assets/icons/point.svg @@ -1,5 +1,5 @@ + p-id="3676" fill="#3c82f6"> \ No newline at end of file diff --git a/modeler/src/style.less b/modeler/src/style.less index f4aef21..32b711c 100644 --- a/modeler/src/style.less +++ b/modeler/src/style.less @@ -1204,7 +1204,7 @@ .ant-tabs-content { //padding: 15px; padding: 4px; - background: #041b36db; + background: #041832; } &.settings-tab, @@ -1641,4 +1641,10 @@ color: #b5b39d; cursor: pointer; } +} + +.ant-input-group-addon { + .anticon{ + color: #eeeeee; + } } \ No newline at end of file diff --git a/modeler/src/views/decision/builder/element.ts b/modeler/src/views/decision/builder/element.ts index 8cc0055..03f4bca 100644 --- a/modeler/src/views/decision/builder/element.ts +++ b/modeler/src/views/decision/builder/element.ts @@ -74,6 +74,7 @@ export interface GraphTaskElement extends BaseElement { templateType: NullableString, inputs: any; outputs: any; + order: number; variables: ElementVariable[]; parameters: ElementParameter[]; children?: GraphTaskElement[], diff --git a/modeler/src/views/decision/builder/graph.ts b/modeler/src/views/decision/builder/graph.ts index d7d371d..56324c3 100644 --- a/modeler/src/views/decision/builder/graph.ts +++ b/modeler/src/views/decision/builder/graph.ts @@ -52,7 +52,15 @@ export const createGraphConnectingAttributes = (): Partial => { const edge: Edge = this.createEdge({ shape: 'edge', ...lineOptions, // 应用动画配置 - attrs: lineOptions.attrs, + attrs: { + ...lineOptions.attrs, + // 在创建边时覆盖箭头配置,确保移除箭头 + line: { + ...lineOptions.attrs?.line, + targetMarker: null, + sourceMarker: null, + } + }, animation: lineOptions.animation, markup: lineOptions.markup, }); diff --git a/modeler/src/views/decision/builder/line.ts b/modeler/src/views/decision/builder/line.ts index 5e444d7..446931f 100644 --- a/modeler/src/views/decision/builder/line.ts +++ b/modeler/src/views/decision/builder/line.ts @@ -28,6 +28,10 @@ export const createLineOptions = (): any => { strokeWidth: 2, strokeDasharray: ' ', strokeDashoffset: 0, + + // 去掉箭头 + targetMarker: null, + sourceMarker: null, }, marker: { fill: '#5da0df', diff --git a/modeler/src/views/decision/builder/node.vue b/modeler/src/views/decision/builder/node.vue index 12e0a3c..95910ee 100644 --- a/modeler/src/views/decision/builder/node.vue +++ b/modeler/src/views/decision/builder/node.vue @@ -9,25 +9,30 @@ > -
-
+
+
+
+
-

+

{{ substring(element?.description ?? (element?.name ?? '-'), 40) }}

-

+

{{ substring(element?.description ?? (element?.name ?? '-'), 40) }}

-
+
+
+
-
- - 添加 - - - - -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/modeler/src/views/decision/utils/node.ts b/modeler/src/views/decision/utils/node.ts index 613100c..d83cdb5 100644 --- a/modeler/src/views/decision/utils/node.ts +++ b/modeler/src/views/decision/utils/node.ts @@ -26,6 +26,7 @@ export const createGraphTaskElementFromTemplate = ( name: template.name, category: template.type, description: template.description, + order: 0, position: { x: realRect.x ?? 0, y: realRect.y ?? 0, diff --git a/modeler/types/components.d.ts b/modeler/types/components.d.ts index ef68777..a3af590 100644 --- a/modeler/types/components.d.ts +++ b/modeler/types/components.d.ts @@ -12,7 +12,6 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { - AAvatar: typeof import('ant-design-vue/es')['Avatar'] ABadge: typeof import('ant-design-vue/es')['Badge'] AButton: typeof import('ant-design-vue/es')['Button'] ACard: typeof import('ant-design-vue/es')['Card'] @@ -23,7 +22,6 @@ declare module 'vue' { ADropdown: typeof import('ant-design-vue/es')['Dropdown'] AEmpty: typeof import('ant-design-vue/es')['Empty'] AFlex: typeof import('ant-design-vue/es')['Flex'] - AFloatButton: typeof import('ant-design-vue/es')['FloatButton'] AForm: typeof import('ant-design-vue/es')['Form'] AFormItem: typeof import('ant-design-vue/es')['FormItem'] AFormItemRest: typeof import('ant-design-vue/es')['FormItemRest'] @@ -46,8 +44,6 @@ declare module 'vue' { ASelect: typeof import('ant-design-vue/es')['Select'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASpace: typeof import('ant-design-vue/es')['Space'] - ASubMenu: typeof import('ant-design-vue/es')['SubMenu'] - ATable: typeof import('ant-design-vue/es')['Table'] ATabPane: typeof import('ant-design-vue/es')['TabPane'] ATabs: typeof import('ant-design-vue/es')['Tabs'] ATextarea: typeof import('ant-design-vue/es')['Textarea'] @@ -59,7 +55,6 @@ declare module 'vue' { // For TSX support declare global { - const AAvatar: typeof import('ant-design-vue/es')['Avatar'] const ABadge: typeof import('ant-design-vue/es')['Badge'] const AButton: typeof import('ant-design-vue/es')['Button'] const ACard: typeof import('ant-design-vue/es')['Card'] @@ -70,7 +65,6 @@ declare global { const ADropdown: typeof import('ant-design-vue/es')['Dropdown'] const AEmpty: typeof import('ant-design-vue/es')['Empty'] const AFlex: typeof import('ant-design-vue/es')['Flex'] - const AFloatButton: typeof import('ant-design-vue/es')['FloatButton'] const AForm: typeof import('ant-design-vue/es')['Form'] const AFormItem: typeof import('ant-design-vue/es')['FormItem'] const AFormItemRest: typeof import('ant-design-vue/es')['FormItemRest'] @@ -93,8 +87,6 @@ declare global { const ASelect: typeof import('ant-design-vue/es')['Select'] const ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] const ASpace: typeof import('ant-design-vue/es')['Space'] - const ASubMenu: typeof import('ant-design-vue/es')['SubMenu'] - const ATable: typeof import('ant-design-vue/es')['Table'] const ATabPane: typeof import('ant-design-vue/es')['TabPane'] const ATabs: typeof import('ant-design-vue/es')['Tabs'] const ATextarea: typeof import('ant-design-vue/es')['Textarea'] diff --git a/solution-rule/pom.xml b/solution-rule/pom.xml new file mode 100644 index 0000000..33757b0 --- /dev/null +++ b/solution-rule/pom.xml @@ -0,0 +1,39 @@ + + + + solution + com.solution + 3.9.1 + + + 4.0.0 + + solution-rule + + + rule模块 + + + + + + + com.solution + solution-common + + + + org.projectlombok + lombok + + + + io.springfox + springfox-boot-starter + + + + + \ No newline at end of file diff --git a/solution-rule/src/main/java/com/solution/rule/domain/PlatformComponent.java b/solution-rule/src/main/java/com/solution/rule/domain/PlatformComponent.java new file mode 100644 index 0000000..dd66e3a --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/PlatformComponent.java @@ -0,0 +1,32 @@ +package com.solution.rule.domain; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 平台挂载的组件实体类 + * 对应表 platform_component + */ +@Data +@ApiModel(value = "平台组件对象", description = "平台所挂载的武器、雷达、通信等组件") +public class PlatformComponent { + + @ApiModelProperty(value = "组件ID,主键自增") + private Integer id; + + @ApiModelProperty(value = "组件名称(具体型号)") + private String name; + + @ApiModelProperty(value = "组件类型:weapon(武器)、radar(雷达)、comm(通信)") + private String type; + + @ApiModelProperty(value = "组件描述信息") + private String description; + + @ApiModelProperty(value = "所属平台ID,关联platform表") + private Integer platformId; + + @ApiModelProperty(value = "组件数量") + private Long num; +} \ No newline at end of file diff --git a/solution-rule/src/main/java/com/solution/rule/domain/RuleParam.java b/solution-rule/src/main/java/com/solution/rule/domain/RuleParam.java new file mode 100644 index 0000000..f437c75 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/RuleParam.java @@ -0,0 +1,14 @@ +package com.solution.rule.domain; + +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.WeaponModelVO; +import lombok.Data; + + +@Data +public class RuleParam { + + private WeaponModelVO weaponModelVO; + + private WeaponModelDTO weaponModelDTO; +} diff --git a/solution-rule/src/main/java/com/solution/rule/domain/dto/RequestDTO.java b/solution-rule/src/main/java/com/solution/rule/domain/dto/RequestDTO.java new file mode 100644 index 0000000..f2cdeeb --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/dto/RequestDTO.java @@ -0,0 +1,22 @@ +package com.solution.rule.domain.dto; + +import lombok.Data; + +/** + * 规则请求参数 + */ +@Data +public class RequestDTO { + + //编队数量 + private Long formationNum; + + //武装直升机数量 + private Long gunshipNum; + + //无人机数量 + private Long droneNum; + + //单兵武器数量 + private Long singleWeaponNum; +} diff --git a/solution-rule/src/main/java/com/solution/rule/domain/dto/WeaponModelDTO.java b/solution-rule/src/main/java/com/solution/rule/domain/dto/WeaponModelDTO.java new file mode 100644 index 0000000..1ec2fff --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/dto/WeaponModelDTO.java @@ -0,0 +1,23 @@ +package com.solution.rule.domain.dto; + +import com.solution.rule.domain.PlatformComponent; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class WeaponModelDTO { + + @ApiModelProperty("平台id") + private Integer id; + + @ApiModelProperty("平台名称") + private String name; + + @ApiModelProperty("平台描述") + private String description; + + @ApiModelProperty("平台组件") + private List components; +} diff --git a/solution-rule/src/main/java/com/solution/rule/domain/vo/ComponentCountVO.java b/solution-rule/src/main/java/com/solution/rule/domain/vo/ComponentCountVO.java new file mode 100644 index 0000000..9bb1f80 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/vo/ComponentCountVO.java @@ -0,0 +1,16 @@ +package com.solution.rule.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +// 组件计数VO +@Data +@ApiModel("组件计数信息") +public class ComponentCountVO { + @ApiModelProperty("组件名称") + private String componentName; + + @ApiModelProperty("组件数量") + private Long count; +} \ No newline at end of file diff --git a/solution-rule/src/main/java/com/solution/rule/domain/vo/PlatformComponentNamesVO.java b/solution-rule/src/main/java/com/solution/rule/domain/vo/PlatformComponentNamesVO.java new file mode 100644 index 0000000..cd9e6c9 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/vo/PlatformComponentNamesVO.java @@ -0,0 +1,17 @@ +package com.solution.rule.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +@ApiModel("平台组件名称聚合") +public class PlatformComponentNamesVO { + @ApiModelProperty("平台名称") + private String platformName; + + @ApiModelProperty("该平台下的组件名称列表(去重)") + private List componentNames; +} \ No newline at end of file diff --git a/solution-rule/src/main/java/com/solution/rule/domain/vo/PlatformWeaponAggregateVO.java b/solution-rule/src/main/java/com/solution/rule/domain/vo/PlatformWeaponAggregateVO.java new file mode 100644 index 0000000..f602600 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/vo/PlatformWeaponAggregateVO.java @@ -0,0 +1,18 @@ +package com.solution.rule.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +// 平台武器聚合VO +@Data +@ApiModel("平台武器聚合信息") +public class PlatformWeaponAggregateVO { + @ApiModelProperty("平台名称") + private String platformName; + + @ApiModelProperty("该平台下的组件列表") + private List components; +} \ No newline at end of file diff --git a/solution-rule/src/main/java/com/solution/rule/domain/vo/WeaponModelVO.java b/solution-rule/src/main/java/com/solution/rule/domain/vo/WeaponModelVO.java new file mode 100644 index 0000000..8388741 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/domain/vo/WeaponModelVO.java @@ -0,0 +1,19 @@ +package com.solution.rule.domain.vo; + +import com.solution.rule.domain.dto.WeaponModelDTO; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class WeaponModelVO { + + @ApiModelProperty("平台名称") + private String platformName; + + @ApiModelProperty("组件名称") + private String componentName; + + @ApiModelProperty("组件数量") + private Long count; + +} diff --git a/solution-rule/src/main/java/com/solution/rule/enums/SceneType.java b/solution-rule/src/main/java/com/solution/rule/enums/SceneType.java new file mode 100644 index 0000000..142a69f --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/enums/SceneType.java @@ -0,0 +1,39 @@ +package com.solution.rule.enums; + +public enum SceneType { + + DEFENSE(0, "防御"), + AIRBORNE(1, "空降"); + + private final int code; + private final String description; + + SceneType(int code, String description) { + this.code = code; + this.description = description; + } + + public int getCode() { + return code; + } + + public String getDescription() { + return description; + } + + + /** + * 根据数字编码获取对应的枚举 + * @param code 前端传递的数字 + * @return 枚举实例 + * @throws IllegalArgumentException 如果找不到对应枚举 + */ + public static SceneType fromCode(int code) { + for (SceneType type : values()) { + if (type.code == code) { + return type; + } + } + throw new IllegalArgumentException("未知的场景类型编码: " + code); + } +} \ No newline at end of file diff --git a/solution-rule/src/main/java/com/solution/rule/handler/AbstractRuleChainHandler.java b/solution-rule/src/main/java/com/solution/rule/handler/AbstractRuleChainHandler.java new file mode 100644 index 0000000..9d5c2e3 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/handler/AbstractRuleChainHandler.java @@ -0,0 +1,43 @@ +package com.solution.rule.handler; + +import cn.hutool.core.util.ObjectUtil; +import com.solution.rule.domain.RuleParam; + +/** + * 规则链抽象类 + */ +public abstract class AbstractRuleChainHandler { + + + private AbstractRuleChainHandler nextHandler; + + + /** + * 执行过滤方法 + * @param ruleParam + * @return + */ + public abstract RuleParam doHandler(RuleParam ruleParam); + + + /** + * 执行下一个处理器 + * @param ruleParam + * @return + */ + public RuleParam doNextHandler(RuleParam ruleParam){ + if(ObjectUtil.isEmpty(nextHandler) || ObjectUtil.isNotEmpty(ruleParam)){ + return ruleParam; + } + return nextHandler.doHandler(ruleParam); + } + + /** + * 设置下游handler + * @param nextHandler + */ + public void setNextHandler(AbstractRuleChainHandler nextHandler) { + this.nextHandler = nextHandler; + } + +} diff --git a/solution-rule/src/main/java/com/solution/rule/handler/RuleChainHandler.java b/solution-rule/src/main/java/com/solution/rule/handler/RuleChainHandler.java new file mode 100644 index 0000000..42a5d33 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/handler/RuleChainHandler.java @@ -0,0 +1,47 @@ +package com.solution.rule.handler; + + +import cn.hutool.core.collection.CollUtil; +import com.solution.common.constant.ExceptionConstants; +import com.solution.rule.domain.RuleParam; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.List; + +/** + * 封装规则处理链 + */ +@Component +public class RuleChainHandler { + + @Resource + private List chainHandlers; + + private AbstractRuleChainHandler firstHandler; + + /** + * 组装处理链 + */ + @PostConstruct + private void constructChain(){ + if (CollUtil.isEmpty(chainHandlers)) { + throw new RuntimeException(ExceptionConstants.NOT_FOUND_CARRIAGE_CHAIN_HANDLER); + } + this.firstHandler = chainHandlers.get(0); + for (int i = 0; i < chainHandlers.size(); i++) { + if(i == (chainHandlers.size() - 1)){ + chainHandlers.get(i).setNextHandler(null); + }else { + chainHandlers.get(i).setNextHandler(chainHandlers.get(i + 1)); + } + } + + } + + public RuleParam findRuleParam(RuleParam ruleParam){ + return firstHandler.doHandler(ruleParam); + } + +} diff --git a/solution-rule/src/main/java/com/solution/rule/handler/WarplaneHandler.java b/solution-rule/src/main/java/com/solution/rule/handler/WarplaneHandler.java new file mode 100644 index 0000000..7896673 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/handler/WarplaneHandler.java @@ -0,0 +1,36 @@ +package com.solution.rule.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.solution.common.constant.ExceptionConstants; +import com.solution.common.constant.PlatformAndModuleConstants; +import com.solution.rule.domain.PlatformComponent; +import com.solution.rule.domain.RuleParam; +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.WeaponModelVO; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 战斗机处理链 + */ +@Component +public class WarplaneHandler extends AbstractRuleChainHandler{ + + @Override + public RuleParam doHandler(RuleParam ruleParam) { + if(ObjectUtil.isEmpty(ruleParam) || ObjectUtil.isEmpty(ruleParam.getWeaponModelDTO())){ + throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION); + } + WeaponModelDTO weaponModelDTO = ruleParam.getWeaponModelDTO(); + List platformComponents = weaponModelDTO.getComponents().stream() + .filter(component -> PlatformAndModuleConstants.F22.equals(component.getName())) + .collect(Collectors.toList()); + if (CollUtil.isEmpty(platformComponents)) { + throw new RuntimeException(ExceptionConstants.NOT_FOUND_F22_COMPONENT); + } + return null; + } +} diff --git a/solution-rule/src/main/java/com/solution/rule/mapper/ModelDetailMapper.java b/solution-rule/src/main/java/com/solution/rule/mapper/ModelDetailMapper.java new file mode 100644 index 0000000..903bf51 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/mapper/ModelDetailMapper.java @@ -0,0 +1,9 @@ +package com.solution.rule.mapper; + +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ModelDetailMapper { + + +} diff --git a/solution-rule/src/main/java/com/solution/rule/mapper/RuleMapper.java b/solution-rule/src/main/java/com/solution/rule/mapper/RuleMapper.java new file mode 100644 index 0000000..2208c46 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/mapper/RuleMapper.java @@ -0,0 +1,19 @@ +package com.solution.rule.mapper; + +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.WeaponModelVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface RuleMapper { + + /** + * 获取所有武器平台和组件 + * @return + */ + List getWeapon(); + + List getPlatformComponentNames(); +} diff --git a/solution-rule/src/main/java/com/solution/rule/service/RuleService.java b/solution-rule/src/main/java/com/solution/rule/service/RuleService.java new file mode 100644 index 0000000..694da7d --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/service/RuleService.java @@ -0,0 +1,29 @@ +package com.solution.rule.service; + +import com.solution.rule.domain.dto.RequestDTO; +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.PlatformComponentNamesVO; +import com.solution.rule.domain.vo.PlatformWeaponAggregateVO; +import com.solution.rule.domain.vo.WeaponModelVO; + +import java.util.HashMap; +import java.util.List; + +public interface RuleService { + + /** + * 开始执行规则匹配 + * @param sceneType + * @param weaponModelDTO + * @return + */ + WeaponModelVO execute(Integer sceneType, WeaponModelDTO weaponModelDTO); + + List getWeapon(); + + /** + * 获取所有武器平台和组件 + * @return + */ + List getPlatformComponentNames(); +} diff --git a/solution-rule/src/main/java/com/solution/rule/service/impl/RuleServiceImpl.java b/solution-rule/src/main/java/com/solution/rule/service/impl/RuleServiceImpl.java new file mode 100644 index 0000000..1dd9545 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/service/impl/RuleServiceImpl.java @@ -0,0 +1,109 @@ +package com.solution.rule.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.solution.common.constant.ExceptionConstants; +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.ComponentCountVO; +import com.solution.rule.domain.vo.PlatformComponentNamesVO; +import com.solution.rule.domain.vo.PlatformWeaponAggregateVO; +import com.solution.rule.domain.vo.WeaponModelVO; +import com.solution.rule.mapper.RuleMapper; +import com.solution.rule.service.RuleService; +import com.solution.rule.strategy.SceneStrategy; +import com.solution.rule.strategy.SceneStrategyFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class RuleServiceImpl implements RuleService { + + @Autowired + private SceneStrategyFactory strategyFactory; + + @Autowired + private RuleMapper ruleMapper; + + @Override + public WeaponModelVO execute(Integer sceneType, WeaponModelDTO weaponModelDTO) { + if(ObjectUtil.isNull(sceneType) || ObjectUtil.isEmpty(weaponModelDTO)){ + throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION); + } + //TODO 查数据库获取我方装备 + List weapon = this.getWeapon(); + + SceneStrategy strategy = strategyFactory.getStrategy(sceneType); + WeaponModelVO result = strategy.execute(weaponModelDTO); + if(ObjectUtil.isEmpty(result)){ + throw new RuntimeException(ExceptionConstants.RESULT_EXCEPTION); + } + return result; + } + + + + @Override + public List getWeapon() { + List flatList = ruleMapper.getWeapon(); + if (CollUtil.isEmpty(flatList)) { + throw new RuntimeException(ExceptionConstants.RESULT_EXCEPTION); + } + + Map> groupByPlatform = flatList.stream() + .collect(Collectors.groupingBy(WeaponModelVO::getPlatformName)); + + List result = new ArrayList<>(); + for (Map.Entry> entry : groupByPlatform.entrySet()) { + PlatformWeaponAggregateVO platformVO = new PlatformWeaponAggregateVO(); + platformVO.setPlatformName(entry.getKey()); + + List components = entry.getValue().stream() + .map(item -> { + ComponentCountVO comp = new ComponentCountVO(); + comp.setComponentName(item.getComponentName()); + comp.setCount(item.getCount()); + return comp; + }) + .collect(Collectors.toList()); + platformVO.setComponents(components); + + result.add(platformVO); + } + + return result; + } + + + /** + * 获取所有武器平台和组件 + * @return + */ + @Override + public List getPlatformComponentNames() { + List flatList = ruleMapper.getPlatformComponentNames(); + if (CollUtil.isEmpty(flatList)) { + throw new RuntimeException(ExceptionConstants.RESULT_EXCEPTION); + } + + + Map> groupByPlatform = flatList.stream() + .collect(Collectors.groupingBy( + WeaponModelVO::getPlatformName, + Collectors.mapping(WeaponModelVO::getComponentName, Collectors.toList()) + )); + + return groupByPlatform.entrySet().stream() + .map(entry -> { + PlatformComponentNamesVO vo = new PlatformComponentNamesVO(); + vo.setPlatformName(entry.getKey()); + vo.setComponentNames(entry.getValue()); + return vo; + }) + .collect(Collectors.toList()); + } +} diff --git a/solution-rule/src/main/java/com/solution/rule/strategy/AirborneStrategy.java b/solution-rule/src/main/java/com/solution/rule/strategy/AirborneStrategy.java new file mode 100644 index 0000000..6540140 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/strategy/AirborneStrategy.java @@ -0,0 +1,43 @@ +package com.solution.rule.strategy; + +import cn.hutool.core.util.ObjectUtil; +import com.solution.common.constant.ExceptionConstants; +import com.solution.rule.domain.RuleParam; +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.WeaponModelVO; +import com.solution.rule.enums.SceneType; +import com.solution.rule.handler.RuleChainHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + + +@Component +public class AirborneStrategy implements SceneStrategy{ + + + @Autowired + private RuleChainHandler ruleChainHandler; + /** + * 空降场景处理 + * @param weaponModelDTO + * @return + */ + @Override + public WeaponModelVO execute(WeaponModelDTO weaponModelDTO) { + if(ObjectUtil.isEmpty(weaponModelDTO)){ + throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION); + } + RuleParam ruleParam = new RuleParam(); + ruleParam.setWeaponModelDTO(weaponModelDTO); + ruleParam = ruleChainHandler.findRuleParam(ruleParam); + if(ObjectUtil.isEmpty(ruleParam.getWeaponModelVO())){ + throw new RuntimeException(ExceptionConstants.RESULT_EXCEPTION); + } + return ruleParam.getWeaponModelVO(); + } + + @Override + public SceneType getSceneType() { + return SceneType.AIRBORNE; + } +} diff --git a/solution-rule/src/main/java/com/solution/rule/strategy/DefenseStrategy.java b/solution-rule/src/main/java/com/solution/rule/strategy/DefenseStrategy.java new file mode 100644 index 0000000..e063702 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/strategy/DefenseStrategy.java @@ -0,0 +1,42 @@ +package com.solution.rule.strategy; + +import cn.hutool.core.util.ObjectUtil; +import com.solution.common.constant.ExceptionConstants; +import com.solution.rule.domain.RuleParam; +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.WeaponModelVO; +import com.solution.rule.enums.SceneType; +import com.solution.rule.handler.RuleChainHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class DefenseStrategy implements SceneStrategy{ + + + @Autowired + private RuleChainHandler ruleChainHandler; + /** + * 防御场景处理 + * @param weaponModelDTO + * @return + */ + @Override + public WeaponModelVO execute(WeaponModelDTO weaponModelDTO) { + if(ObjectUtil.isEmpty(weaponModelDTO)){ + throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION); + } + RuleParam ruleParam = new RuleParam(); + ruleParam.setWeaponModelDTO(weaponModelDTO); + ruleParam = ruleChainHandler.findRuleParam(ruleParam); + if(ObjectUtil.isEmpty(ruleParam.getWeaponModelVO())){ + throw new RuntimeException(ExceptionConstants.RESULT_EXCEPTION); + } + return ruleParam.getWeaponModelVO(); + } + + @Override + public SceneType getSceneType() { + return SceneType.DEFENSE; + } +} diff --git a/solution-rule/src/main/java/com/solution/rule/strategy/SceneStrategy.java b/solution-rule/src/main/java/com/solution/rule/strategy/SceneStrategy.java new file mode 100644 index 0000000..1e30b37 --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/strategy/SceneStrategy.java @@ -0,0 +1,15 @@ +package com.solution.rule.strategy; + +import com.solution.rule.domain.dto.RequestDTO; +import com.solution.rule.domain.dto.WeaponModelDTO; +import com.solution.rule.domain.vo.WeaponModelVO; +import com.solution.rule.enums.SceneType; + +import java.util.HashMap; + +public interface SceneStrategy { + + WeaponModelVO execute(WeaponModelDTO weaponModelDTO); + + SceneType getSceneType(); +} diff --git a/solution-rule/src/main/java/com/solution/rule/strategy/SceneStrategyFactory.java b/solution-rule/src/main/java/com/solution/rule/strategy/SceneStrategyFactory.java new file mode 100644 index 0000000..beb935a --- /dev/null +++ b/solution-rule/src/main/java/com/solution/rule/strategy/SceneStrategyFactory.java @@ -0,0 +1,45 @@ +package com.solution.rule.strategy; + +import com.solution.rule.enums.SceneType; +import com.solution.rule.strategy.SceneStrategy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +@Component +public class SceneStrategyFactory { + + @Autowired + private List strategyList; + + private final Map strategyMap = new EnumMap<>(SceneType.class); + + @PostConstruct + public void init() { + for (SceneStrategy strategy : strategyList) { + SceneType type = strategy.getSceneType(); + if (strategyMap.containsKey(type)) { + throw new IllegalStateException("重复的场景类型: " + type); + } + strategyMap.put(type, strategy); + } + } + + /** + * 根据前端传递的数字编码获取对应的策略 + * @param code 前端传递的数字 + * @return 策略实现 + * @throws IllegalArgumentException 如果编码无效或策略未注册 + */ + public SceneStrategy getStrategy(int code) { + SceneType type = SceneType.fromCode(code); + SceneStrategy strategy = strategyMap.get(type); + if (strategy == null) { + throw new IllegalArgumentException("未找到编码 " + code + " 对应的策略实现"); + } + return strategy; + } +} \ No newline at end of file diff --git a/solution-rule/src/main/resources/mapper/rule/RuleMapper.xml b/solution-rule/src/main/resources/mapper/rule/RuleMapper.xml new file mode 100644 index 0000000..38d7dc5 --- /dev/null +++ b/solution-rule/src/main/resources/mapper/rule/RuleMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file