Merge remote-tracking branch 'origin/master' into feature-transform-node-data

This commit is contained in:
2026-04-14 16:30:13 +08:00
14 changed files with 418 additions and 14 deletions

View File

@@ -64,4 +64,15 @@ public class SceneController extends BaseController {
public AjaxResult getAllTree(@PathVariable Integer id){
return success(sceneService.getAllTree(id));
}
/**
* 根据场景id获取场景下所有关系
* @param id
* @return
*/
@GetMapping("/getAllRelation/{id}")
@ApiOperation("根据场景id获取场景下所有关系")
public AjaxResult getAllRelation(@PathVariable Integer id){
return success(sceneService.getAllRelation(id));
}
}

View File

@@ -2,6 +2,7 @@ package com.solution.system.mapper;
import com.solution.system.domain.PlatformTree;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -20,5 +21,5 @@ public interface PlatformMapper {
* @param underlingEnglishName
* @return
*/
List<String> selectPlatformChineseName(List<String> underlingEnglishName);
List<String> selectPlatformChineseName(@Param("underlingEnglishName") List<String> underlingEnglishName);
}

View File

@@ -5,13 +5,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="com.solution.system.mapper.BehaviortreeMapper">
<resultMap type="Behaviortree" id="BehaviortreeResult">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="description" column="description" />
<result property="createdAt" column="created_at" />
<result property="updatedAt" column="updated_at" />
<result property="englishName" column="english_name" />
<result property="xmlContent" column="xml_content" />
<result property="id" column="id" />
<result property="name" column="name" />
<result property="description" column="description" />
<result property="createdAt" column="created_at" />
<result property="updatedAt" column="updated_at" />
<result property="englishName" column="english_name"/>
<result property="xmlContent" column="xml_content" />
<result property="platformId" column="platform_id" />
<result property="scenarioId" column="scenario_id" />
</resultMap>
<select id="findOneByPlatformId" resultMap="BehaviortreeResult">
@@ -37,7 +39,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectBehaviortreeById" parameterType="Long" resultMap="BehaviortreeResult">
<include refid="selectBehaviortreeVo"/>
select id, name, description, created_at, updated_at, english_name,graph, xml_content ,platform_id, scenario_id from behaviortree
where id = #{id}
</select>

View File

@@ -112,7 +112,7 @@
FROM platform p
LEFT JOIN platform_component pc ON p.id = pc.platform_id
WHERE pc.type = 'comm'
AND p.scenario_id = #{scenarioId}
AND p.scenario_id = #{scenarioId}
ORDER BY p.name,pc.name
</select>

View File

@@ -0,0 +1,67 @@
-- 规则主数据表结构MySQL 8+
-- 说明:用于前端按“层级->种类->规则项”进行展示与增删改查。
CREATE TABLE IF NOT EXISTS `rule_dict` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`dict_type` VARCHAR(32) NOT NULL COMMENT '字典类型(level/kind/task_type/status)',
`dict_code` VARCHAR(64) NOT NULL COMMENT '字典编码',
`dict_name` VARCHAR(64) NOT NULL COMMENT '字典名称',
`sort_no` INT NOT NULL DEFAULT 0 COMMENT '排序号',
`enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用(1是0否)',
`remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_rule_dict_type_code` (`dict_type`, `dict_code`),
KEY `idx_rule_dict_type_enabled` (`dict_type`, `enabled`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='规则字典表';
CREATE TABLE IF NOT EXISTS `rule_item` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`rule_code` VARCHAR(64) NOT NULL COMMENT '规则编码',
`rule_name` VARCHAR(128) NOT NULL COMMENT '规则名称',
`level_code` VARCHAR(32) NOT NULL COMMENT '规则层级(task/action/platform)',
`kind_code` VARCHAR(32) NOT NULL COMMENT '规则种类(select/assign/deploy/config/mode/spacetime/relation/limit)',
`module_code` VARCHAR(32) NOT NULL COMMENT '规则模块(equipment/target/position/track/group)',
`priority_no` INT NOT NULL DEFAULT 100 COMMENT '优先级(数字越小越先执行)',
`condition_expr` VARCHAR(1024) DEFAULT NULL COMMENT '条件表达式(展示用)',
`action_expr` VARCHAR(1024) DEFAULT NULL COMMENT '动作表达式(展示用)',
`version_no` INT NOT NULL DEFAULT 1 COMMENT '版本号',
`enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用(1是0否)',
`remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_rule_item_code` (`rule_code`),
KEY `idx_rule_item_level_kind` (`level_code`, `kind_code`),
KEY `idx_rule_item_module_enabled` (`module_code`, `enabled`),
KEY `idx_rule_item_priority` (`priority_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='规则主表';
CREATE TABLE IF NOT EXISTS `rule_item_task_type` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`rule_code` VARCHAR(64) NOT NULL COMMENT '规则编码',
`task_type_code` VARCHAR(32) NOT NULL COMMENT '任务类型编码',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_rule_task_type` (`rule_code`, `task_type_code`),
KEY `idx_rule_task_type` (`task_type_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='规则适用任务类型关联表';
CREATE TABLE IF NOT EXISTS `rule_item_param` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`rule_code` VARCHAR(64) NOT NULL COMMENT '规则编码',
`param_key` VARCHAR(128) NOT NULL COMMENT '参数键',
`param_val` TEXT NOT NULL COMMENT '参数值(统一文本存储)',
`val_type` VARCHAR(16) NOT NULL DEFAULT 'string' COMMENT '值类型(string/number/bool/json)',
`param_name` VARCHAR(128) DEFAULT NULL COMMENT '参数名称',
`sort_no` INT NOT NULL DEFAULT 0 COMMENT '排序号',
`enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用(1是0否)',
`remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_rule_param` (`rule_code`, `param_key`),
KEY `idx_rule_param_key` (`param_key`),
KEY `idx_rule_param_enabled` (`enabled`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='规则参数表';

View File

@@ -0,0 +1,213 @@
-- 从 rules/rule.drl 提取的初始化数据
-- 说明:本文件提供字典、规则主数据、规则参数与任务类型关联的初始记录。
-- 1) 字典数据
INSERT INTO `rule_dict` (`dict_type`, `dict_code`, `dict_name`, `sort_no`, `enabled`, `remark`) VALUES
('level', 'task', '任务级', 10, 1, '任务层面的选择/分配/限制'),
('level', 'action', '行动级', 20, 1, '行动层面的航迹/编组/模式'),
('level', 'platform', '平台级', 30, 1, '平台层面的部署/时空约束'),
('kind', 'select', '选择', 10, 1, '对象选择与评分'),
('kind', 'assign', '分配', 20, 1, '目标分配'),
('kind', 'deploy', '部署', 30, 1, '阵位与部署'),
('kind', 'config', '配置', 40, 1, '通用配置参数'),
('kind', 'mode', '工作模式', 50, 1, '算法与模式选择'),
('kind', 'spacetime', '时空约束', 60, 1, '空间和时间相关约束'),
('kind', 'relation', '关联关系', 70, 1, '蓝红关键词关联'),
('kind', 'limit', '限制条件', 80, 1, '阈值和边界'),
('task_type', 'strike', '打击任务', 10, 1, '典型任务类型'),
('task_type', 'recon', '侦察任务', 20, 1, '典型任务类型'),
('task_type', 'intercept', '拦截任务', 30, 1, '典型任务类型'),
('task_type', 'support', '支援任务', 40, 1, '典型任务类型'),
('task_type', 'jamming', '干扰任务', 50, 1, '典型任务类型'),
('status', 'enabled', '启用', 10, 1, '通用状态'),
('status', 'disabled', '停用', 20, 1, '通用状态')
ON DUPLICATE KEY UPDATE
`dict_name` = VALUES(`dict_name`),
`sort_no` = VALUES(`sort_no`),
`enabled` = VALUES(`enabled`),
`remark` = VALUES(`remark`);
-- 2) 规则主数据(层级->种类->规则项)
INSERT INTO `rule_item`
(`rule_code`, `rule_name`, `level_code`, `kind_code`, `module_code`, `priority_no`, `condition_expr`, `action_expr`, `version_no`, `enabled`, `remark`)
VALUES
('R_TASK_SELECT_BASE', '任务级-装备选择基础规则', 'task', 'select', 'equipment', 100, 'task!=null', 'equipmentRule(fact, params)', 1, 1, '来自装备匹配主流程'),
('R_TASK_SELECT_SLOT_1', '任务级-规则槽1', 'task', 'relation', 'equipment', 101, 'containsAny(blue,slot1Blue)&&containsAny(red,slot1Red)', 'score += ruleScore_1*weight', 1, 1, '蓝红关键词槽位匹配'),
('R_TASK_SELECT_SLOT_2', '任务级-规则槽2', 'task', 'relation', 'equipment', 102, 'containsAny(blue,slot2Blue)&&containsAny(red,slot2Red)', 'score += ruleScore_2*weight', 1, 1, '蓝红关键词槽位匹配'),
('R_TASK_SELECT_SLOT_3', '任务级-规则槽3', 'task', 'relation', 'equipment', 103, 'containsAny(blue,slot3Blue)&&containsAny(red,slot3Red)', 'score += ruleScore_3*weight', 1, 1, '蓝红关键词槽位匹配'),
('R_TASK_REL_AIR_PLATFORM', '任务级-关联关系-空中平台', 'task', 'relation', 'equipment', 104, 'bluePlatformKeywords_air && redPreferredWhenBlueAir', 'score += airScore*weight', 1, 1, '兼容层空中平台关联'),
('R_TASK_REL_AIR_TASK', '任务级-关联关系-空中任务', 'task', 'relation', 'equipment', 105, 'airTaskKeywords && redPreferredWhenBlueAir', 'score += airTaskScore*weight', 1, 1, '兼容层空中任务关联'),
('R_TASK_REL_GROUND_TASK', '任务级-关联关系-地面任务', 'task', 'relation', 'equipment', 106, 'groundTaskKeywords && redPreferredWhenGround', 'score += groundScore*weight', 1, 1, '兼容层地面任务关联'),
('R_TASK_REL_TANK', '任务级-关联关系-坦克装甲', 'task', 'relation', 'equipment', 107, 'tankKeywords && redMatchKeywords_tank', 'score += tankScore*weight', 1, 1, '兼容层坦克关联'),
('R_TASK_REL_MISSILE', '任务级-关联关系-导弹火箭', 'task', 'relation', 'equipment', 108, 'missileKeywords && redMatchKeywords_missile', 'score += missileScore*weight', 1, 1, '兼容层导弹关联'),
('R_TASK_ASSIGN_TARGET', '任务级-目标分配规则', 'task', 'assign', 'target', 90, 'task!=null', 'target(fact, params)', 1, 1, '目标分配与execute填充'),
('R_TASK_LIMIT_SUPPLEMENT', '任务级-低命中率补拿限制', 'task', 'limit', 'target', 89, 'hitRate<threshold', '补拿装备并更新任务', 1, 1, '补拿轮次和数量限制'),
('R_PLATFORM_DEPLOY', '平台级-阵位部署规则', 'platform', 'deploy', 'position', 80, 'positionRuleEnabled=true', 'position(fact, params)', 1, 1, '平台部署与编队参数'),
('R_PLATFORM_SPACETIME', '平台级-时空约束规则', 'platform', 'spacetime', 'position', 79, 'enableWarZoneClamp=true', '平台点位约束到作战区', 1, 1, '阵位空间约束'),
('R_ACTION_TRACK_ROUTE', '行动级-航迹生成规则', 'action', 'mode', 'track', 70, 'trackRuleEnabled=true', 'trackRoute(fact, params)', 1, 1, '航迹算法与路由绑定'),
('R_ACTION_TRACK_SPACETIME', '行动级-航迹时空约束', 'action', 'spacetime', 'track', 69, 'enableTrackWarZoneClamp=true', '航迹点约束到作战区', 1, 1, '航迹空间约束'),
('R_ACTION_GROUP_FORMATION', '行动级-编组规则', 'action', 'mode', 'group', 60, 'groupRuleEnabled=true', 'groupFormation(fact, params)', 1, 1, '编组与wingman规则')
ON DUPLICATE KEY UPDATE
`rule_name` = VALUES(`rule_name`),
`level_code` = VALUES(`level_code`),
`kind_code` = VALUES(`kind_code`),
`module_code` = VALUES(`module_code`),
`priority_no` = VALUES(`priority_no`),
`condition_expr` = VALUES(`condition_expr`),
`action_expr` = VALUES(`action_expr`),
`version_no` = VALUES(`version_no`),
`enabled` = VALUES(`enabled`),
`remark` = VALUES(`remark`);
-- 3) 规则参数(来自 rule.drl 的 buildParam
INSERT INTO `rule_item_param`
(`rule_code`, `param_key`, `param_val`, `val_type`, `param_name`, `sort_no`, `enabled`, `remark`)
VALUES
-- R_TASK_SELECT_BASE
('R_TASK_SELECT_BASE','weight','1','number','全局权重',10,1,'评分乘数'),
('R_TASK_SELECT_BASE','minSelectedScore','1','number','最小选中分',20,1,'低于该分不选中'),
('R_TASK_SELECT_BASE','tieBreak','equipmentId','string','并列决策方式',30,1,'equipmentId字典序'),
('R_TASK_SELECT_BASE','outputDrawNameSuffix','打击任务','string','输出任务后缀',40,1,'匹配成功后缀'),
('R_TASK_SELECT_BASE','ruleSlotCount','3','number','规则槽数量',50,1,'槽位匹配条数'),
-- R_TASK_SELECT_SLOT_1~3
('R_TASK_SELECT_SLOT_1','blueRuleKeywords_1','F-16,F-35','string','蓝方关键词1',10,1,'规则槽1'),
('R_TASK_SELECT_SLOT_1','redRuleKeywords_1','防空,导弹,无人机','string','红方关键词1',20,1,'规则槽1'),
('R_TASK_SELECT_SLOT_1','ruleScore_1','5','number','规则槽1分值',30,1,'规则槽1'),
('R_TASK_SELECT_SLOT_2','blueRuleKeywords_2','坦克,装甲','string','蓝方关键词2',10,1,'规则槽2'),
('R_TASK_SELECT_SLOT_2','redRuleKeywords_2','反坦克','string','红方关键词2',20,1,'规则槽2'),
('R_TASK_SELECT_SLOT_2','ruleScore_2','4','number','规则槽2分值',30,1,'规则槽2'),
('R_TASK_SELECT_SLOT_3','blueRuleKeywords_3','地面,突击','string','蓝方关键词3',10,1,'规则槽3'),
('R_TASK_SELECT_SLOT_3','redRuleKeywords_3','远火,榴弹,炮','string','红方关键词3',20,1,'规则槽3'),
('R_TASK_SELECT_SLOT_3','ruleScore_3','2','number','规则槽3分值',30,1,'规则槽3'),
-- R_TASK_REL_AIR_PLATFORM
('R_TASK_REL_AIR_PLATFORM','bluePlatformKeywords_air','F-16,J-10,F-35','string','蓝方空中平台关键词',10,1,'兼容层'),
('R_TASK_REL_AIR_PLATFORM','redPreferredWhenBlueAir','防空,导弹,无人机,直升机,空空','string','红方空中偏好关键词',20,1,'兼容层'),
('R_TASK_REL_AIR_PLATFORM','airScore','2','number','空中平台分值',30,1,'兼容层'),
-- R_TASK_REL_AIR_TASK
('R_TASK_REL_AIR_TASK','airTaskKeywords','空中,制空,拦截,空战','string','空中任务关键词',10,1,'兼容层'),
('R_TASK_REL_AIR_TASK','airTaskScore','10','number','空中任务分值',20,1,'兼容层'),
-- R_TASK_REL_GROUND_TASK
('R_TASK_REL_GROUND_TASK','groundTaskKeywords','地面,突击,登陆','string','地面任务关键词',10,1,'兼容层'),
('R_TASK_REL_GROUND_TASK','redPreferredWhenGround','远火,榴弹,炮,火箭','string','红方地面偏好关键词',20,1,'兼容层'),
('R_TASK_REL_GROUND_TASK','groundScore','1','number','地面任务分值',30,1,'兼容层'),
-- R_TASK_REL_TANK
('R_TASK_REL_TANK','tankKeywords','坦克,装甲','string','坦克关键词',10,1,'兼容层'),
('R_TASK_REL_TANK','redMatchKeywords_tank','反坦克','string','红方反坦克关键词',20,1,'兼容层'),
('R_TASK_REL_TANK','tankScore','1','number','坦克分值',30,1,'兼容层'),
-- R_TASK_REL_MISSILE
('R_TASK_REL_MISSILE','missileKeywords','导弹,火箭弹,巡航','string','导弹关键词',10,1,'兼容层'),
('R_TASK_REL_MISSILE','redMatchKeywords_missile','防空,导弹,导弹发射','string','红方导弹匹配关键词',20,1,'兼容层'),
('R_TASK_REL_MISSILE','missileScore','1','number','导弹分值',30,1,'兼容层'),
-- R_TASK_ASSIGN_TARGET
('R_TASK_ASSIGN_TARGET','executeTypeDefault','assault','string','执行类型默认值',10,1,'目标分配'),
('R_TASK_ASSIGN_TARGET','targetPickMode','roundRobin','string','目标选择模式',20,1,'roundRobin/random'),
('R_TASK_ASSIGN_TARGET','minTargetsPerRed','1','number','每红装最少目标数',30,1,'目标分配'),
('R_TASK_ASSIGN_TARGET','maxTargetsPerRedCap','3','number','每红装最多目标数',40,1,'目标分配'),
('R_TASK_ASSIGN_TARGET','radToTargetsCsv','0.8:1,0.5:2,0.2:3','string','命中率映射目标数',50,1,'阈值映射'),
('R_TASK_ASSIGN_TARGET','rangeParseRegex','(\\\\d+(?:\\\\.\\\\d+)?)','string','射程提取正则',60,1,'提取首个数字'),
('R_TASK_ASSIGN_TARGET','rangeUnit','km','string','射程单位',70,1,'km/m'),
('R_TASK_ASSIGN_TARGET','minRangeToAllowAssignKm','0','number','允许分配最小射程',80,1,'射程过滤'),
-- R_TASK_LIMIT_SUPPLEMENT
('R_TASK_LIMIT_SUPPLEMENT','redHitRateThreshold','0.6','number','红装命中率阈值',10,1,'低于阈值触发补拿'),
('R_TASK_LIMIT_SUPPLEMENT','maxExtraWeaponsPerTask','2','number','每任务最大补拿装备数',20,1,'限制条件'),
('R_TASK_LIMIT_SUPPLEMENT','maxSupplementRounds','2','number','补拿最大轮次',30,1,'防止死循环'),
('R_TASK_LIMIT_SUPPLEMENT','extraPickMinScore','1','number','补拿最小匹配分',40,1,'限制条件'),
-- R_PLATFORM_DEPLOY
('R_PLATFORM_DEPLOY','positionRuleEnabled','true','bool','是否启用阵位规则',10,1,'部署开关'),
('R_PLATFORM_DEPLOY','positionAnchorMode','hybrid','string','阵位锚点模式',20,1,'当前使用hybrid'),
('R_PLATFORM_DEPLOY','trackPointDirectionMode','head2next','string','航向计算模式',30,1,'head2next/tail2prev'),
('R_PLATFORM_DEPLOY','fallbackBearingDeg','0','number','默认航向角',40,1,'无法计算时回退'),
('R_PLATFORM_DEPLOY','deployDistanceKmMin','8','number','部署距离最小值(km)',50,1,'部署约束'),
('R_PLATFORM_DEPLOY','deployDistanceKmMax','30','number','部署距离最大值(km)',60,1,'部署约束'),
('R_PLATFORM_DEPLOY','deployDistanceKmDefault','15','number','默认部署距离(km)',70,1,'部署距离'),
('R_PLATFORM_DEPLOY','distanceByPlatformCsv','','string','按平台覆盖部署距离',80,1,'关键词:距离'),
('R_PLATFORM_DEPLOY','formationType','line','string','编队样式',90,1,'line/wedge/circle'),
('R_PLATFORM_DEPLOY','formationSpacingMeters','300','number','编队间距(米)',100,1,'部署参数'),
('R_PLATFORM_DEPLOY','formationHeadingOffsetDeg','15','number','编队偏转角(度)',110,1,'部署参数'),
('R_PLATFORM_DEPLOY','defaultDeployHeight','30','number','默认部署高度(米)',120,1,'部署参数'),
('R_PLATFORM_DEPLOY','heightFollowBlueRatio','0.0','number','高度跟随比例',130,1,'部署参数'),
('R_PLATFORM_DEPLOY','warZoneClampMode','nearestInside','string','作战区约束模式',140,1,'部署约束'),
('R_PLATFORM_DEPLOY','minInterPlatformDistanceMeters','80','number','平台最小间距(米)',150,1,'部署约束'),
-- R_PLATFORM_SPACETIME
('R_PLATFORM_SPACETIME','enableWarZoneClamp','true','bool','是否启用作战区约束',10,1,'平台时空约束'),
-- R_ACTION_TRACK_ROUTE
('R_ACTION_TRACK_ROUTE','trackRuleEnabled','true','bool','是否启用航迹规则',10,1,'航迹开关'),
('R_ACTION_TRACK_ROUTE','trackRouteAlgorithm','followBlue','string','航迹算法',20,1,'followBlue/shortestPath/flank/jam'),
('R_ACTION_TRACK_ROUTE','trackRouteNameSuffix','航迹','string','航迹名称后缀',30,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackAirDataTypeCsv','taskPlane,air,plane,flight','string','空中航迹dataType关键词',40,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackAirKeywordsCsv','机,飞,空,J-,F-,无人机,直升机','string','空中航迹关键词',50,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackGroundTrackType','routeLineGround','string','地面航迹类型',60,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackFallbackBearingDeg','0','number','航迹默认回退航向角',70,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackExtraNodesMax','0','number','航迹额外插点上限',80,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackShortPathSegments','3','number','最短路径插值分段',90,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackFlankOffsetMeters','800','number','flank偏移距离(米)',100,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackFlankSideMode','alternate','string','flank侧向模式',110,1,'alternate/left/right'),
('R_ACTION_TRACK_ROUTE','trackJamWobbleMeters','400','number','jam摆动振幅(米)',120,1,'行动模式'),
('R_ACTION_TRACK_ROUTE','trackJamSegments','4','number','jam摆动周期数',130,1,'行动模式'),
-- R_ACTION_TRACK_SPACETIME
('R_ACTION_TRACK_SPACETIME','enableTrackWarZoneClamp','true','bool','是否启用航迹作战区约束',10,1,'行动时空约束'),
-- R_ACTION_GROUP_FORMATION
('R_ACTION_GROUP_FORMATION','groupRuleEnabled','true','bool','是否启用编组规则',10,1,'编组开关'),
('R_ACTION_GROUP_FORMATION','groupDrawNameSuffix','编组','string','编组名称后缀',20,1,'编组规则'),
('R_ACTION_GROUP_FORMATION','groupDrawNameWithIndex','false','bool','编组名称是否加序号',30,1,'编组规则'),
('R_ACTION_GROUP_FORMATION','groupFormationMode','onePerRed','string','编组模式',40,1,'onePerRed/clusterByCount/singleGroup'),
('R_ACTION_GROUP_FORMATION','groupClusterSize','3','number','按人数编组的每组上限',50,1,'编组规则'),
('R_ACTION_GROUP_FORMATION','groupLeaderPickMode','byHitRateThenId','string','领队选择模式',60,1,'byHitRateThenId/byId'),
('R_ACTION_GROUP_FORMATION','groupMinMembersForWingman','2','number','生成僚机的最小人数',70,1,'编组规则'),
('R_ACTION_GROUP_FORMATION','wingmanDistanceBaseMeters','100','number','僚机基础距离(米)',80,1,'编组几何'),
('R_ACTION_GROUP_FORMATION','wingmanDistanceStepMeters','50','number','僚机距离步长(米)',90,1,'编组几何'),
('R_ACTION_GROUP_FORMATION','wingmanAngleBaseDeg','50','number','僚机基础角度(度)',100,1,'编组几何'),
('R_ACTION_GROUP_FORMATION','wingmanAngleStepDeg','15','number','僚机角度步长(度)',110,1,'编组几何'),
('R_ACTION_GROUP_FORMATION','wingmanAltBaseMeters','40','number','僚机基础高度(米)',120,1,'编组几何'),
('R_ACTION_GROUP_FORMATION','wingmanAltScale','1.0','number','僚机高度缩放系数',130,1,'编组几何')
ON DUPLICATE KEY UPDATE
`param_val` = VALUES(`param_val`),
`val_type` = VALUES(`val_type`),
`param_name` = VALUES(`param_name`),
`sort_no` = VALUES(`sort_no`),
`enabled` = VALUES(`enabled`),
`remark` = VALUES(`remark`);
-- 4) 规则适用任务类型(默认全部规则覆盖五类任务,后续可在前端按需调整)
INSERT INTO `rule_item_task_type` (`rule_code`, `task_type_code`)
SELECT r.rule_code, t.task_type_code
FROM (
SELECT 'R_TASK_SELECT_BASE' AS rule_code
UNION ALL SELECT 'R_TASK_SELECT_SLOT_1'
UNION ALL SELECT 'R_TASK_SELECT_SLOT_2'
UNION ALL SELECT 'R_TASK_SELECT_SLOT_3'
UNION ALL SELECT 'R_TASK_REL_AIR_PLATFORM'
UNION ALL SELECT 'R_TASK_REL_AIR_TASK'
UNION ALL SELECT 'R_TASK_REL_GROUND_TASK'
UNION ALL SELECT 'R_TASK_REL_TANK'
UNION ALL SELECT 'R_TASK_REL_MISSILE'
UNION ALL SELECT 'R_TASK_ASSIGN_TARGET'
UNION ALL SELECT 'R_TASK_LIMIT_SUPPLEMENT'
UNION ALL SELECT 'R_PLATFORM_DEPLOY'
UNION ALL SELECT 'R_PLATFORM_SPACETIME'
UNION ALL SELECT 'R_ACTION_TRACK_ROUTE'
UNION ALL SELECT 'R_ACTION_TRACK_SPACETIME'
UNION ALL SELECT 'R_ACTION_GROUP_FORMATION'
) r
CROSS JOIN (
SELECT 'strike' AS task_type_code
UNION ALL SELECT 'recon'
UNION ALL SELECT 'intercept'
UNION ALL SELECT 'support'
UNION ALL SELECT 'jamming'
) t
ON DUPLICATE KEY UPDATE
`task_type_code` = VALUES(`task_type_code`);

View File

@@ -1,4 +1,4 @@
package com.solution.system.domain;
package com.solution.scene.domain;
import lombok.Data;

View File

@@ -2,6 +2,7 @@ package com.solution.scene.mapper;
import com.solution.scene.domain.AfsimScenario;
import com.solution.scene.domain.AfsimScenarioForm;
import com.solution.scene.domain.PlatformCommunication;
import com.solution.system.domain.Behaviortree;
import org.apache.ibatis.annotations.Mapper;
@@ -34,4 +35,11 @@ public interface SceneMapper {
* @return
*/
List<Behaviortree> selectAllTreeBySceneId(Integer id);
/**
* 根据场景id获取场景下所有关系
* @param id
* @return
*/
List<PlatformCommunication> selectAllRelationBySceneId(Integer id);
}

View File

@@ -2,6 +2,7 @@ package com.solution.scene.service;
import com.solution.scene.domain.AfsimScenario;
import com.solution.scene.domain.AfsimScenarioForm;
import com.solution.scene.domain.PlatformCommunication;
import com.solution.system.domain.Behaviortree;
import java.util.List;
@@ -33,4 +34,11 @@ public interface SceneService {
* @return
*/
List<Behaviortree> getAllTree(Integer id);
/**
* 根据场景id获取场景下所有关系
* @param id
* @return
*/
List<PlatformCommunication> getAllRelation(Integer id);
}

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import com.solution.common.constant.ExceptionConstants;
import com.solution.scene.domain.AfsimScenario;
import com.solution.scene.domain.AfsimScenarioForm;
import com.solution.scene.domain.PlatformCommunication;
import com.solution.scene.mapper.PlatFormCommunicationMapper;
import com.solution.scene.mapper.SceneMapper;
import com.solution.scene.service.SceneService;
@@ -90,4 +91,18 @@ public class SceneServiceImpl implements SceneService {
return allTree;
}
/**
* 根据场景id获取场景下所有关系
* @param id
* @return
*/
@Override
public List<PlatformCommunication> getAllRelation(Integer id) {
List<PlatformCommunication> result = sceneMapper.selectAllRelationBySceneId(id);
if(CollUtil.isEmpty( result)){
throw new RuntimeException("该场景下不存在关系");
}
return result;
}
}

View File

@@ -31,6 +31,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
FROM behaviortree
WHERE scenario_id=#{id}
</select>
<select id="selectAllRelationBySceneId" resultType="com.solution.scene.domain.PlatformCommunication"
parameterType="java.lang.Integer">
SELECT id,command_platform,subordinate_platform,command_comm,subordinate_comm,scenary_id
FROM platform_communication
WHERE scenary_id = #{id}
</select>
<insert id="update" parameterType="com.solution.scene.domain.AfsimScenario">
update afsim_scenario

View File

@@ -28,6 +28,10 @@ export const findOneTreeByPlatformId = (platformId: number): Promise<BehaviorTre
return req.get(`/system/behaviortree/platform/${platformId}`);
};
export const findSubPlatforms = (treeId: number): Promise<BehaviorTreeDetailsResponse> => {
return req.get(`/system/behaviortree/underling/${treeId}`);
};
export const findOneTreeById = (id: number): Promise<BehaviorTreeDetailsResponse> => {
return req.get(`/system/behaviortree/${id}`);
};

View File

@@ -43,6 +43,7 @@
<Properties
v-if="graph"
:platforms="platforms"
:sub-platforms="subPlatforms"
:nodeCommands="nodeCommands"
:element="selectedNodeTaskElement"
:graph="(graph as any)"
@@ -75,7 +76,7 @@ import { createGraphTaskElement, createLineOptions, type GraphContainer, type Gr
import { registerNodeElement } from './register';
import { findAllBasicPlatforms, findAllNodeCommands } from '../api';
import type { NodeCommand, Platform } from '../types';
import { createTree, findOneTreeById, findOneTreeByPlatformId, updateTree } from './api';
import { createTree, findOneTreeById, findOneTreeByPlatformId, updateTree, findSubPlatforms } from './api';
import TressCard from './trees-card.vue';
import NodesCard from './nodes-card.vue';
@@ -112,6 +113,7 @@ export default defineComponent({
const changed = ref<boolean>(false);
const treesCardRef = ref<InstanceType<typeof TressCard> | null>(null);
const platforms = ref<Platform[]>([]);
const subPlatforms = ref<Platform[]>([]);
const nodeCommands = ref<NodeCommand[]>([])
const currentScenarioId = ref<number | null>(null);
const currentPlatformId = ref<number | null>(null);
@@ -153,6 +155,27 @@ export default defineComponent({
loadNodeCommands();
}
// 加载下属平台
const loadSubPlatforms = (treeId: number) => {
console.log(treeId);
if (!treeId || treeId <= 0) {
subPlatforms.value = [];
return;
}
findSubPlatforms(treeId).then(r => {
if (r.data && Array.isArray(r.data)) {
subPlatforms.value = r.data as Platform[];
} else {
subPlatforms.value = [];
}
}).catch(err => {
console.error('加载下属平台失败:', err);
subPlatforms.value = [];
});
};
// 处理拖动开始
const handleDragStart = (nm: NodeDragTemplate) => {
draggedNodeData.value = nm;
@@ -267,6 +290,10 @@ export default defineComponent({
graph: nodeGraph,
};
currentTreeEditing.value = true;
// 加载下属平台
loadSubPlatforms(r.data.id);
nextTick(() => {
initGraph();
});
@@ -343,6 +370,7 @@ export default defineComponent({
};
selectedModelNode.value = null;
selectedNodeTaskElement.value = null;
subPlatforms.value = []; // 重置下属平台
nextTick(() => {
initGraph();
@@ -487,6 +515,7 @@ export default defineComponent({
nodeCommands,
currentScenarioId,
platforms,
subPlatforms,
treesCardRef,
handleCreateTree,
currentTreeEditing,

View File

@@ -101,7 +101,7 @@
size="small"
type="editable-card"
@edit="onEditParameterTab">
<a-tab-pane v-for="(grouped,index) in groupedParameters" :key="index" :tab="`平台 ${index + 1}`" :closable="true">
<a-tab-pane v-for="(grouped,index) in groupedParameters" :key="index" :tab="getPlatformTabName(index)" :closable="true">
<a-form-item v-for="setting in grouped" :label="setting.description">
<a-input-number v-if="setting.dataType === 'double'"
v-model:value="setting.defaultValue"
@@ -109,7 +109,7 @@
<a-select :placeholder="`请选择${setting.description}`"
allow-clear
v-else-if="setting.paramKey === 'platforms'" v-model:value="setting.defaultValue">
<a-select-option v-for="pl in platforms" :value="pl.name">{{pl.description}}</a-select-option>
<a-select-option v-for="pl in getAvailablePlatforms()" :value="pl.name">{{pl.description}}</a-select-option>
</a-select>
<a-select :placeholder="`请选择${setting.description}`"
allow-clear
@@ -194,11 +194,13 @@ export default defineComponent({
node: { type: [Object, null] as PropType<Node<NodeProperties> | null | undefined>, required: false },
graph: { type: [Object, null] as PropType<Graph | null | undefined>, required: true },
platforms: { type: Array as PropType<Platform[]>, required: true },
subPlatforms: { type: Array as PropType<Platform[]>, required: false, default: () => [] },
nodeCommands: { type: Array as PropType<NodeCommand[]>, required: true },
},
emits: ['update-element', 'update-tree'],
setup(props, { emit }) {
const platforms = ref<Platform[]>(props.platforms ?? []);
const subPlatforms = ref<Platform[]>(props.subPlatforms ?? []);
const nodeCommands = ref<NodeCommand[]>(props.nodeCommands ?? []);
const activeTopTabsKey = ref<string>('1');
@@ -299,6 +301,41 @@ export default defineComponent({
multiableParameters.value = multiable === true && groupedParameters.value.length > 0;
};
// 获取平台Tab显示名称
const getPlatformTabName = (index: number): string => {
if (!currentTree.value?.platformId) {
return `平台 ${index + 1}`;
}
// 查找当前行为树绑定的平台
const currentPlatform = platforms.value.find(p => p.id === currentTree.value?.platformId);
if (!currentPlatform) {
return `平台 ${index + 1}`;
}
// 如果有多个分组,显示平台名称和索引
if (groupedParameters.value.length > 1) {
return `${currentPlatform.name || '未知平台'}-${index + 1}`;
}
return currentPlatform.name || '平台';
};
// 获取可用的平台列表(包括当前平台和其下属平台)
const getAvailablePlatforms = (): Platform[] => {
if (!currentTree.value?.platformId) {
return platforms.value;
}
// 如果有下属平台,返回下属平台列表
if (subPlatforms.value && subPlatforms.value.length > 0) {
return subPlatforms.value;
}
// 否则返回所有平台
return platforms.value;
};
const resolveNode = (n?: Node | null | undefined) => {
groupedParametersActiveTab.value = 0;
@@ -389,6 +426,7 @@ export default defineComponent({
watch(() => props.nodeCommands, (n: NodeCommand[] | null | undefined) => nodeCommands.value = n ?? [], { deep: true, immediate: true });
watch(() => props.platforms, (n: Platform[] | null | undefined) => platforms.value = n ?? [], { deep: true, immediate: true });
watch(() => props.subPlatforms, (n: Platform[] | null | undefined) => subPlatforms.value = n ?? [], { deep: true, immediate: true });
onMounted(() => load());
@@ -400,6 +438,8 @@ export default defineComponent({
multiableParameters,
onEditParameterTab,
groupedParameters,
getPlatformTabName,
getAvailablePlatforms,
actionSpaceColumns,
activeTopTabsKey,
activeBottomTabsKey,