This commit is contained in:
2026-04-09 16:19:08 +08:00
80 changed files with 9181 additions and 366 deletions

9
.dockerignore Normal file
View File

@@ -0,0 +1,9 @@
**/target/
**/.git/
**/.idea/
**/*.iml
**/.vscode/
**/node_modules/
**/*.log
**/.DS_Store
**/uploadPath/

15
.env.example Normal file
View File

@@ -0,0 +1,15 @@
# 复制为 .env 后 docker compose 会自动加载
# copy .env.example .env
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=autosolution_db
MYSQL_PORT=3307
REDIS_PASSWORD=123456
REDIS_PORT=6379
APP_PORT=1777
APP_IMAGE_TAG=latest
# JVM 可选
# JAVA_OPTS=-Xms512m -Xmx1024m

4
.gitignore vendored
View File

@@ -38,6 +38,10 @@ dist/
nbdist/
.nb-gradle/
######################################################################
# Docker / local secrets
.env
######################################################################
# Others
*.log

18
Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
# 运行已打包的 JAR不依赖源码目录
# 要求构建上下文中存在 solution-admin.jar
# 构建docker build -t auto-solution-admin:latest .
FROM eclipse-temurin:11-jre-jammy
LABEL org.opencontainers.image.title="auto-solution-admin"
WORKDIR /app
RUN mkdir -p /app/uploadPath
COPY solution-admin.jar /app/app.jar
ENV TZ=Asia/Shanghai \
JAVA_OPTS="-Xms512m -Xmx1024m"
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app/app.jar --spring.profiles.active=druid,docker"]

View File

@@ -4,6 +4,7 @@ import com.solution.common.core.controller.BaseController;
import com.solution.common.core.domain.AjaxResult;
import com.solution.rule.domain.FireRuleExecuteDTO;
import com.solution.rule.domain.simplerulepojo.Task;
import com.solution.rule.domain.ultimately.dto.FireRuleInputDTO;
import com.solution.rule.service.FireRuleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -85,6 +86,14 @@ public class FireRuleController extends BaseController {
return success(ruleService.getComponents(platformId));
}
/* @PostMapping("/rule")
@ApiOperation("开始执行规则匹配")
public AjaxResult execute(@RequestBody Task task){
return success(ruleService.executeTask(task));
}*/
/**
* 开始执行规则匹配
* @param task 敌方参数
@@ -92,7 +101,10 @@ public class FireRuleController extends BaseController {
*/
@PostMapping("/rule")
@ApiOperation("开始执行规则匹配")
public AjaxResult execute(@RequestBody Task task){
return success(ruleService.executeTask(task));
public AjaxResult rule(@RequestBody FireRuleInputDTO task){
return success(ruleService.rule(task));
}
}

View File

@@ -0,0 +1,23 @@
# Docker / docker-compose 环境:与 application.yml 的 druid 配置叠加使用
# 启动:-Dspring.profiles.active=druid,docker
spring:
devtools:
restart:
enabled: false
redis:
host: ${REDIS_HOST:redis}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD:}
database: ${REDIS_DB:0}
datasource:
druid:
master:
url: jdbc:mysql://${MYSQL_HOST:mysql}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:autosolution_db}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
username: ${MYSQL_USER:root}
password: ${MYSQL_PASSWORD:root}
server:
port: ${SERVER_PORT:8080}
solution:
profile: ${SOLUTION_UPLOAD_PATH:/app/uploadPath}

View File

@@ -0,0 +1,33 @@
package com.solution.rule.config;
import java.util.HashMap;
import java.util.Map;
/**
* 装备匹配规则默认参数,与 {@code resources/rules/rule.drl} 中 {@code buildParam} 键保持一致。
*/
public final class FireRuleMatchDefaultParams {
private FireRuleMatchDefaultParams() {
}
public static Map<String, Object> defaults() {
Map<String, Object> param = new HashMap<>();
param.put("weight", 1);
param.put("minSelectedScore", 1);
param.put("tankScore", 1);
param.put("airScore", 2);
param.put("groundScore", 1);
param.put("missileScore", 1);
param.put("airTaskScore", 10);
param.put("bluePlatformKeywords_air", "F-16,J-10,F-35");
param.put("redPreferredWhenBlueAir", "防空,导弹,无人机,直升机,空空");
param.put("redPreferredWhenGround", "远火,榴弹,炮,火箭");
param.put("airTaskKeywords", "空中,制空,拦截,空战");
param.put("groundTaskKeywords", "地面,突击,登陆");
param.put("tankKeywords", "坦克,装甲");
param.put("missileKeywords", "导弹,火箭弹,巡航");
param.put("tieBreak", "equipmentId");
return param;
}
}

View File

@@ -39,4 +39,16 @@ public class Task {
//防区经纬高
private List<Coordinate> defZoneLocation;
//阵型类型TRIANGLE/DIAMOND/LINE/COLUMN/WEDGE
private String formationType;
//阵型基础间距(米)
private Integer formationSpacingMeters;
//主僚标准距离(米)
private Integer mainWingDistanceMeters;
//阵型朝向0~359
private Integer formationHeadingDeg;
}

View File

@@ -30,4 +30,13 @@ public class Weapon {
//目标id
private String targetId;
//编队角色MAIN=主机WING=僚机
private String formationRole;
//僚机相对主机距离(米)
private Integer wingRelativeDistanceMeters;
//僚机相对主机方位角(度)
private Integer wingRelativeBearingDeg;
}

View File

@@ -0,0 +1,32 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 装备组件参数项
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleComponentParamDTO {
/**
* 参数唯一标识
*/
private String uuid;
/**
* 属性默认值
*/
private String attDefaultValue;
/**
* 属性说明
*/
private String attExplain;
/**
* 数量
*/
private Integer number;
}

View File

@@ -0,0 +1,27 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 经纬高坐标点
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleCoordinateDTO {
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
/**
* 高程(米)
*/
private Double height;
}

View File

@@ -0,0 +1,13 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputArithmeticRefDTO {
private String id;
private String name;
}

View File

@@ -0,0 +1,37 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 火力规则输入根文档,与 {@code 火力规则输入-无注释.json} 顶层字段对应。
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputDTO {
/**
* 来源场景文件名
*/
private String sourceFile;
/**
* 蓝方任务列表
*/
private List<FireRuleTaskInputDTO> tasks;
/**
* 红方装备等条目列表,对应 JSON 键 {@code redWeapons}(当前 {@link FireRuleInputRedWeaponElementDTO} 与装备结构一致)
*/
@JsonProperty("equipments")
private List<FireRuleInputRedWeaponElementDTO> equipments;
/**
* 阵营与姿态关系列表,对应 JSON 键 {@code ForceSides}
*/
@JsonProperty("ForceSides")
private List<FireRuleInputForceSideDTO> forceSides;
}

View File

@@ -0,0 +1,15 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputDeviceRefDTO {
private String id;
private String name;
private String refId;
}

View File

@@ -0,0 +1,19 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 阵营侧一方与其它方的姿态关系项
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputForcePostureDTO {
@JsonProperty("ObjectHandle")
private String objectHandle;
@JsonProperty("Type")
private Integer type;
}

View File

@@ -0,0 +1,26 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 阵营侧ForceSides 数组中的一项)
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputForceSideDTO {
private String groupType;
@JsonProperty("Postures")
private List<FireRuleInputForcePostureDTO> postures;
@JsonProperty("ObjectHandle")
private String objectHandle;
@JsonProperty("ForceSideName")
private String forceSideName;
}

View File

@@ -0,0 +1,17 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputLauncherConfigurationDTO {
private String classifyName;
private Integer isMount;
private FireRuleInputMountedWeaponRefDTO mountedWeapon;
private Integer number;
}

View File

@@ -0,0 +1,15 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputMountedWeaponRefDTO {
@JsonProperty("_id")
private String id;
private String name;
}

View File

@@ -0,0 +1,37 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputRedCommSlotDTO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleInputArithmeticRefDTO arithmetic;
private FireRuleInputDeviceRefDTO device;
private String deviceId;
private String deviceName;
private Boolean employLabel;
private String facilityName;
private String soleId;
private Map<String, Object> twiceModified;
private List<Object> zLists;
@JsonProperty("ParentPlat")
private String parentPlat;
}

View File

@@ -0,0 +1,33 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputRedMotorizedSlotDTO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleInputArithmeticRefDTO arithmetic;
private FireRuleInputDeviceRefDTO device;
private String deviceId;
private String deviceName;
private String soleId;
@JsonProperty("ParentPlat")
private String parentPlat;
private Map<String, Object> twiceModified;
private List<Object> zLists;
}

View File

@@ -0,0 +1,42 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputRedPlatformSlotDTO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleInputArithmeticRefDTO arithmetic;
private FireRuleInputDeviceRefDTO device;
private String deviceId;
private String deviceName;
private Boolean employLabel;
private String facilityName;
private String soleId;
private Map<String, Object> twiceModified;
private List<Object> zLists;
@JsonProperty("TrackParamId")
private String trackParamId;
private List<Double> positions;
@JsonProperty("ParentPlat")
private String parentPlat;
}

View File

@@ -0,0 +1,21 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputRedSubComponentsDTO {
private List<FireRuleInputRedCommSlotDTO> communication;
@JsonProperty("motorized_assembly")
private List<FireRuleInputRedMotorizedSlotDTO> motorizedAssembly;
private List<FireRuleInputRedPlatformSlotDTO> platform;
private List<FireRuleInputRedWeaponSlotDTO> weapon;
}

View File

@@ -0,0 +1,52 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Map;
/**
* {@code redWeapons} 中红方装备platform条目与 {@code 火力规则输入-无注释.json} 中带
* {@code SubComponents} 的装备对象字段一致。
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputRedWeaponElementDTO {
@JsonProperty("SupportType")
private String supportType;
@JsonProperty("TroopsDetail")
private Map<String, Object> troopsDetail;
@JsonProperty("Platform_type")
private String platformType;
private Boolean isStrikeTarget;
private Boolean isReconTarget;
private Boolean isInterferenceTarget;
private Boolean isDefendImportantPlace;
//命中率
private Double successTargetRad;
private String groupType;
@JsonProperty("EquipmentID")
private String equipmentId;
@JsonProperty("Name")
private String name;
@JsonProperty("OwnerForceSide")
private String ownerForceSide;
@JsonProperty("PlatID")
private String platId;
@JsonProperty("SubComponents")
private FireRuleInputRedSubComponentsDTO subComponents;
}

View File

@@ -0,0 +1,43 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleInputRedWeaponSlotDTO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleInputArithmeticRefDTO arithmetic;
private String codedQueue;
private FireRuleInputLauncherConfigurationDTO configuration;
private FireRuleInputDeviceRefDTO device;
private String deviceId;
private String deviceName;
private Boolean employLabel;
private String facilityName;
private String serialNumber;
private String soleId;
private Map<String, Object> twiceModified;
private List<Object> zLists;
@JsonProperty("ParentPlat")
private String parentPlat;
}

View File

@@ -0,0 +1,64 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 单条火力规则任务输入(蓝方多任务时为列表中的一项)
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTaskInputDTO {
/**
* 任务唯一标识
*/
private String id;
/**
* 任务名称
*/
private String drawName;
/**
* 任务类型
*/
private String dataType;
/**
* 任务所属阵营
*/
private String side;
/**
* 蓝方任务装备命中率
*/
private Double successTargetRad;
/**
* 航迹所属实体或阵营标识
*/
private String trackPointsId;
/**
* 任务航迹点列表
*/
private List<FireRuleTrackPointDTO> trackPoints;
/**
* 任务武器配置列表
*/
private List<FireRuleTaskWeaponDTO> taskWeapons;
/**
* 任务目标 id
*/
private String targetId;
/**
* 作战区经纬高坐标列表
*/
private List<FireRuleCoordinateDTO> warZoneLocation;
}

View File

@@ -0,0 +1,50 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 任务挂载的武器配置
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTaskWeaponDTO {
/**
* 装备 id武器唯一标识
*/
private String equipmentId;
/**
* 装备名称
*/
private String name;
/**
* 装备类型
*/
private String supportType;
/**
* 装备组件列表
*/
private List<FireRuleWeaponComponentDTO> components;
/**
* 装备部署位置
*/
private FireRuleCoordinateDTO coordinate;
/**
* 武器数量;对应 JSON 键 {@code number}。{@code _comment_number} 为注释键,不映射。
* 可为数值或业务文案(如「最大载弹量」)。
*/
private Object number;
/**
* 该武器打击目标 id
*/
private String targetId;
}

View File

@@ -0,0 +1,37 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 任务航迹点
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTrackPointDTO {
/**
* 航迹点序号
*/
private Integer index;
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
/**
* 高度
*/
private Double height;
/**
* 速度
*/
private Double speed;
}

View File

@@ -0,0 +1,29 @@
package com.solution.rule.domain.ultimately.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 任务武器下的设备组件
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleWeaponComponentDTO {
/**
* 设备 id
*/
private String deviceId;
/**
* 设备名称
*/
private String deviceName;
/**
* 组件参数列表
*/
private List<FireRuleComponentParamDTO> componentParams;
}

View File

@@ -0,0 +1,6 @@
/**
* 火力规则输入侧 DTO与 {@code resources/json/火力规则输入-无注释.json} 对齐。
* <p>
* {@code redWeapons} 中装备项为 {@link com.solution.rule.domain.ultimately.dto.FireRuleInputRedWeaponElementDTO}(含 {@code SubComponents})。
*/
package com.solution.rule.domain.ultimately.dto;

View File

@@ -0,0 +1,20 @@
package com.solution.rule.domain.ultimately.fact;
import com.solution.rule.domain.ultimately.dto.FireRuleInputRedWeaponElementDTO;
import com.solution.rule.domain.ultimately.dto.FireRuleTaskInputDTO;
import com.solution.rule.domain.ultimately.vo.FireRuleOutputVO;
import lombok.Data;
import java.util.List;
@Data
public class DroolsFact {
//蓝方任务列表
private FireRuleTaskInputDTO task;
//红方武器库
private List<FireRuleInputRedWeaponElementDTO> redWeapons;
private FireRuleOutputVO fireRuleOutputVO;
}

View File

@@ -0,0 +1,22 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 算法引用id / 名称)
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleArithmeticRefVO {
/**
* 算法 id
*/
private String id;
/**
* 算法名称
*/
private String name;
}

View File

@@ -0,0 +1,32 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 装备组件参数项
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleComponentParamVO {
/**
* 参数唯一标识
*/
private String uuid;
/**
* 属性默认值
*/
private String attDefaultValue;
/**
* 属性说明
*/
private String attExplain;
/**
* 数量或序号
*/
private Integer number;
}

View File

@@ -0,0 +1,27 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 经纬高坐标点
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleCoordinateVO {
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
/**
* 高程(米)
*/
private Double height;
}

View File

@@ -0,0 +1,27 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 巡航航线偏移量项(上下 / 前后 / 左右 三选一与取值)
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleCruiseRouteOffsetItemVO {
@JsonProperty("UpOrDown")
private Boolean upOrDown;
@JsonProperty("BeforeOrAfter")
private Boolean beforeOrAfter;
@JsonProperty("LeftOrRight")
private Boolean leftOrRight;
/**
* 偏移数值
*/
private Number value;
}

View File

@@ -0,0 +1,27 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 设备引用
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleDeviceRefVO {
/**
* 设备 id
*/
private String id;
/**
* 设备名称
*/
private String name;
/**
* 引用 id
*/
private String refId;
}

View File

@@ -0,0 +1,21 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 任务载荷中的单次执行块(含目标列表与类型)
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleExecuteBlockVO {
private List<FireRuleExecuteTargetItemVO> targetList;
/**
* 执行类型,如 assault
*/
private String type;
}

View File

@@ -0,0 +1,65 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 打击执行块中单个目标条目
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleExecuteTargetItemVO {
@JsonProperty("ID")
private String id;
/**
* 阵列位置 id
*/
private Integer arrayPositionId;
/**
* 阵列位置 id 备份
*/
private String arrayPositionIdBak;
/**
* 到达时间配置
*/
@JsonProperty("at_time")
private FireRuleTargetAttTimeVO atTime;
@JsonProperty("times_interval")
private Integer timesInterval;
private String attackType;
private String boost;
private String bootTime;
private String companion;
private String cruiseRouteId;
private String moveRouteId;
private List<FireRuleCruiseRouteOffsetItemVO> cruiseRouteOffset;
private String fireType;
private List<Object> strategy;
private String targetId;
private String weaponId;
private String weaponRelease;
private String weaponType;
private Integer weaponUseCount;
}

View File

@@ -0,0 +1,32 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 发射架配置块
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleLauncherConfigurationVO {
/**
* 分类名称
*/
private String classifyName;
/**
* 是否挂载
*/
private Integer isMount;
/**
* 已挂载武器
*/
private FireRuleMountedWeaponRefVO mountedWeapon;
/**
* 数量
*/
private Integer number;
}

View File

@@ -0,0 +1,23 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 任务载荷中的挂载/任务清单项
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleMissionListItemVO {
private String label;
/**
* 发射器类型,如 sam
*/
private String launcherType;
private Integer number;
private String value;
}

View File

@@ -0,0 +1,24 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 挂载武器简要信息
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleMountedWeaponRefVO {
/**
* 武器文档 id
*/
@JsonProperty("_id")
private String id;
/**
* 武器名称
*/
private String name;
}

View File

@@ -0,0 +1,45 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleOutputVO {
private String sourceFile;
private List<FireRuleTaskInputVO> fireRuleInputs;
@JsonProperty("Tasks")
private List<FireRuleSceneTaskNodeVO> tasks;
@JsonProperty("TrackParam")
private FireRuleTrackParamVO trackParam;
@JsonIgnore
public List<FireRuleSceneGroupNodeVO> getGroups() {
return trackParam == null ? null : trackParam.getGroups();
}
@JsonIgnore
public void setGroups(List<FireRuleSceneGroupNodeVO> groups) {
if (trackParam == null) {
trackParam = new FireRuleTrackParamVO();
}
trackParam.setGroups(groups);
}
@JsonIgnore
public List<FireRuleRedWeaponEquipmentVO> getRedWeapons() {
return trackParam == null ? null : trackParam.getRedWeapons();
}
@JsonIgnore
public void setRedWeapons(List<FireRuleRedWeaponEquipmentVO> redWeapons) {
if (trackParam == null) {
trackParam = new FireRuleTrackParamVO();
}
trackParam.setRedWeapons(redWeapons);
}
}

View File

@@ -0,0 +1,40 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 红方装备子组件:通信类数组元素
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleRedCommunicationSlotVO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleArithmeticRefVO arithmetic;
private FireRuleDeviceRefVO device;
private String deviceId;
private String deviceName;
private Boolean employLabel;
private String facilityName;
private String soleId;
private Map<String, Object> twiceModified;
private List<Object> zLists;
@JsonProperty("ParentPlat")
private String parentPlat;
}

View File

@@ -0,0 +1,36 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 红方装备子组件:机动组件数组元素
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleRedMotorizedSlotVO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleArithmeticRefVO arithmetic;
private FireRuleDeviceRefVO device;
private String deviceId;
private String deviceName;
private String soleId;
@JsonProperty("ParentPlat")
private String parentPlat;
private Map<String, Object> twiceModified;
private List<Object> zLists;
}

View File

@@ -0,0 +1,45 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 红方装备子组件:平台数组元素
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleRedPlatformSlotVO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleArithmeticRefVO arithmetic;
private FireRuleDeviceRefVO device;
private String deviceId;
private String deviceName;
private Boolean employLabel;
private String facilityName;
private String soleId;
private Map<String, Object> twiceModified;
private List<Object> zLists;
@JsonProperty("TrackParamId")
private String trackParamId;
private List<Double> positions;
@JsonProperty("ParentPlat")
private String parentPlat;
}

View File

@@ -0,0 +1,24 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 红方装备子组件分组(按 communication / motorized_assembly / platform / weapon
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleRedSubComponentsVO {
private List<FireRuleRedCommunicationSlotVO> communication;
@JsonProperty("motorized_assembly")
private List<FireRuleRedMotorizedSlotVO> motorizedAssembly;
private List<FireRuleRedPlatformSlotVO> platform;
private List<FireRuleRedWeaponSlotVO> weapon;
}

View File

@@ -0,0 +1,43 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleRedWeaponEquipmentVO {
@JsonProperty("SupportType")
private String supportType;
@JsonProperty("TroopsDetail")
private Map<String, Object> troopsDetail;
@JsonProperty("Platform_type")
private String platformType;
private Boolean isStrikeTarget;
private Boolean isReconTarget;
private Boolean isInterferenceTarget;
private Boolean isDefendImportantPlace;
private Double successTargetRad;
private String groupType;
@JsonProperty("EquipmentID")
private String equipmentId;
@JsonProperty("Name")
private String name;
@JsonProperty("OwnerForceSide")
private String ownerForceSide;
@JsonProperty("PlatID")
private String platId;
@JsonProperty("SubComponents")
private FireRuleRedSubComponentsVO subComponents;
}

View File

@@ -0,0 +1,46 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 红方装备子组件:武器 / 发射架子项
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleRedWeaponSlotVO {
@JsonProperty("ObjectHandle")
private String objectHandle;
private FireRuleArithmeticRefVO arithmetic;
private String codedQueue;
private FireRuleLauncherConfigurationVO configuration;
private FireRuleDeviceRefVO device;
private String deviceId;
private String deviceName;
private Boolean employLabel;
private String facilityName;
private String serialNumber;
private String soleId;
private Map<String, Object> twiceModified;
private List<Object> zLists;
@JsonProperty("ParentPlat")
private String parentPlat;
}

View File

@@ -0,0 +1,17 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleRouteTrackPointVO {
private String index;
private String longitude;
private String latitude;
private String height;
private String speed;
private String psia;
private Integer time;
private String active;
}

View File

@@ -0,0 +1,44 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 火力规则输出中 Groups 数组的单项
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleSceneGroupNodeVO {
private Number allAngle;
private String drawName;
private List<Object> editPermission;
private String groupType;
private String id;
private String idKey;
private Boolean isSelected;
private Boolean isShow;
private String leader;
private String name;
private String parentId;
private List<String> permission;
private Boolean show;
private Long sort;
private List<FireRuleWingmanDataVO> wingmanData;
}

View File

@@ -0,0 +1,42 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 火力规则输出中 Tasks 数组的单项(场景树任务节点)
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleSceneTaskNodeVO {
private String color;
private String dataType;
private String drawName;
private String groupType;
private String id;
private String idKey;
private Boolean isSelected;
private String name;
private String parentId;
private List<String> permission;
private Boolean show;
private String side;
private Long sort;
private FireRuleSceneTaskPayloadVO task;
}

View File

@@ -0,0 +1,42 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 场景任务节点中的内层 task 对象
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleSceneTaskPayloadVO {
@JsonProperty("at_time")
private String atTime;
private String attackId;
private String color;
private String departureAirport;
private List<FireRuleExecuteBlockVO> execute;
private String landAirport;
private List<FireRuleMissionListItemVO> missionList;
private String name;
private String side;
private String sideId;
private Integer speed;
private String type;
private String weaponId;
}

View File

@@ -0,0 +1,22 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 目标项中的到达时间开关与取值
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTargetAttTimeVO {
/**
* 时间上限是否为真
*/
private Boolean timeUp;
/**
* 时间值
*/
private Number value;
}

View File

@@ -0,0 +1,64 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 单条火力规则任务输出(相对输入增加防区坐标)
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTaskInputVO {
/**
* 任务唯一标识
*/
private String id;
/**
* 任务名称
*/
private String drawName;
/**
* 任务类型
*/
private String dataType;
/**
* 任务所属阵营
*/
private String side;
/**
* 航迹所属实体或阵营标识
*/
private String trackPointsId;
/**
* 任务航迹点列表
*/
private List<FireRuleTrackPointVO> trackPoints;
/**
* 任务武器配置列表
*/
private List<FireRuleTaskWeaponVO> taskWeapons;
/**
* 任务目标 id
*/
private String targetId;
/**
* 作战区经纬高坐标列表
*/
private List<FireRuleCoordinateVO> warZoneLocation;
/**
* 防区经纬高坐标列表
*/
private List<FireRuleCoordinateVO> defZoneLocation;
}

View File

@@ -0,0 +1,49 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 任务挂载的武器配置
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTaskWeaponVO {
/**
* 装备 id武器唯一标识
*/
private String equipmentId;
/**
* 装备名称
*/
private String name;
/**
* 装备类型编码
*/
private String supportType;
/**
* 装备组件列表
*/
private List<FireRuleWeaponComponentVO> components;
/**
* 装备部署位置
*/
private FireRuleCoordinateVO coordinate;
/**
* 武器数量;可为数值或业务文案(如「最大载弹量」)
*/
private Object number;
/**
* 该武器打击目标 id
*/
private String targetId;
}

View File

@@ -0,0 +1,41 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTrackParamVO {
private static final ObjectMapper MAPPER = new ObjectMapper();
private Map<String, FireRuleTrackRouteVO> routeMap = new LinkedHashMap<>();
@JsonProperty("Groups")
private List<FireRuleSceneGroupNodeVO> groups;
@JsonProperty("redWeapons")
private List<FireRuleRedWeaponEquipmentVO> redWeapons;
@JsonAnySetter
public void putRoute(String key, JsonNode value) {
if ("Groups".equals(key) || "redWeapons".equals(key) || value == null) {
return;
}
routeMap.put(key, MAPPER.convertValue(value, FireRuleTrackRouteVO.class));
}
@JsonAnyGetter
public Map<String, FireRuleTrackRouteVO> getRouteMap() {
return routeMap;
}
}

View File

@@ -0,0 +1,37 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 任务航迹点
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTrackPointVO {
/**
* 航迹点序号
*/
private Integer index;
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
/**
* 高度
*/
private Double height;
/**
* 速度
*/
private Double speed;
}

View File

@@ -0,0 +1,28 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleTrackRouteVO {
private String name;
@JsonProperty("StartTime")
private Integer startTime;
@JsonProperty("EndTime")
private Integer endTime;
@JsonProperty("TrackType")
private String trackType;
@JsonProperty("HeightType")
private String heightType;
private String seaType;
@JsonProperty("TrackPoints")
private List<FireRuleRouteTrackPointVO> trackPoints;
@JsonProperty("Color")
private String color;
@JsonProperty("PointCount")
private Integer pointCount;
}

View File

@@ -0,0 +1,29 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
/**
* 任务武器下的设备组件
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleWeaponComponentVO {
/**
* 设备 id
*/
private String deviceId;
/**
* 设备名称
*/
private String deviceName;
/**
* 组件参数列表
*/
private List<FireRuleComponentParamVO> componentParams;
}

View File

@@ -0,0 +1,22 @@
package com.solution.rule.domain.ultimately.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 编组中的僚机相对参数
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FireRuleWingmanDataVO {
private Integer alt;
private String angle;
private Integer distance;
private Integer key;
private String name;
}

View File

@@ -1,120 +0,0 @@
//package com.solution.rule.parser;
//
//import com.fasterxml.jackson.core.JsonParser;
//import com.fasterxml.jackson.core.JsonToken;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import javax.servlet.http.HttpServletRequest;
//import java.io.IOException;
//import java.util.*;
//
//public class JsonStreamParser {
//
// // 核心:解析所有集合 → 内存关联ID → 组装完整数据
// public List<AssembledWeapon> parseAndAssemble(HttpServletRequest request) throws IOException {
// ObjectMapper mapper = new ObjectMapper();
// try (JsonParser parser = mapper.getFactory().createParser(request.getInputStream())) {
//
// // ========== 步骤1流式解析把所有关联集合存到内存 ==========
// String version = null;
// // 存储所有集合key=集合名(weaponList/weaponParams)value=数据列表
// Map<String, List<Map<String, Object>>> allCollections = new HashMap<>();
//
// // 解析状态
// String currentCollection = null;
// Map<String, Object> currentItem = null;
//
// JsonToken token;
// while ((token = parser.nextToken()) != null) {
// switch (token) {
// case START_OBJECT:
// if (currentCollection != null) currentItem = new HashMap<>();
// break;
// case END_OBJECT:
// if (currentCollection != null && currentItem != null) {
// allCollections.get(currentCollection).add(currentItem);
// currentItem = null;
// }
// break;
// case START_ARRAY:
// currentCollection = parser.getCurrentName();
// allCollections.putIfAbsent(currentCollection, new ArrayList<>());
// break;
// case END_ARRAY:
// currentCollection = null;
// break;
// case FIELD_NAME:
// String field = parser.getCurrentName();
// // 解析版本号
// if ("version".equals(field) && isInMeta(parser)) {
// version = parser.nextTextValue();
// break;
// }
// // 解析普通字段
// if (currentItem != null) {
// parser.nextToken();
// currentItem.put(field, getValue(parser));
// }
// break;
// }
// }
//
// // ========== 步骤2核心通过ID关联匹配组装完整数据 ==========
// return assembleFullWeaponData(allCollections);
// }
// }
//
// /**
// * 【核心逻辑】ID关联匹配武器列表 + 参数列表 → 完整武器
// */
// private List<AssembledWeapon> assembleFullWeaponData(Map<String, List<Map<String, Object>>> allCollections) {
// List<AssembledWeapon> result = new ArrayList<>();
//
// // 1. 获取武器主列表
// List<Map<String, Object>> weaponList = allCollections.getOrDefault("weaponList", Collections.emptyList());
// // 2. 获取武器参数列表
// List<Map<String, Object>> paramList = allCollections.getOrDefault("weaponParams", Collections.emptyList());
//
// // 3. 构建【ID -> 参数】索引MapO(1)快速匹配,效率最高)
// Map<Long, Map<String, Object>> paramIndex = new HashMap<>();
// for (Map<String, Object> param : paramList) {
// Long weaponId = Long.valueOf(param.get("weaponId").toString());
// paramIndex.put(weaponId, param);
// }
//
// // 4. 遍历武器通过ID匹配参数组装完整对象
// for (Map<String, Object> weapon : weaponList) {
// AssembledWeapon fullWeapon = new AssembledWeapon();
// Long weaponId = Long.valueOf(weapon.get("id").toString());
//
// // 填充基础信息
// fullWeapon.setId(weaponId);
// fullWeapon.setName((String) weapon.get("name"));
//
// // 匹配参数通过ID
// Map<String, Object> param = paramIndex.get(weaponId);
// if (param != null) {
// fullWeapon.setDamage(Integer.valueOf(param.get("damage").toString()));
// fullWeapon.setMagazine(Integer.valueOf(param.get("magazine").toString()));
// fullWeapon.setType((String) param.get("type"));
// }
//
// result.add(fullWeapon);
// }
//
// return result;
// }
//
// // ---------------- 工具方法 ----------------
// private boolean isInMeta(JsonParser parser) {
// return parser.getParsingContext().getParent() != null
// && "meta".equals(parser.getParsingContext().getParent().getCurrentName());
// }
//
// private Object getValue(JsonParser parser) throws IOException {
// if (parser.getCurrentToken().isNumeric()) return parser.getLongValue();
// if (parser.getCurrentToken() == JsonToken.VALUE_STRING) return parser.getText();
// if (parser.getCurrentToken() == JsonToken.VALUE_TRUE) return true;
// if (parser.getCurrentToken() == JsonToken.VALUE_FALSE) return false;
// return null;
// }
//}

View File

@@ -5,6 +5,8 @@ import com.solution.rule.domain.FireRuleExecuteDTO;
import com.solution.rule.domain.Platform;
import com.solution.rule.domain.PlatformComponent;
import com.solution.rule.domain.simplerulepojo.Task;
import com.solution.rule.domain.ultimately.dto.FireRuleInputDTO;
import com.solution.rule.domain.ultimately.vo.FireRuleOutputVO;
import com.solution.rule.domain.vo.PlatformComponentNamesVO;
import com.solution.rule.domain.vo.PlatformWeaponAggregateVO;
@@ -58,4 +60,11 @@ public interface FireRuleService {
* @return
*/
Task executeTask(Task task);
/**
* 火力规则
* @param task
* @return
*/
FireRuleOutputVO rule(FireRuleInputDTO task);
}

View File

@@ -7,6 +7,14 @@ import com.solution.rule.domain.*;
import com.solution.rule.domain.dto.WeaponModelDTO;
import com.solution.rule.domain.simplerulepojo.Task;
import com.solution.rule.domain.simplerulepojo.Weapon;
import com.solution.rule.domain.simplerulepojo.fact.FactTask;
import com.solution.rule.domain.ultimately.dto.FireRuleInputDTO;
import com.solution.rule.domain.ultimately.dto.FireRuleInputForceSideDTO;
import com.solution.rule.domain.ultimately.dto.FireRuleInputRedWeaponElementDTO;
import com.solution.rule.domain.ultimately.dto.FireRuleTaskInputDTO;
import com.solution.rule.config.FireRuleMatchDefaultParams;
import com.solution.rule.domain.ultimately.fact.DroolsFact;
import com.solution.rule.domain.ultimately.vo.FireRuleOutputVO;
import com.solution.rule.domain.vo.ComponentCountVO;
import com.solution.rule.domain.vo.PlatformComponentNamesVO;
import com.solution.rule.domain.vo.PlatformWeaponAggregateVO;
@@ -19,13 +27,12 @@ import com.solution.rule.simpstrategy.FireRuleStrategyFactory;
import com.solution.rule.strategy.SceneStrategy;
import com.solution.rule.strategy.SceneStrategyFactory;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -186,6 +193,64 @@ public class FireRuleServiceImpl implements FireRuleService {
return task;
}
/**
* 执行任务
* @param task
* @return
*/
@Override
public FireRuleOutputVO rule(FireRuleInputDTO task) {
if(ObjectUtil.isEmpty(task)){
throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION);
}
List<FireRuleTaskInputDTO> tasks = task.getTasks();
if(CollUtil.isEmpty( tasks)){
throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION);
}
//创建KieSession
KieSession kieSession = kieBase.newKieSession();
Map<String, Object> globalParams = new HashMap<>();
// globalParams.putAll(FireRuleMatchDefaultParams.defaults());
kieSession.setGlobal("globalParams", globalParams);
//获取红方阵营id
String redObjectHandleId = getObjectHandle(task);
if(ObjectUtil.isEmpty(redObjectHandleId)){
throw new RuntimeException(ExceptionConstants.PARAMETER_EXCEPTION);
}
//获取所有武器库
List<FireRuleInputRedWeaponElementDTO> allWeapons = task.getEquipments();
//获取红方武器库
List<FireRuleInputRedWeaponElementDTO> redWeapons = allWeapons.stream()
.filter(weapon -> redObjectHandleId.equals(weapon.getOwnerForceSide()))
.collect(Collectors.toList());
//创建返回数据
FireRuleOutputVO fireRuleOutputVO = new FireRuleOutputVO();
fireRuleOutputVO.setSourceFile(task.getSourceFile());
DroolsFact droolsFact = new DroolsFact();
droolsFact.setRedWeapons(new ArrayList<>(redWeapons));
droolsFact.setFireRuleOutputVO(fireRuleOutputVO);
FactHandle droolsFactHandle = null;
try {
for (FireRuleTaskInputDTO fireRuleTaskInputDTO : tasks) {
droolsFact.setTask(fireRuleTaskInputDTO);
if (droolsFactHandle == null) {
droolsFactHandle = kieSession.insert(droolsFact);
} else {
kieSession.update(droolsFactHandle, droolsFact);
}
kieSession.fireAllRules();
}
} finally {
kieSession.dispose();
}
return fireRuleOutputVO;
}
/**
* 获取所有组件以及数量
* @return
@@ -217,4 +282,15 @@ public class FireRuleServiceImpl implements FireRuleService {
return ruleMapper.findAllBasicPlatformComponents();
}
/**
* 获取红方阵营id
* @param task
* @return
*/
private String getObjectHandle(FireRuleInputDTO task){
List<FireRuleInputForceSideDTO> forceSides = task.getForceSides();
List<FireRuleInputForceSideDTO> collect = forceSides.stream().filter(f -> "红方".equals(f.getForceSideName())).collect(Collectors.toList());
return collect.get(0).getObjectHandle();
}
}

View File

@@ -0,0 +1,482 @@
package com.solution.rule.utils;
import com.solution.rule.domain.ultimately.dto.FireRuleInputRedWeaponElementDTO;
import com.solution.rule.domain.ultimately.dto.FireRuleTaskInputDTO;
import com.solution.rule.domain.ultimately.dto.FireRuleTaskWeaponDTO;
import com.solution.rule.domain.ultimately.dto.FireRuleWeaponComponentDTO;
import com.solution.rule.domain.ultimately.fact.DroolsFact;
import com.solution.rule.domain.ultimately.vo.FireRuleOutputVO;
import com.solution.rule.domain.ultimately.vo.FireRuleRedWeaponEquipmentVO;
import com.solution.rule.domain.ultimately.vo.FireRuleTaskInputVO;
import com.solution.rule.domain.ultimately.vo.FireRuleTaskWeaponVO;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Drools 规则调用的装备匹配逻辑。所有业务词均来自 globalParams由 rule.drl 的 buildParam 注入),本类不写死中文业务词。
* <p>
* <b>总分公式(每件候选红装)</b>
* <pre>
* score(red) = scoreRuleSlots(...) + scoreLegacyLayer(...)
*
* scoreRuleSlots = Σ(i=1..ruleSlotCount) [ containsAny(blueBlob, blueRuleKeywords_i)
* ∧ containsAny(redBlob, redRuleKeywords_i)
* ? ruleScore_i * weight : 0 ]
*
* scoreLegacyLayer = ①空中平台 + ②空中任务 + ③地面任务 + ④坦克 + ⑤导弹 五段条件之和,每段若满足均为「对应 *Score * weight」
* (五段含义见 scoreLegacyLayer 方法注释与 rule.drl 中各键说明)。
* </pre>
* <p>
* <b>文本串定义</b>
* <ul>
* <li>blueBlob{@link #buildBlueTextBlob} — 蓝方任务 drawName、dataType、taskWeapons 及组件名拼接成一大串,用于关键词包含判断。</li>
* <li>redBlob{@link #buildRedTextBlob} — 红装 name、platformType、supportType 拼接。</li>
* </ul>
* <p>
* <b>选优与输出</b>
* <ul>
* <li>在 redWeapons 池中对每件算 score取最大值若并列{@link #compareRedForTieBreak}(由 tieBreak 参数控制,默认 equipmentId 小者优先)。</li>
* <li>若 maxScore &lt; minSelectedScore不追加 fireRuleInputs仍将当前池映射到 FireRuleOutputVO.redWeapons。</li>
* <li>否则:池中 remove 选中项fireRuleInputs 追加一行drawName += outputDrawNameSuffixtaskWeapons 一条映射自选中红装redWeapons 为剩余池。</li>
* </ul>
*/
public final class RuleFunction {
private RuleFunction() {
}
/**
* 单轮规则执行:对当前 DroolsFact 的一条蓝方任务,从 redWeapons 中选一件装备并写回输出。
* <p>
* 参数 pglobalParams中各键含义与运算见 {@link RuleFunction} 类注释及 resources/rules/rule.drl 内 buildParam 行内注释。
*/
@SuppressWarnings("rawtypes")
public static void equipmentRule(DroolsFact fact, Map globalParams) {
if (fact == null || fact.getTask() == null) {
return;
}
Map<String, Object> p = castParams(globalParams);
FireRuleTaskInputDTO blue = fact.getTask();
List<FireRuleInputRedWeaponElementDTO> pool = fact.getRedWeapons();
if (pool == null) {
pool = new ArrayList<>();
fact.setRedWeapons(pool);
}
// weight、minSelectedScore见 rule.drl 注释
String blueBlob = buildBlueTextBlob(blue);
int weight = readInt(p, "weight", 1);
int minScore = readInt(p, "minSelectedScore", 1);
int bestIndex = -1;
int bestScore = Integer.MIN_VALUE;
for (int i = 0; i < pool.size(); i++) {
FireRuleInputRedWeaponElementDTO red = pool.get(i);
String redBlob = buildRedTextBlob(red);
int score = scoreRuleSlots(blueBlob, redBlob, p, weight)
+ scoreLegacyLayer(blueBlob, redBlob, p, weight);
if (score > bestScore) {
bestScore = score;
bestIndex = i;
} else if (score == bestScore && bestIndex >= 0) {
// 并列compareRedForTieBreak(a,b)>0 表示当前 best 的 equipmentId 比候选 red 大,应换成更小的 id
if (compareRedForTieBreak(pool.get(bestIndex), red, p) > 0) {
bestIndex = i;
}
}
}
FireRuleOutputVO out = fact.getFireRuleOutputVO();
if (out == null) {
out = new FireRuleOutputVO();
fact.setFireRuleOutputVO(out);
}
// 未达门槛或池空:不写 fireRuleInputs仅同步「剩余池」到输出 redWeapons
if (bestIndex < 0 || pool.isEmpty() || bestScore < minScore) {
out.setRedWeapons(convertPoolToEquipmentVoList(pool));
// Tasks 由最终输出 redWeapons 一一生成(一个装备 -> 一个任务)
out.setTasks(FireRuleRedWeaponOutputFillHelper.toTaskNodes(out.getRedWeapons()));
return;
}
pool.remove(bestIndex);
out.setRedWeapons(convertPoolToEquipmentVoList(pool));
// Tasks 由最终输出 redWeapons 一一生成(一个装备 -> 一个任务)
out.setTasks(FireRuleRedWeaponOutputFillHelper.toTaskNodes(out.getRedWeapons()));
}
/**
* 目标规则:显式为 Tasks 填 targetId并按红方命中率不足时补拿装备出池带上限
*/
@SuppressWarnings("rawtypes")
public static void target(DroolsFact fact, Map globalParams){
if (fact == null || fact.getTask() == null || fact.getFireRuleOutputVO() == null) {
return;
}
Map<String, Object> p = castParams(globalParams);
FireRuleTaskInputDTO blue = fact.getTask();
FireRuleOutputVO out = fact.getFireRuleOutputVO();
List<FireRuleInputRedWeaponElementDTO> pool = fact.getRedWeapons();
if (pool == null) {
pool = new ArrayList<>();
fact.setRedWeapons(pool);
}
if (out.getRedWeapons() == null) {
out.setRedWeapons(convertPoolToEquipmentVoList(pool));
}
if (out.getTasks() == null || out.getTasks().size() != out.getRedWeapons().size()) {
out.setTasks(FireRuleRedWeaponOutputFillHelper.toTaskNodes(out.getRedWeapons()));
}
double threshold = readDouble(p, "redHitRateThreshold", 0.6d);
int maxExtra = readInt(p, "maxExtraWeaponsPerTask", 2);
int maxRounds = readInt(p, "maxSupplementRounds", 5);
int extraMinScore = readInt(p, "extraPickMinScore", 1);
int weight = readInt(p, "weight", 1);
String blueBlob = buildBlueTextBlob(blue);
if (maxExtra > 0 && maxRounds > 0 && !pool.isEmpty()) {
Set<String> selectedIds = new HashSet<>();
for (FireRuleRedWeaponEquipmentVO w : out.getRedWeapons()) {
if (w != null && !isBlank(w.getEquipmentId())) {
selectedIds.add(w.getEquipmentId());
}
}
int extraCount = 0;
int rounds = 0;
while (rounds < maxRounds && extraCount < maxExtra && !pool.isEmpty()) {
rounds++;
boolean needExtra = false;
for (FireRuleRedWeaponEquipmentVO w : out.getRedWeapons()) {
Double rad = w != null ? w.getSuccessTargetRad() : null;
if (rad == null || rad.doubleValue() < threshold) {
needExtra = true;
break;
}
}
if (!needExtra) {
break;
}
int bestIdx = -1;
int bestScore = Integer.MIN_VALUE;
for (int i = 0; i < pool.size(); i++) {
FireRuleInputRedWeaponElementDTO red = pool.get(i);
if (red == null) {
continue;
}
if (!isBlank(red.getEquipmentId()) && selectedIds.contains(red.getEquipmentId())) {
continue;
}
String redBlob = buildRedTextBlob(red);
int s = scoreRuleSlots(blueBlob, redBlob, p, weight)
+ scoreLegacyLayer(blueBlob, redBlob, p, weight);
if (s > bestScore) {
bestScore = s;
bestIdx = i;
} else if (s == bestScore && bestIdx >= 0) {
if (compareRedForTieBreak(pool.get(bestIdx), red, p) > 0) {
bestIdx = i;
}
}
}
if (bestIdx < 0 || bestScore < extraMinScore) {
break;
}
FireRuleInputRedWeaponElementDTO extra = pool.remove(bestIdx);
FireRuleRedWeaponEquipmentVO vo = toRedEquipmentVo(extra);
out.getRedWeapons().add(vo);
if (!isBlank(vo.getEquipmentId())) {
selectedIds.add(vo.getEquipmentId());
}
extraCount++;
}
}
out.setTasks(FireRuleRedWeaponOutputFillHelper.toTaskNodes(out.getRedWeapons()));
FireRuleRedWeaponOutputFillHelper.assignTargetsToTasks(out.getTasks(), out.getRedWeapons(), blue, p);
}
/**
* 阵位规则:根据蓝方武器 coordinate + trackPoints + warZone 计算红方平台 positions。
*/
@SuppressWarnings("rawtypes")
public static void position(DroolsFact fact, Map globalParams) {
if (fact == null || fact.getTask() == null || fact.getFireRuleOutputVO() == null) {
return;
}
Map<String, Object> p = castParams(globalParams);
boolean enabled = Boolean.parseBoolean(String.valueOf(p.getOrDefault("positionRuleEnabled", true)));
if (!enabled) {
return;
}
FireRuleOutputVO out = fact.getFireRuleOutputVO();
if (out.getRedWeapons() == null || out.getRedWeapons().isEmpty()) {
return;
}
FireRuleRedWeaponOutputFillHelper.fillPlatformPositions(out.getRedWeapons(), fact.getTask(), p);
}
/**
* 航迹规则:根据蓝方 trackPoints 与作战区生成 TrackParam 航迹,并绑定 execute.targetList.moveRouteId。
*/
@SuppressWarnings("rawtypes")
public static void trackRoute(DroolsFact fact, Map globalParams) {
if (fact == null || fact.getTask() == null || fact.getFireRuleOutputVO() == null) {
return;
}
Map<String, Object> p = castParams(globalParams);
boolean enabled = Boolean.parseBoolean(String.valueOf(p.getOrDefault("trackRuleEnabled", true)));
if (!enabled) {
return;
}
FireRuleOutputVO out = fact.getFireRuleOutputVO();
if (out.getTasks() == null || out.getTasks().isEmpty()) {
return;
}
FireRuleRedWeaponOutputFillHelper.fillTrackParamAndBindMoveRoute(out, fact.getTask(), p);
}
@SuppressWarnings("unchecked")
private static Map<String, Object> castParams(Map raw) {
return raw == null ? new java.util.HashMap<>() : (Map<String, Object>) raw;
}
/**
* 蓝方侧用于「关键词包含」判断的合并文本(空格分隔各字段)。
*/
private static String buildBlueTextBlob(FireRuleTaskInputDTO task) {
StringBuilder sb = new StringBuilder();
append(sb, task.getDrawName());
append(sb, task.getDataType());
if (task.getTaskWeapons() != null) {
for (FireRuleTaskWeaponDTO w : task.getTaskWeapons()) {
if (w == null) {
continue;
}
append(sb, w.getName());
append(sb, w.getSupportType());
append(sb, w.getEquipmentId());
if (w.getComponents() != null) {
for (FireRuleWeaponComponentDTO c : w.getComponents()) {
if (c == null) {
continue;
}
append(sb, c.getDeviceName());
}
}
}
}
return sb.toString();
}
/**
* 红方侧用于「关键词包含」判断的合并文本。
*/
private static String buildRedTextBlob(FireRuleInputRedWeaponElementDTO red) {
if (red == null) {
return "";
}
StringBuilder sb = new StringBuilder();
append(sb, red.getName());
append(sb, red.getPlatformType());
append(sb, red.getSupportType());
return sb.toString();
}
private static void append(StringBuilder sb, String s) {
if (s != null && !s.isEmpty()) {
sb.append(s).append(' ');
}
}
/**
* 规则槽得分:对 i=1..ruleSlotCount若 blueBlob 命中 blueRuleKeywords_i 且 redBlob 命中 redRuleKeywords_i
* 则累加 ruleScore_i * weight。关键词为英文逗号分隔任一词作为子串出现在文本中即命中。
*/
private static int scoreRuleSlots(String blueBlob, String redBlob, Map<String, Object> p, int weight) {
int n = readInt(p, "ruleSlotCount", 0);
int sum = 0;
for (int i = 1; i <= n; i++) {
String bk = str(p, "blueRuleKeywords_" + i, "");
String rk = str(p, "redRuleKeywords_" + i, "");
if (bk.isEmpty() || rk.isEmpty()) {
continue;
}
if (containsAny(blueBlob, bk) && containsAny(redBlob, rk)) {
sum += readInt(p, "ruleScore_" + i, 0) * weight;
}
}
return sum;
}
/**
* 兼容层得分:五段独立条件,可叠加。每段均为「蓝关键词命中 ∧ 红关键词命中 → 加 对应分数 * weight」。
* <ul>
* <li>① bluePlatformKeywords_air + redPreferredWhenBlueAir → airScore</li>
* <li>② airTaskKeywords + redPreferredWhenBlueAir → airTaskScore</li>
* <li>③ groundTaskKeywords + redPreferredWhenGround → groundScore</li>
* <li>④ tankKeywords + redMatchKeywords_tank → tankScore</li>
* <li>⑤ missileKeywords + redMatchKeywords_missile → missileScore</li>
* </ul>
* 键名与 rule.drl 中 param.put 一致。
*/
private static int scoreLegacyLayer(String blueBlob, String redBlob, Map<String, Object> p, int weight) {
int s = 0;
if (containsAny(blueBlob, str(p, "bluePlatformKeywords_air", ""))
&& containsAny(redBlob, str(p, "redPreferredWhenBlueAir", ""))) {
s += readInt(p, "airScore", 0) * weight;
}
if (containsAny(blueBlob, str(p, "airTaskKeywords", ""))
&& containsAny(redBlob, str(p, "redPreferredWhenBlueAir", ""))) {
s += readInt(p, "airTaskScore", 0) * weight;
}
if (containsAny(blueBlob, str(p, "groundTaskKeywords", ""))
&& containsAny(redBlob, str(p, "redPreferredWhenGround", ""))) {
s += readInt(p, "groundScore", 0) * weight;
}
if (containsAny(blueBlob, str(p, "tankKeywords", ""))
&& containsAny(redBlob, str(p, "redMatchKeywords_tank", ""))) {
s += readInt(p, "tankScore", 0) * weight;
}
if (containsAny(blueBlob, str(p, "missileKeywords", ""))
&& containsAny(redBlob, str(p, "redMatchKeywords_missile", ""))) {
s += readInt(p, "missileScore", 0) * weight;
}
return s;
}
/**
* 并列时比较两件红装tieBreak=equipmentId 时返回 id 字典序比较结果(&gt;0 表示 a 的 id 大于 b应选 b
*/
private static int compareRedForTieBreak(
FireRuleInputRedWeaponElementDTO a,
FireRuleInputRedWeaponElementDTO b,
Map<String, Object> p) {
if (a == null) {
return b == null ? 0 : 1;
}
if (b == null) {
return -1;
}
String mode = str(p, "tieBreak", "equipmentId");
if ("equipmentId".equals(mode)) {
String ida = nz(a.getEquipmentId());
String idb = nz(b.getEquipmentId());
return ida.compareTo(idb);
}
return 0;
}
/**
* commaKeywords英文逗号分隔若 text 包含其中任一词trim 后非空)则命中。
*/
private static boolean containsAny(String text, String commaKeywords) {
if (text == null || text.isEmpty() || commaKeywords == null || commaKeywords.isEmpty()) {
return false;
}
for (String part : commaKeywords.split(",")) {
String k = part.trim();
if (!k.isEmpty() && text.contains(k)) {
return true;
}
}
return false;
}
private static String str(Map<String, Object> p, String key, String def) {
Object v = p.get(key);
return v == null ? def : String.valueOf(v);
}
private static int readInt(Map<String, Object> p, String key, int def) {
Object v = p.get(key);
if (v == null) {
return def;
}
if (v instanceof Number) {
return ((Number) v).intValue();
}
try {
return Integer.parseInt(String.valueOf(v).trim());
} catch (NumberFormatException e) {
return def;
}
}
private static double readDouble(Map<String, Object> p, String key, double def) {
Object v = p.get(key);
if (v == null) {
return def;
}
if (v instanceof Number) {
return ((Number) v).doubleValue();
}
try {
return Double.parseDouble(String.valueOf(v).trim());
} catch (NumberFormatException e) {
return def;
}
}
private static String nz(String s) {
return s == null ? "" : s;
}
private static boolean isBlank(String s) {
return s == null || s.trim().isEmpty();
}
private static FireRuleTaskWeaponVO toTaskWeaponVo(FireRuleInputRedWeaponElementDTO r) {
FireRuleTaskWeaponVO w = new FireRuleTaskWeaponVO();
if (r != null) {
w.setEquipmentId(r.getEquipmentId());
w.setName(r.getName());
w.setSupportType(r.getSupportType());
}
return w;
}
private static List<FireRuleRedWeaponEquipmentVO> convertPoolToEquipmentVoList(
List<FireRuleInputRedWeaponElementDTO> pool) {
List<FireRuleRedWeaponEquipmentVO> list = new ArrayList<>();
if (pool == null) {
return list;
}
for (FireRuleInputRedWeaponElementDTO e : pool) {
list.add(toRedEquipmentVo(e));
}
return list;
}
private static FireRuleRedWeaponEquipmentVO toRedEquipmentVo(FireRuleInputRedWeaponElementDTO src) {
if (src == null) {
return null;
}
FireRuleRedWeaponEquipmentVO vo = new FireRuleRedWeaponEquipmentVO();
vo.setSupportType(src.getSupportType());
vo.setTroopsDetail(src.getTroopsDetail());
vo.setPlatformType(src.getPlatformType());
vo.setIsStrikeTarget(src.getIsStrikeTarget());
vo.setIsReconTarget(src.getIsReconTarget());
vo.setIsInterferenceTarget(src.getIsInterferenceTarget());
vo.setIsDefendImportantPlace(src.getIsDefendImportantPlace());
vo.setSuccessTargetRad(src.getSuccessTargetRad());
vo.setGroupType(src.getGroupType());
vo.setEquipmentId(src.getEquipmentId());
vo.setName(src.getName());
vo.setOwnerForceSide(src.getOwnerForceSide());
vo.setPlatId(src.getPlatId());
vo.setSubComponents(FireRuleRedWeaponOutputFillHelper.toOutputSubComponents(src.getSubComponents()));
return vo;
}
}

View File

@@ -0,0 +1,392 @@
{
"sourceFile": "区域防空31111_2026-04-02 15_29_03.json",
"fireRuleInputs": [
{
"taskWeapons": [
{
"equipmentId": "40b341f6-d60a-4a29-b84d-2973a3065124",
"name": "导弹",
"supportType": "2001",
"components": [
{
"deviceId": "81c7e7da-cb7b-4435-bba3-1648e946d2b2",
"deviceName": "导弹机动组件",
"componentParams": [
{
"uuid": "b47f34c2-3cba-4be3-a1d5-be0a986dff6f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "4cf26cd0-bd5b-4d4c-a2eb-bca6184be5a1",
"deviceName": "导弹平台",
"componentParams": [
{
"uuid": "32beea38-ffc2-445a-9687-e9bdb087727f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"coordinate": {
"longitude": 124.74107151788,
"latitude": 26.74143394432,
"height": -498.06469972014
},
"number": 10,
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1"
}
],
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1",
"warZoneLocation": [
{
"longitude": 122.18971775079,
"latitude": 28.64177652916,
"height": -99.95248993318
},
{
"longitude": 127.22874089381,
"latitude": 28.54075963352,
"height": -1063.0224849918
},
{
"longitude": 127.99831970891,
"latitude": 23.81306022325,
"height": -5900.62524601637
},
{
"longitude": 120.14866648107,
"latitude": 23.90272134296,
"height": -22.17614107099
}
],
"defZoneLocation": []
}
],
"TrackParam": {
"routeLine_220e5b3c-270d-4006-87f0-a0ab4b22deda": {
"name": "F-22航线1",
"StartTime": 0,
"EndTime": 1657,
"TrackType": "routeLineAir",
"HeightType": "msl",
"seaType": "seaLevel",
"TrackPoints": [
{
"index": "1",
"longitude": "124.69258218394617",
"latitude": "27.801527639000142",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
},
{
"index": "2",
"longitude": "122.9223606765063",
"latitude": "27.585793910609084",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
},
{
"index": "3",
"longitude": "121.59995205693548",
"latitude": "27.41556157737817",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
},
{
"index": "4",
"longitude": "121.00161216798338",
"latitude": "27.07354384591234",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
},
{
"index": "5",
"longitude": "121.0190476615353",
"latitude": "26.599336790536423",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
},
{
"index": "6",
"longitude": "121.67869100949231",
"latitude": "26.183061747705537",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
},
{
"index": "7",
"longitude": "123.7900051477299",
"latitude": "25.733670416880216",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
},
{
"index": "8",
"longitude": "125.47545066085917",
"latitude": "26.136857380879235",
"height": "6000",
"speed": "600",
"psia": "0",
"time": 0,
"active": "null"
}
],
"Color": "rgb(4,161,246)",
"PointCount": 8
},
"Groups": [
{
"allAngle": 0,
"drawName": "J15编组1",
"editPermission": [],
"groupType": "addGroup",
"id": "5dea9ff7-5e45-4f8e-a67f-3ff4187c39ed",
"idKey": "id",
"isSelected": false,
"isShow": false,
"leader": "7a16c098-ceec-4c4d-8a24-8f44976a90ca",
"name": "addGroup",
"parentId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_batFormation",
"permission": [
"14bc8ff9-3c93-4218-b01a-e144add196f9"
],
"show": false,
"sort": 1774271497726,
"wingmanData": [
{
"alt": 40,
"angle": "50",
"distance": 100,
"key": 0,
"name": "9aa9e5aa-9273-4c27-88e1-e582ff561685"
}
]
}
],
"redWeapons": [
{
"SupportType": "car",
"TroopsDetail": {},
"Platform_type": "HQ-9发射车",
"isStrikeTarget": false,
"isReconTarget": false,
"isInterferenceTarget": false,
"isDefendImportantPlace": false,
"groupType": "equipment",
"EquipmentID": "b3c6de29-2b27-4500-a9ce-95d0bebc5cb9",
"Name": "HQ-9发射车--5",
"OwnerForceSide": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831",
"PlatID": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_equipmentPlane",
"SubComponents": {
"communication": [
{
"ObjectHandle": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"arithmetic": {
"id": "66cd29fdce08f520f1d9bf0e",
"name": "短波电台"
},
"device": {
"id": "5e0e5b064f1fae2ee9fa1000",
"name": "3MHZ通信电台",
"refId": "5e0e5b064f1fae2ee9fa1000"
},
"deviceId": "0b700ca6-290e-422a-b4e3-73b222809938",
"deviceName": "3MHZ通信电台",
"employLabel": false,
"facilityName": "3MHZ通信电台",
"soleId": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"twiceModified": {},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"motorized_assembly": [
{
"ObjectHandle": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"arithmetic": {},
"device": {},
"deviceId": "55915bc4-c825-43c4-93eb-6a76ab345e42",
"deviceName": "",
"soleId": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"platform": [
{
"ObjectHandle": "04a96dbc-837a-48be-8c04-e4f53586c47e",
"arithmetic": {
"id": "68876d0fd41989f086e905b8",
"name": "通用发射车算法"
},
"device": {
"id": "68876d2dd41989f086e905b9",
"name": "发射车平台",
"refId": "68876d2dd41989f086e905b9"
},
"deviceId": "164c75ec-6db5-48f9-8285-a7e726fd2a11",
"deviceName": "发射车平台",
"employLabel": false,
"facilityName": "发射车平台",
"soleId": "87905d6b-857a-4c5a-a922-5e2d191588d4",
"twiceModified": {},
"zLists": [],
"TrackParamId": "",
"positions": [
119.28585462691,
25.67974332623,
34.28352933882
]
}
],
"weapon": [
{
"ObjectHandle": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"arithmetic": {
"id": "669dd6356bc286bd64e5d66c",
"name": "发射架算法"
},
"codedQueue": "weapon.launcher",
"configuration": {
"classifyName": "导弹平台",
"isMount": 1,
"mountedWeapon": {
"_id": "68f681794ddde62a52c7e569",
"name": "HQ-9"
},
"number": 4
},
"device": {
"id": "67ff279dafa7ea5aaa3a1236",
"name": "通用发射架",
"refId": "b9665788-9437-40fb-8a24-eff3d4d3b529"
},
"deviceId": "4e910ccf-d937-4a93-9b68-116167eda202",
"deviceName": "通用发射架",
"employLabel": false,
"facilityName": "通用发射架",
"serialNumber": "launcher",
"soleId": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"twiceModified": {
"launcherType": "sam"
},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
]
}
}
]
},
"Tasks": [
{
"color": "rgb(220,39,39)",
"dataType": "taskPlane",
"drawName": "HQ-9发射车--3打击任务",
"groupType": "tasks",
"id": "41d3c5ce-3fda-4dee-a38f-fd3ae7e15e69",
"idKey": "id",
"isSelected": false,
"name": "HQ-9发射车--3打击任务",
"parentId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_taskPlane",
"permission": [
"14bc8ff9-3c93-4218-b01a-e144add196f9",
"56a96b1b-14a8-4daf-a2d0-47c7faa4b831"
],
"show": true,
"side": "红方",
"sort": 1774271151846,
"task": {
"at_time": "180",
"attackId": "267c5d87-bf36-42f2-b0a8-09c608d94b62",
"color": "rgb(220,39,39)",
"departureAirport": "",
"execute": [
{
"targetList": [
{
"ID": "fbddc49c-f7b0-4d07-8000-1b5a2633c461",
"arrayPositionId": 4,
"arrayPositionIdBak": "",
"at_time": {
"timeUp": true,
"value": 180
},
"attackType": "",
"boost": "",
"bootTime": "",
"companion": "",
"cruiseRouteId": "routeLine_f01be820-33ca-4843-8354-3f93a9986fe3",
"cruiseRouteOffset": [
{
"UpOrDown": true,
"value": 0
},
{
"BeforeOrAfter": true,
"value": 0
},
{
"LeftOrRight": true,
"value": 0
}
],
"moveRouteId": "routeLine_de092f0b-d8a3-4382-8e46-398efae3649c",
"fireType": "absolute",
"strategy": [],
"targetId": "dd20d7d9-7ce8-4531-aa0c-0b2056e7fbcd",
"times_interval": 1,
"weaponId": "HQ-9",
"weaponRelease": "",
"weaponType": "",
"weaponUseCount": 3
}
],
"type": "assault"
}
],
"landAirport": "",
"missionList": [
{
"label": "HQ-9(4)",
"launcherType": "sam",
"number": 4,
"value": "HQ-9"
}
],
"name": "HQ-9发射车--3打击任务",
"side": "红方",
"sideId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831",
"speed": 600,
"type": "assault",
"weaponId": ""
}
}
]
}

View File

@@ -0,0 +1,349 @@
{
"sourceFile": "区域防空31111_2026-04-02 15_29_03.json",
"tasks": [
{
"id": "ed0e67e8-691f-4902-bb67-bd289aec89a1",
"drawName": "F-22-1打击任务",
"dataType": "taskPlane",
"side": "BLUE",
"trackPointsId": "d685ca26-2ffa-4b2b-8e75-ecf5897338f5",
"trackPoints": [
{
"index": 1,
"longitude": 124.02895007578839,
"latitude": 26.836172676390202,
"height": 6000.0,
"speed": 600.0
},
{
"index": 2,
"longitude": 122.81034067987203,
"latitude": 27.017765463140986,
"height": 6000.0,
"speed": 600.0
},
{
"index": 3,
"longitude": 121.49435868664283,
"latitude": 27.17048502942595,
"height": 6000.0,
"speed": 600.0
},
{
"index": 4,
"longitude": 120.87774502345792,
"latitude": 27.16848996890842,
"height": 6000.0,
"speed": 600.0
},
{
"index": 5,
"longitude": 120.86773193816859,
"latitude": 26.390372000100005,
"height": 6000.0,
"speed": 600.0
},
{
"index": 6,
"longitude": 122.81161998730377,
"latitude": 25.50052904615808,
"height": 6000.0,
"speed": 600.0
},
{
"index": 7,
"longitude": 125.09035998725984,
"latitude": 24.79876865711152,
"height": 6000.0,
"speed": 600.0
}
],
"taskWeapons": [
{
"equipmentId": "40b341f6-d60a-4a29-b84d-2973a3065124",
"name": "导弹",
"supportType": "2001",
"components": [
{
"deviceId": "81c7e7da-cb7b-4435-bba3-1648e946d2b2",
"deviceName": "导弹机动组件",
"componentParams": [
{
"uuid": "b47f34c2-3cba-4be3-a1d5-be0a986dff6f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "4cf26cd0-bd5b-4d4c-a2eb-bca6184be5a1",
"deviceName": "导弹平台",
"componentParams": [
{
"uuid": "32beea38-ffc2-445a-9687-e9bdb087727f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"coordinate": {
"longitude": 124.74107151788,
"latitude": 26.74143394432,
"height": -498.06469972014
},
"number": "1" ,
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1"
}
],
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1",
"warZoneLocation": [
{
"longitude": 122.18971775079,
"latitude": 28.64177652916,
"height": -99.95248993318
},
{
"longitude": 127.22874089381,
"latitude": 28.54075963352,
"height": -1063.0224849918
},
{
"longitude": 127.99831970891,
"latitude": 23.81306022325,
"height": -5900.62524601637
},
{
"longitude": 120.14866648107,
"latitude": 23.90272134296,
"height": -22.17614107099
}
]
}
],
"redWeapons": [
{
"name": "HQ-9",
"id": "07e18ffb-3826-4e84-b884-68d77838ae25",
"components": [
{
"deviceId": "89a639f5-3675-457b-ad4c-6b91a8d900e3",
"deviceName": "",
"componentParams": [
{
"uuid": "647087e6-ccad-4b14-ba32-9962ae42eee7",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "7c6529f5-3fe5-4cfe-b4c8-b5a5a8178cda",
"deviceName": "导弹平台",
"componentParams": [
{
"uuid": "a2ac6d74-09ac-49d5-8e05-fcaec47757c5",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"number": 1,
"successTargetRad": "命中率",
"isLead": {
"leader": "长机平台的唯一标识 id",
"side": "阵营",
"supportType": "长机平台类型",
"positions": [
{
"longitude": "经度",
"latitude": "纬度",
"height": "高度"
}
]
},
"isWing": [
{
"name": "僚机名称",
"distance": "距离",
"angle": "角度",
"alt": "高度差"
}
]
},
{
"SupportType": "car",
"TroopsDetail": {},
"Platform_type": "HQ-9发射车",
"isStrikeTarget": false,
"isReconTarget": false,
"isInterferenceTarget": false,
"isDefendImportantPlace": false,
"groupType": "equipment",
"EquipmentID": "b3c6de29-2b27-4500-a9ce-95d0bebc5cb9",
"Name": "HQ-9发射车--5",
"OwnerForceSide": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831",
"PlatID": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_equipmentPlane",
"SubComponents": {
"communication": [
{
"ObjectHandle": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"arithmetic": {
"id": "66cd29fdce08f520f1d9bf0e",
"name": "短波电台"
},
"device": {
"id": "5e0e5b064f1fae2ee9fa1000",
"name": "3MHZ通信电台",
"refId": "5e0e5b064f1fae2ee9fa1000"
},
"deviceId": "0b700ca6-290e-422a-b4e3-73b222809938",
"deviceName": "3MHZ通信电台",
"employLabel": false,
"facilityName": "3MHZ通信电台",
"soleId": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"twiceModified": {},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"motorized_assembly": [
{
"ObjectHandle": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"arithmetic": {},
"device": {},
"deviceId": "55915bc4-c825-43c4-93eb-6a76ab345e42",
"deviceName": "",
"soleId": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"platform": [
{
"ObjectHandle": "04a96dbc-837a-48be-8c04-e4f53586c47e",
"arithmetic": {
"id": "68876d0fd41989f086e905b8",
"name": "通用发射车算法"
},
"device": {
"id": "68876d2dd41989f086e905b9",
"name": "发射车平台",
"refId": "68876d2dd41989f086e905b9"
},
"deviceId": "164c75ec-6db5-48f9-8285-a7e726fd2a11",
"deviceName": "发射车平台",
"employLabel": false,
"facilityName": "发射车平台",
"soleId": "87905d6b-857a-4c5a-a922-5e2d191588d4",
"twiceModified": {},
"zLists": [],
"TrackParamId": "",
"positions": [
119.28585462691,
25.67974332623,
34.28352933882
]
}
],
"weapon": [
{
"ObjectHandle": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"arithmetic": {
"id": "669dd6356bc286bd64e5d66c",
"name": "发射架算法"
},
"codedQueue": "weapon.launcher",
"configuration": {
"classifyName": "导弹平台",
"isMount": 1,
"mountedWeapon": {
"_id": "68f681794ddde62a52c7e569",
"name": "HQ-9"
},
"number": 4
},
"device": {
"id": "67ff279dafa7ea5aaa3a1236",
"name": "通用发射架",
"refId": "b9665788-9437-40fb-8a24-eff3d4d3b529"
},
"deviceId": "4e910ccf-d937-4a93-9b68-116167eda202",
"deviceName": "通用发射架",
"employLabel": false,
"facilityName": "通用发射架",
"serialNumber": "launcher",
"soleId": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"twiceModified": {
"launcherType": "sam"
},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
]
}
},
{
"name": "营指挥所",
"id": "9843e2ec-59a5-440f-9669-67f910b8edc3",
"components": [
{
"deviceId": "7f41d14e-83bc-41c7-8e20-cb61f4fc1289",
"deviceName": "",
"componentParams": [
{
"uuid": "5da5f834-a8a9-407d-8a10-6dc78e488af9",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "591217ed-04e5-4120-87db-b5896d87b44d",
"deviceName": "地面指挥所",
"componentParams": [
{
"uuid": "2c53125c-76da-4454-9f91-04ab3c940b9a",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"number": 1,
"successTargetRad": "命中率"
},
{
"name": "防区2",
"id": "c2259481-279a-4c10-ae45-cf2a669e7b52_Circle",
"isLead": {
"drawName": "圆形名称",
"airspaceType": "空域类型",
"side": "阵营",
"selectLonLat": "positions",
"positions": [
{
"longitude": "圆心经度",
"latitude": "圆心纬度",
"height": "圆心高程"
}
],
"radius": "圆半径(KM)",
"height": "高度(米)",
"extrudedHeight": "离地高度(米)"
},
"isWing": {
"outlineWidth": "线宽",
"lineType": "线条",
"outlineColor": "轮廓色",
"color": "填充色"
}
}
]
}

View File

@@ -0,0 +1,474 @@
{
"_comment_sourceFile": "来源场景文件名",
"sourceFile": "区域防空31111_2026-04-02 15_29_03.json",
"_comment_tasks": "蓝方火力规则任务列表(数组,每项为一条任务)",
"tasks": [
{
"_comment_id": "任务id唯一标识符",
"id": "ed0e67e8-691f-4902-bb67-bd289aec89a1",
"_comment_drawName": "任务名称",
"drawName": "F-22-1打击任务",
"_comment_dataType": "任务类型",
"dataType": "taskPlane",
"_comment_side": "任务所属阵营",
"side": "BLUE",
"_comment_trackPointsId": "航迹所属实体/阵营标识",
"trackPointsId": "d685ca26-2ffa-4b2b-8e75-ecf5897338f5",
"_comment_trackPoints": "任务航迹点列表",
"trackPoints": [
{
"index": 1,
"longitude": 124.02895007578839,
"latitude": 26.836172676390202,
"height": 6000.0,
"speed": 600.0
},
{
"index": 2,
"longitude": 122.81034067987203,
"latitude": 27.017765463140986,
"height": 6000.0,
"speed": 600.0
},
{
"index": 3,
"longitude": 121.49435868664283,
"latitude": 27.17048502942595,
"height": 6000.0,
"speed": 600.0
},
{
"index": 4,
"longitude": 120.87774502345792,
"latitude": 27.16848996890842,
"height": 6000.0,
"speed": 600.0
},
{
"index": 5,
"longitude": 120.86773193816859,
"latitude": 26.390372000100005,
"height": 6000.0,
"speed": 600.0
},
{
"index": 6,
"longitude": 122.81161998730377,
"latitude": 25.50052904615808,
"height": 6000.0,
"speed": 600.0
},
{
"index": 7,
"longitude": 125.09035998725984,
"latitude": 24.79876865711152,
"height": 6000.0,
"speed": 600.0
}
],
"_comment_taskWeapons": "任务武器配置列表",
"taskWeapons": [
{
"_comment_equipmentId": "装备id武器唯一标识",
"equipmentId": "40b341f6-d60a-4a29-b84d-2973a3065124",
"_comment_name": "装备名称",
"name": "导弹",
"_comment_supportType": "装备类型",
"supportType": "2001",
"_comment_components": "装备组件列表",
"components": [
{
"deviceId": "81c7e7da-cb7b-4435-bba3-1648e946d2b2",
"deviceName": "导弹机动组件",
"componentParams": [
{
"uuid": "b47f34c2-3cba-4be3-a1d5-be0a986dff6f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "4cf26cd0-bd5b-4d4c-a2eb-bca6184be5a1",
"deviceName": "导弹平台",
"componentParams": [
{
"uuid": "32beea38-ffc2-445a-9687-e9bdb087727f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"_comment_coordinate": "装备部署位置:经纬高坐标",
"coordinate": {
"longitude": 124.74107151788,
"latitude": 26.74143394432,
"height": -498.06469972014
},
"_comment_number": "武器数量",
"number": "最大载弹量" ,
"_comment_targetId": "目标id",
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1"
}
],
"_comment_targetId": "任务目标id",
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1",
"_comment_warZoneLocation": "作战区经纬高坐标列表",
"warZoneLocation": [
{
"longitude": 122.18971775079,
"latitude": 28.64177652916,
"height": -99.95248993318
},
{
"longitude": 127.22874089381,
"latitude": 28.54075963352,
"height": -1063.0224849918
},
{
"longitude": 127.99831970891,
"latitude": 23.81306022325,
"height": -5900.62524601637
},
{
"longitude": 120.14866648107,
"latitude": 23.90272134296,
"height": -22.17614107099
}
]
}
],
"_comment_redWeapons": "红方武器汇总()",
"redWeapons": [
{
"_comment_name": "红方武器名称",
"name": "HQ-9",
"_comment_id": "红方武器id",
"id": "07e18ffb-3826-4e84-b884-68d77838ae25",
"_comment_components": "红方武器下组件列表",
"components": [
{
"deviceId": "89a639f5-3675-457b-ad4c-6b91a8d900e3",
"deviceName": "",
"componentParams": [
{
"uuid": "647087e6-ccad-4b14-ba32-9962ae42eee7",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "7c6529f5-3fe5-4cfe-b4c8-b5a5a8178cda",
"deviceName": "导弹平台",
"componentParams": [
{
"uuid": "a2ac6d74-09ac-49d5-8e05-fcaec47757c5",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"_comment_number": "红方武器弹药数量",
"number": 1,
"_comment_successTargetRad": "红方武器命中率(目前无)",
"successTargetRad": "命中率",
"_comment_isLead": "长机入参结构",
"isLead": {
"leader": "长机平台的唯一标识 id",
"side": "阵营",
"supportType": "长机平台类型",
"positions": [
{
"longitude": "经度",
"latitude": "纬度",
"height": "高度"
}
]
},
"_comment_isWing": "僚机入参结构",
"isWing": [
{
"name": "僚机名称",
"distance": "距离",
"angle": "角度",
"alt": "高度差"
}
]
},
{
"color": "rgb(220,39,39)",
"dataType": "taskPlane",
"drawName": "",
"groupType": "tasks",
"id": "41d3c5ce-3fda-4dee-a38f-fd3ae7e15e69",
"idKey": "id",
"isSelected": false,
"name": "",
"parentId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_taskPlane",
"permission": [
"14bc8ff9-3c93-4218-b01a-e144add196f9",
"56a96b1b-14a8-4daf-a2d0-47c7faa4b831"
],
"show": true,
"side": "红方",
"sort": 1774271151846,
"task": {
"at_time": "180",
"attackId": "267c5d87-bf36-42f2-b0a8-09c608d94b62",
"color": "rgb(220,39,39)",
"departureAirport": "",
"execute": [
{
"targetList": [
{
"ID": "fbddc49c-f7b0-4d07-8000-1b5a2633c461",
"arrayPositionId": 4,
"arrayPositionIdBak": "",
"at_time": {
"timeUp": true,
"value": 180
},
"attackType": "",
"boost": "",
"bootTime": "",
"companion": "",
"cruiseRouteId": "routeLine_f01be820-33ca-4843-8354-3f93a9986fe3",
"cruiseRouteOffset": [
{
"UpOrDown": true,
"value": 0
},
{
"BeforeOrAfter": true,
"value": 0
},
{
"LeftOrRight": true,
"value": 0
}
],
"decoyNum": "0",
"decoyTime": "0",
"disturbNum": "0",
"disturbStartTime": "0",
"droneNum": "",
"fireType": "absolute",
"hitNum": "",
"launchAngle": "",
"launchAzimuth": "",
"noFlyZone": "",
"orbitInclination": "",
"refulId": "",
"salvo": {
"salvoUp": true,
"value": 0
},
"strategy": [],
"targetId": "dd20d7d9-7ce8-4531-aa0c-0b2056e7fbcd",
"times_interval": 1,
"weaponId": "HQ-9",
"weaponRelease": "",
"weaponType": "",
"weaponUseCount": 3
}
],
"type": "assault" //任务类型
}
],
"landAirport": "",
"missionList": [
{
"label": "HQ-9(4)",
"launcherType": "sam",
"number": 4,
"value": "HQ-9"
}
],
"name": "HQ-9发射车--3打击任务",
"side": "红方",
"sideId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831",
"speed": 600,
"type": "assault",
"weaponId": ""
}
},
{
"SupportType": "car",
"TroopsDetail": {},
"Platform_type": "HQ-9发射车",
"isStrikeTarget": false,
"isReconTarget": false,
"isInterferenceTarget": false,
"isDefendImportantPlace": false,
"groupType": "equipment",
"EquipmentID": "b3c6de29-2b27-4500-a9ce-95d0bebc5cb9",
"Name": "HQ-9发射车--5",
"OwnerForceSide": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831",
"PlatID": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_equipmentPlane",
"SubComponents": {
"communication": [
{
"ObjectHandle": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"arithmetic": {
"id": "66cd29fdce08f520f1d9bf0e",
"name": "短波电台"
},
"device": {
"id": "5e0e5b064f1fae2ee9fa1000",
"name": "3MHZ通信电台",
"refId": "5e0e5b064f1fae2ee9fa1000"
},
"deviceId": "0b700ca6-290e-422a-b4e3-73b222809938",
"deviceName": "3MHZ通信电台",
"employLabel": false,
"facilityName": "3MHZ通信电台",
"soleId": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"twiceModified": {},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"motorized_assembly": [
{
"ObjectHandle": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"arithmetic": {},
"device": {},
"deviceId": "55915bc4-c825-43c4-93eb-6a76ab345e42",
"deviceName": "",
"soleId": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"platform": [
{
"ObjectHandle": "04a96dbc-837a-48be-8c04-e4f53586c47e",
"arithmetic": {
"id": "68876d0fd41989f086e905b8",
"name": "通用发射车算法"
},
"device": {
"id": "68876d2dd41989f086e905b9",
"name": "发射车平台",
"refId": "68876d2dd41989f086e905b9"
},
"deviceId": "164c75ec-6db5-48f9-8285-a7e726fd2a11",
"deviceName": "发射车平台",
"employLabel": false,
"facilityName": "发射车平台",
"soleId": "87905d6b-857a-4c5a-a922-5e2d191588d4",
"twiceModified": {},
"zLists": [],
"TrackParamId": "",
"positions": [
119.28585462691,
25.67974332623,
34.28352933882
]
}
],
"weapon": [
{
"ObjectHandle": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"arithmetic": {
"id": "669dd6356bc286bd64e5d66c",
"name": "发射架算法"
},
"codedQueue": "weapon.launcher",
"configuration": {
"classifyName": "导弹平台",
"isMount": 1,
"mountedWeapon": {
"_id": "68f681794ddde62a52c7e569",
"name": "HQ-9"
},
"number": 4
},
"device": {
"id": "67ff279dafa7ea5aaa3a1236",
"name": "通用发射架",
"refId": "b9665788-9437-40fb-8a24-eff3d4d3b529"
},
"deviceId": "4e910ccf-d937-4a93-9b68-116167eda202",
"deviceName": "通用发射架",
"employLabel": false,
"facilityName": "通用发射架",
"serialNumber": "launcher",
"soleId": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"twiceModified": {
"launcherType": "sam"
},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
]
}
},
{
"name": "营指挥所",
"id": "9843e2ec-59a5-440f-9669-67f910b8edc3",
"components": [
{
"deviceId": "7f41d14e-83bc-41c7-8e20-cb61f4fc1289",
"deviceName": "",
"componentParams": [
{
"uuid": "5da5f834-a8a9-407d-8a10-6dc78e488af9",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "591217ed-04e5-4120-87db-b5896d87b44d",
"deviceName": "地面指挥所",
"componentParams": [
{
"uuid": "2c53125c-76da-4454-9f91-04ab3c940b9a",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"number": 1,
"successTargetRad": "命中率"
},
{
"name": "防区2",
"id": "c2259481-279a-4c10-ae45-cf2a669e7b52_Circle",
"_comment_isLead": "圆形编辑入参结构",
"isLead": {
"drawName": "圆形名称",
"airspaceType": "空域类型",
"side": "阵营",
"selectLonLat": "positions",
"positions": [
{
"longitude": "圆心经度",
"latitude": "圆心纬度",
"height": "圆心高程"
}
],
"radius": "圆半径(KM)",
"height": "高度(米)",
"extrudedHeight": "离地高度(米)"
},
"_comment_isWing": "圆形样式入参结构",
"isWing": {
"outlineWidth": "线宽",
"lineType": "线条",
"outlineColor": "轮廓色",
"color": "填充色"
}
}
]
}

View File

@@ -0,0 +1,355 @@
{
"sourceFile": "区域防空31111_2026-04-02 15_29_03.json",
"fireRuleInputs": [
{
"id": "ed0e67e8-691f-4902-bb67-bd289aec89a1",
"drawName": "红方打击任务",
"dataType": "taskPlane",
"side": "RED",
"trackPointsId": "d685ca26-2ffa-4b2b-8e75-ecf5897338f5",
"trackPoints": [
{
"index": 1,
"longitude": 124.02895007578839,
"latitude": 26.836172676390202,
"height": 6000.0,
"speed": 600.0
},
{
"index": 2,
"longitude": 122.81034067987203,
"latitude": 27.017765463140986,
"height": 6000.0,
"speed": 600.0
},
{
"index": 3,
"longitude": 121.49435868664283,
"latitude": 27.17048502942595,
"height": 6000.0,
"speed": 600.0
},
{
"index": 4,
"longitude": 120.87774502345792,
"latitude": 27.16848996890842,
"height": 6000.0,
"speed": 600.0
},
{
"index": 5,
"longitude": 120.86773193816859,
"latitude": 26.390372000100005,
"height": 6000.0,
"speed": 600.0
},
{
"index": 6,
"longitude": 122.81161998730377,
"latitude": 25.50052904615808,
"height": 6000.0,
"speed": 600.0
},
{
"index": 7,
"longitude": 125.09035998725984,
"latitude": 24.79876865711152,
"height": 6000.0,
"speed": 600.0
}
],
"taskWeapons": [
{
"equipmentId": "40b341f6-d60a-4a29-b84d-2973a3065124",
"name": "导弹",
"supportType": "2001",
"components": [
{
"deviceId": "81c7e7da-cb7b-4435-bba3-1648e946d2b2",
"deviceName": "导弹机动组件",
"componentParams": [
{
"uuid": "b47f34c2-3cba-4be3-a1d5-be0a986dff6f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
},
{
"deviceId": "4cf26cd0-bd5b-4d4c-a2eb-bca6184be5a1",
"deviceName": "导弹平台",
"componentParams": [
{
"uuid": "32beea38-ffc2-445a-9687-e9bdb087727f",
"attDefaultValue": "",
"attExplain": "",
"number": 1
}
]
}
],
"coordinate": {
"longitude": 124.74107151788,
"latitude": 26.74143394432,
"height": -498.06469972014
},
"number": 10,
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1"
}
],
"targetId": "0c058874-0c12-4902-8fd0-2cde015965e1",
"warZoneLocation": [
{
"longitude": 122.18971775079,
"latitude": 28.64177652916,
"height": -99.95248993318
},
{
"longitude": 127.22874089381,
"latitude": 28.54075963352,
"height": -1063.0224849918
},
{
"longitude": 127.99831970891,
"latitude": 23.81306022325,
"height": -5900.62524601637
},
{
"longitude": 120.14866648107,
"latitude": 23.90272134296,
"height": -22.17614107099
}
],
"defZoneLocation": []
}
],
"Tasks": [
{
"color": "rgb(220,39,39)",
"dataType": "taskPlane",
"drawName": "HQ-9发射车--3打击任务",
"groupType": "tasks",
"id": "41d3c5ce-3fda-4dee-a38f-fd3ae7e15e69",
"idKey": "id",
"isSelected": false,
"name": "HQ-9发射车--3打击任务",
"parentId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_taskPlane",
"permission": [
"14bc8ff9-3c93-4218-b01a-e144add196f9",
"56a96b1b-14a8-4daf-a2d0-47c7faa4b831"
],
"show": true,
"side": "红方",
"sort": 1774271151846,
"task": {
"at_time": "180",
"attackId": "267c5d87-bf36-42f2-b0a8-09c608d94b62",
"color": "rgb(220,39,39)",
"departureAirport": "",
"execute": [
{
"targetList": [
{
"ID": "fbddc49c-f7b0-4d07-8000-1b5a2633c461",
"arrayPositionId": 4,
"arrayPositionIdBak": "",
"at_time": {
"timeUp": true,
"value": 180
},
"attackType": "",
"boost": "",
"bootTime": "",
"companion": "",
"cruiseRouteId": "routeLine_f01be820-33ca-4843-8354-3f93a9986fe3",
"cruiseRouteOffset": [
{
"UpOrDown": true,
"value": 0
},
{
"BeforeOrAfter": true,
"value": 0
},
{
"LeftOrRight": true,
"value": 0
}
],
"fireType": "absolute",
"strategy": [],
"targetId": "dd20d7d9-7ce8-4531-aa0c-0b2056e7fbcd",
"times_interval": 1,
"weaponId": "HQ-9",
"weaponRelease": "",
"weaponType": "",
"weaponUseCount": 3
}
],
"type": "assault"
}
],
"landAirport": "",
"missionList": [
{
"label": "HQ-9(4)",
"launcherType": "sam",
"number": 4,
"value": "HQ-9"
}
],
"name": "HQ-9发射车--3打击任务",
"side": "红方",
"sideId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831",
"speed": 600,
"type": "assault",
"weaponId": ""
}
}
],
"Groups": [
{
"allAngle": 0,
"drawName": "J15编组1",
"editPermission": [],
"groupType": "addGroup",
"id": "5dea9ff7-5e45-4f8e-a67f-3ff4187c39ed",
"idKey": "id",
"isSelected": false,
"isShow": false,
"leader": "7a16c098-ceec-4c4d-8a24-8f44976a90ca",
"name": "addGroup",
"parentId": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_batFormation",
"permission": [
"14bc8ff9-3c93-4218-b01a-e144add196f9"
],
"show": false,
"sort": 1774271497726,
"wingmanData": [
{
"alt": 40,
"angle": "50",
"distance": 100,
"key": 0,
"name": "9aa9e5aa-9273-4c27-88e1-e582ff561685"
}
]
}
],
"redWeapons": [
{
"SupportType": "car",
"TroopsDetail": {},
"Platform_type": "HQ-9发射车",
"isStrikeTarget": false,
"isReconTarget": false,
"isInterferenceTarget": false,
"isDefendImportantPlace": false,
"groupType": "equipment",
"EquipmentID": "b3c6de29-2b27-4500-a9ce-95d0bebc5cb9",
"Name": "HQ-9发射车--5",
"OwnerForceSide": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831",
"PlatID": "56a96b1b-14a8-4daf-a2d0-47c7faa4b831_equipmentPlane",
"SubComponents": {
"communication": [
{
"ObjectHandle": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"arithmetic": {
"id": "66cd29fdce08f520f1d9bf0e",
"name": "短波电台"
},
"device": {
"id": "5e0e5b064f1fae2ee9fa1000",
"name": "3MHZ通信电台",
"refId": "5e0e5b064f1fae2ee9fa1000"
},
"deviceId": "0b700ca6-290e-422a-b4e3-73b222809938",
"deviceName": "3MHZ通信电台",
"employLabel": false,
"facilityName": "3MHZ通信电台",
"soleId": "3ed86636-a33a-41ac-aff2-0627eb1f9b28",
"twiceModified": {},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"motorized_assembly": [
{
"ObjectHandle": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"arithmetic": {},
"device": {},
"deviceId": "55915bc4-c825-43c4-93eb-6a76ab345e42",
"deviceName": "",
"soleId": "83ea5d33-90f4-4fd8-9121-eced6c7a44ea",
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
],
"platform": [
{
"ObjectHandle": "04a96dbc-837a-48be-8c04-e4f53586c47e",
"arithmetic": {
"id": "68876d0fd41989f086e905b8",
"name": "通用发射车算法"
},
"device": {
"id": "68876d2dd41989f086e905b9",
"name": "发射车平台",
"refId": "68876d2dd41989f086e905b9"
},
"deviceId": "164c75ec-6db5-48f9-8285-a7e726fd2a11",
"deviceName": "发射车平台",
"employLabel": false,
"facilityName": "发射车平台",
"soleId": "87905d6b-857a-4c5a-a922-5e2d191588d4",
"twiceModified": {},
"zLists": [],
"TrackParamId": "",
"positions": [
119.28585462691,
25.67974332623,
34.28352933882
]
}
],
"weapon": [
{
"ObjectHandle": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"arithmetic": {
"id": "669dd6356bc286bd64e5d66c",
"name": "发射架算法"
},
"codedQueue": "weapon.launcher",
"configuration": {
"classifyName": "导弹平台",
"isMount": 1,
"mountedWeapon": {
"_id": "68f681794ddde62a52c7e569",
"name": "HQ-9"
},
"number": 4
},
"device": {
"id": "67ff279dafa7ea5aaa3a1236",
"name": "通用发射架",
"refId": "b9665788-9437-40fb-8a24-eff3d4d3b529"
},
"deviceId": "4e910ccf-d937-4a93-9b68-116167eda202",
"deviceName": "通用发射架",
"employLabel": false,
"facilityName": "通用发射架",
"serialNumber": "launcher",
"soleId": "4e575d4d-2f36-436b-9939-0b96cde96b89",
"twiceModified": {
"launcherType": "sam"
},
"zLists": [],
"ParentPlat": "04a96dbc-837a-48be-8c04-e4f53586c47e"
}
]
}
}
]
}

View File

@@ -15,6 +15,33 @@
## 2. 参数-效果对照(给业务人员)
### 2.0 规则过程总览(先看这一条)
引擎按 **salience 从高到低** 依次执行(同一 `agenda-group` 内数字越大越先跑)。主链路可以理解为:**先定武器与目标关系 → 再补组件与数量 → 再定任务名与空间位置 → 最后射程与航迹**。
```mermaid
flowchart TD
step1["红方武器自适应装配 55"]
step2["导弹联动增强 54"]
step3["导弹组件数量匹配 53"]
step4["命中率动态数量与offset 52"]
step5["任务自动匹配 50"]
step6["阵位区域解析 49"]
step7["阵位武器部署赋位 48"]
step8["射程合理性校验 47"]
step9["航迹生成 46"]
step1 --> step2 --> step3 --> step4 --> step5 --> step6 --> step7 --> step8 --> step9
```
**两种装配主路径(由 `enableRuleScoring` 决定)**
| 模式 | 开关 | 武器从哪来 | `targetId` 怎么定 |
|------|------|------------|---------------------|
| 过程驱动整数加分 | `enableRuleScoring=true`(默认) | 对每个蓝方目标抽特征 → 红方候选池打分 → **并列最高分全选** → 按需求数克隆武器 | 生成红方武器时 **直接写入** 对应该蓝目标的 `equipmentId`(见 `allocateRedWeaponsForBlueTarget` |
| 传统白名单映射 | `enableRuleScoring=false` | 按 `enableAirRule` 等开关 + `map_*_targets` 映射追加武器 | 装配结束后调用 **`bindTargetIdsForRedWeapons`**:可行性过滤 + **五维加权分** + 边际递减 + 比例/回退 |
**调参时的阅读顺序建议**:先确认当前是过程驱动还是白名单 → 再改对应段落里的开关与阈值 → 最后看下游规则(命中率改数量、阵位改坐标)是否仍符合预期。
### 2.1 武器名称映射(改名字,不改逻辑)
- `redStrikeDroneName`:空中反制组中的无人机名称。
- `redArmedHelicopterName`:空中反制组中的武装直升机名称。
@@ -26,17 +53,20 @@
- `redMissileVehicleName`:导弹补充组中的导弹发射车名称。
### 2.2 白名单开关(决定“是否匹配”)
- `enableAirRule``true` 时,蓝方空中目标会触发红方空中反制组;`false` 时该组永不触发。
- `enableGroundRule``true` 时,蓝方地面目标会触发红方炮类反制组;`false` 时不触发。
- `enableArmorRule``true` 时,蓝方装甲目标会触发红方反坦克组;`false` 时不触发。
- `enableMissileVehicleRule``true` 时,蓝方有导弹能力可追加导弹发射车;`false` 时不追加。
- `enableMissileLinkage``true` 时开启导弹数量/范围联动;`false` 时不做导弹联动增强。
- `allowMultiGroup`
- `true`:同一批输入可命中多组策略并叠加武器;
- `false`:只命中第一组,后续组不再生效(更“死规则”)。
- `enableArmedHelicopterOnAir`:空中组中是否包含武装直升机。
### 2.3 蓝方类型到红方方案映射(核心,可多选)
> **仅当 `enableRuleScoring=false` 时**,下列开关与映射主导装配;`enableRuleScoring=true` 时走过程驱动,本节开关对**是否出武器**基本不生效(仍可能影响你后续阅读的兼容映射字段)。
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `enableAirRule` | 是否允许“蓝方有空中目标”时走空中反制映射 | `false` 时空中组整条链路不追加武器 | 不需要空中反制时置 `false`,减少误匹配 |
| `enableGroundRule` | 是否允许蓝方地面目标触发炮类反制组 | 影响迫榴炮/车载迫击炮等是否出现 | 只想反装甲不上炮时置 `false` |
| `enableArmorRule` | 是否允许装甲目标触发反坦克组 | 影响反坦克火箭/导弹系统等是否出现 | 关闭后装甲线完全不走映射 |
| `enableMissileVehicleRule` | 蓝方有导弹能力时是否追加导弹发射车 | 控制是否额外生成 `map_missile_targets` 对应武器 | 默认多为 `false`,需导弹车时再开 |
| `enableMissileLinkage` | 导弹联动增强(`applyMissileLinkage`)是否执行 | 为 `true` 且满足门槛时,给红方**空中**武器补/增强导弹组件数量与射程 | 不想自动改导弹数量与范围时置 `false` |
| `allowMultiGroup` | 多组策略是否可叠加 | `true`:空中/地面/装甲等多条可同时命中;`false`**只命中第一组**,后续不再加武器 | 想规则更“硬”、少组合时置 `false` |
| `enableArmedHelicopterOnAir` | 空中映射中是否包含武装直升机 | 影响空中组是否出 `redArmedHelicopterName` 对应装备 | 只要无人机不要武直时置 `false` |
### 2.3 蓝方类型到红方方案映射(兼容项,评分模式下弱化)
先解释你提到的 “k”
- 这里的 `k` 就是 **key键名**,例如 `map_armor_targets`
@@ -51,68 +81,173 @@
- `map_missile_targets`:蓝方有导弹能力时,红方使用哪些武器。
映射规则说明:
- 值必须是红方武器库内合法名称,否则该项会被忽略
- 为空时视为该组不配置,允许不命中
- 示例:`map_armor_targets=反坦克火箭,反坦克导弹系统` 表示坦克可同时触发两种红方反制武器。
- `enableScoringSelection=true` 时,本组配置不再主导最终结果,仅作为兼容保留
- 当前主决策由“过程驱动评分引擎”完成(类型/距离/命中率/成本综合评分)
### 2.4 数量和阈值(决定“匹配后给多少”
- `defaultAirNum`:空中组默认数量。
- `defaultGroundNum`:地面/装甲组默认数量。
- `defaultMissileVehicleNum`:导弹发射车默认数量。
- `shellRangeDefault`:炮类组件参数值,单位固定 `范围米`
- `missileCountOffset`:红方导弹数量 = 蓝方导弹数量 + 偏移量。
- `missileRangeOffset`:红方导弹范围 = 蓝方导弹范围 + 偏移量(单位 `破坏范围米`)。
- `blueMissileRangeDefault`:蓝方导弹范围缺失时采用的默认值。
- `minBlueMissileCountForLinkage`:蓝方导弹数量达到该值才触发联动增强。
### 2.4 数量与参数(匹配后给多少、导弹与炮类参数
### 2.5 全组件数量匹配参数(新增)
- `enableComponentQuantityMatch`:是否启用全组件数量覆盖(非导弹组件)。
- `componentDeviceNameMappingCsv`:组件名映射表(逗号分隔),格式 `蓝组件deviceName->红组件deviceName`;为空则默认 `deviceName` 直匹配。
- `skipMissileComponentsByNameContains`:跳过覆盖关键词:蓝方组件 `deviceName` 包含该关键词则不覆盖;默认 `导弹`(用于保留导弹联动偏移)。
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `defaultAirNum` | 白名单路径下空中映射默认实例数量 | 每轮 `map_air_targets` 展开时基数 | 需要更多同型机时调大 |
| `defaultGroundNum` | 地面/装甲/炮类映射默认数量 | 非空中组映射展开基数 | 同上 |
| `defaultMissileVehicleNum` | 导弹发射车映射默认数量 | `enableMissileVehicleRule=true` 时追加数量 | 导弹车要多台时调大 |
| `shellRangeDefault` | 炮类武器“炮弹”组件射程字符串 | `limitRedArtilleryToShellOnly` 写入的默认 `范围米` | 想压远/压近打击时改数值 |
| `missileCountOffset` | 联动时红方导弹数量相对蓝方的增量 | `applyMissileLinkage` 中目标导弹发数 | 希望红方导弹明显多于蓝方时调大 |
| `missileRangeOffset` | 联动时红方导弹射程在蓝方基础上的增量 | 红方空中武器导弹组件首参数(破坏范围米) | 需要更远覆盖时调大 |
| `blueMissileRangeDefault` | 蓝方未给导弹射程时的假定值 | 联动计算 `redRangeTarget` 的输入 | 输入不全时兜底,按典型弹种改 |
| `minBlueMissileCountForLinkage` | 联动触发门槛(蓝方导弹总数) | 低于则 `applyMissileLinkage` 直接返回 | 想更难触发联动时调大(如 2、3 |
### 2.6 targetId 自动绑定参数(新增
- `enableTargetAutoBind`:是否自动给红方武器写入 `targetId`
- `minTargetBindRatio`:最低绑定比例(例如 `0.7` 表示至少 70% 红方武器有目标)。
- `allowReserveWithoutTarget`
- `true`:允许少量红方武器 `targetId` 为空(火力冗余)。
- `false`:尽量给每个红方武器分配目标。
### 2.5 仅导弹组件匹配(`导弹组件数量匹配规则`salience 53
绑定规则说明(固定,不需要业务改代码):
- 绑定来源是蓝方武器 `equipmentId`
- 匹配优先级按武器类型:
- 防空类红方武器优先绑定蓝方空中目标
- 反装甲类红方武器优先绑定蓝方装甲目标
- 炮类红方武器优先绑定蓝方炮类/地面目标
- 导弹发射车优先绑定蓝方导弹能力目标
- 当优先池不足时自动回退到地面池/全目标池,保证大部分武器有目标。
**规则过程**:在红方武器已有 `targetId` 的前提下,按蓝方对应装备的**导弹类组件**去对齐红方导弹组件的**数量**与**首参数**;其它组件不动。
### 2.7 命中率与动态火力参数(新增)
- `hitRateCsv`:业务可配置红方武器命中率,格式 `武器名=0.72,武器名2=0.55`
- `defaultHitRateFallback`:未命中 `hitRateCsv` 且武器未携带 `hitRate` 时的兜底命中率。
- `desiredKillProbability`:目标毁伤置信度(例如 `0.9`)。
- `offsetCsvByWeapon`:显式 offset最高优先级格式 `武器名=1,武器名2=2`
- `enableDynamicMultiRedPerBlue`:是否按命中率动态决定“一个蓝方目标需要几把红方武器”。
- `minRedWeaponsPerBlueTarget` / `maxRedWeaponsPerBlueTargetCap`:每个蓝方目标的最小/最大红方分配数。
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `enableComponentQuantityMatch` | 总开关 | `false` 时本规则不改写任何组件 | 完全手工控组件时关闭 |
| `componentDeviceNameMappingCsv` | 蓝/红导弹组件 `deviceName` 映射 | 解决双方组件命名不一致导致对不上 | 填 `机载导弹->某某导弹` 形式,逗号分隔多对 |
| `missileComponentNameContains` | 判定“导弹组件”的关键词 | 只有 `deviceName` 含该词的组件参与匹配 | 若业务用“火箭弹”等命名,可改关键词 |
优先级说明(重要):
-`offsetCsvByWeapon` 命中某武器,则直接使用显式 offset不再使用命中率推导 offset。
- 未配置显式 offset 时,规则按命中率与 `desiredKillProbability` 自动推导所需火力数量。
- 同一蓝方 `equipmentId` 可能被多个红方武器绑定(不是固定 2 把),数量由命中率动态计算并受 cap 限制。
**输出影响**:仅改导弹组件 `componentParams[0].number``componentParams[0].attDefaultValue`(破坏范围等),非导弹组件保持红方原值。
### 2.8 阵位规则参数(新增
- `enablePositionRules`:阵位规则总开关。
- 阵位输入来源:`blueTask.warZoneLocation``blueTask.defZoneLocation`(各 4 个经纬点)。
- `fireUnitSpacingMeters`:防区/作战区点位间距(米),例如 `100` 代表约每 100 米一个火力单元。
- `airDeployZonePreference`:飞机优先部署区域(`combat``defense`)。
- `defensePriorityWeapons`:优先部署在防区的武器名单(逗号分隔)。
- `groundDeployHeight` / `airDeployHeight`:地面/空中武器部署高度。
### 2.6 targetId 自动绑定(仅传统白名单路径
阵位规则效果:
- 新增两条规则:
- `阵位规则-区域解析与点位生成`
- `阵位规则-武器部署赋位`
- 飞机可在任意区(按偏好区优先);反坦克等重火力优先防区。
- 在多边形区域内按间距生成候选点,并给红方武器写入 `weapon.coordinate`
> **`enableRuleScoring=true`(过程驱动)时**:装配阶段已在 `allocateRedWeaponsForBlueTarget` 里把 `targetId` 设为对应蓝方 `equipmentId`**不会**再走下表的五维分配逻辑。下表仅在 **`enableRuleScoring=false`** 且 `configureRedWeaponsByBlue` 末尾调用 `bindTargetIdsForRedWeapons` 时生效。
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `enableTargetAutoBind` | 是否执行绑定函数 | `false` 时红方 `targetId` 保持入参/空 | 全手工指定目标时关闭 |
| `minTargetBindRatio` | 最低绑定比例下限 | 绑定数/红武器总数低于该比例时,尝试用 `pickAnyBlueId` 补足 | 想“几乎全要有目标”时调高(如 0.9);允许大量空则调低 |
| `allowReserveWithoutTarget` | 是否允许故意留空 | `true`:允许火力冗余;`false`:尽量全部塞满目标 | 与 `minTargetBindRatio` 配合使用 |
| `w_target_type` | 类型匹配在总分中的权重 | 越大越强调类型对口 | 类型错配不可接受时略调高 |
| `w_target_dist` | 距离权重 | 越大越偏向更近、易打击的蓝目标 | 强调近战压制时调高 |
| `w_target_height` | 高度差权重 | 越大越惩罚高度层不匹配 | 空地混合作战可略调高 |
| `w_target_hit` | 命中率权重 | 越大高 `hitRate` 武器越易抢到好目标 | 强调效费比时调高 |
| `w_target_threat` | 蓝方威胁权重 | 越大越优先高威胁蓝目标 | 要“先打高威胁”时调高 |
| `maxEffectiveDistance` | 配对最大有效距离 | 超过则 `isPairFeasible` 直接否 | 只允许远程交火时调大;强制近战调小 |
| `maxHeightGap` | 允许的最大高度差 | 超过则候选失效 | 高原/低空混编时适度调大 |
| `targetDecayAlpha` | 边际递减系数 | `marginal = score / (1 + alpha*k)``k` 为该蓝目标已分配数;**越大越不扎堆** | 避免多机打同一目标时调大 |
| `fallbackToNearestTarget` | 无可行候选时是否按距离回退 | `true` 时尽量给一个最近蓝 `equipmentId` | 不想硬塞错误目标时改 `false` 并配合 `allowUnassignedRedWeapon` |
| `allowUnassignedRedWeapon` | 仍无可行时是否允许 `targetId` 为空 | `true` 允许空;`false` 会再 `pickAnyBlueId` 硬填 | 与火力冗余策略一致即可 |
**绑定过程(白名单路径,固定实现)**:绑定键为蓝方 `equipmentId` → 逐把红武器在可行集合上算分 → 取边际最高 → 更新已分配计数 → 不足比例再补 → 仍不行则按上表回退或留空。
### 2.7 过程驱动整数加分参数(核心,`enableRuleScoring=true`
**规则过程**(函数 `runProcessDrivenSelection`):对每个带 `equipmentId` 的蓝方武器抽一条特征 → 在配置给出的红方武器池里用 `scoreRedWeaponByRules` 打**整数分** → 去掉低于 `minScoreToAssign` 的 → **并列最高分全部保留** → 按 `computeNeededRedCountFromFeature` 得到 `needCount`,再被 `minRedWeaponsPerBlueTarget``maxRedWeaponsPerBlueTargetCap` 钳位 → 轮询 `topNames` 克隆武器并 `setTargetId(blueId)`
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `enableRuleScoring` | 是否走过程驱动主路径 | `true` 走本节;`false` 回退 2.2 白名单 + 2.6 绑定 | 与旧映射二选一 |
| `minScoreToAssign` | 候选武器最低整数分 | 低于则该红方武器名不参与本蓝目标的并列候选 | 想更少种类参与时调大;想多并列时调小 |
| `nearDefenseDistanceMeters` | 蓝方到防区距离“近”的米阈值 | 与 `score_nearDefense_artillery` 联动:近且炮名命中则加分 | 防区尺度变化时同步改 |
| `highThreatLevel` | 任务威胁等级算“高威胁”的整数阈值 | 与 `score_highThreat_missile` 等联动 | 想更容易触发“高威胁分支”时调低 |
| `highTargetCount` | 蓝方该目标 `number` 的“数量高”阈值 | 与 `score_highCount_artillery` 联动 | 集群目标多时调低 |
| `score_type_antiArmor` | 装甲特征下反坦克类名加分 | 含“反坦克”的红方名更容易进并列最高 | 强化反坦时调大 |
| `score_nearDefense_artillery` | 近防区 + 迫榴/迫击炮名加分 | 近防区时更倾向出炮 | 强调要炮时调大 |
| `score_highThreat_missile` | 高威胁或空中场景下导弹/防空类加分(实现中与多项条件叠加) | 高威胁/空中时防空、导弹类名分更高 | 防空压制想加重时调大 |
| `score_highCount_artillery` | 蓝方数量高时炮类加分 | 多目标时更倾向炮 | 炮火优先时调大 |
| `score_hasMissile_airDefence` | 蓝方有导弹组件时防空/导弹发射车类加分 | 有导弹威胁时更倾向防空与导弹车 | 导弹对抗想加重时调大 |
**并列全选机制**
- 对同一蓝方 `equipmentId`,所有红方候选算分后取 `maxScore`**凡 `score == maxScore` 的武器名称都进入 `topNames`**。
- 需要数量大于名称种数时,会在 `allocateRedWeaponsForBlueTarget` 里**轮询** `topNames` 重复添加,故同名武器可出现多把。
- 另:实现里若估算射程覆盖蓝方距离(含安全裕量)还会 **+1 分**,便于优先能打的装备。
### 2.8 命中率与动态火力(`命中率规则-动态数量与offset`salience 52
**规则过程**:在装配之后,对**已有**红方武器的 `number` 做增量:优先读 `offsetCsvByWeapon` 显式 offset否则用命中率与阈值的 **gap 阶梯**`hitRateStep*Offset`
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `hitRateCsv` | 按武器名配置命中率 | `applyDefaultHitRateIfAbsent` 与 gap 计算 | 调整个体武器假定命中能力 |
| `defaultHitRateFallback` | 未配置且武器无 `hitRate` 时 | gap 计算用的默认 p | 整体偏乐观/悲观时改 |
| `desiredKillProbability` | 过程驱动里毁伤置信目标 | `computeNeededRedCountFromFeature``computeRequiredShots` 的输入 | 想“打得更保险”时调高(需求发数可能变多) |
| `offsetCsvByWeapon` | **最高优先级**数量偏移 | 命中武器名则 **忽略** gap 阶梯,直接 `base + offset` | 某武器必须固定加 N 发时配置 |
| `hitRateThreshold` | 命中率门槛 | `gap = threshold - hitRate`,决定进哪一档增量 | 门槛越高,低命中武器越易吃到正 offset |
| `hitRateGapStep1Max` / `hitRateGapStep2Max` | gap 的一、二档上界 | 分档加 `hitRateStep1Offset``hitRateStep2Offset` | 拉宽档位可减少落到高档 |
| `hitRateStep1Offset` / `hitRateStep2Offset` | 各档对 `number` 的加量 | 直接增加 `weapon.number` | 低命中时想多压弹药则调大 |
| `minRedWeaponsPerBlueTarget` | 每蓝目标至少分配红武器数下限 | 过程驱动里与 `needCount` 取大 | 强制“至少 N 把伺候一个目标” |
| `maxRedWeaponsPerBlueTargetCap` | 每蓝目标分配上限 | 与 `needCount` 取小,防止无限膨胀 | 控制火力上限 |
| `enableDynamicMultiRedPerBlue` | 配置项(当前实现**未读取** | 预留;**改之暂无效果**,以 `desiredKillProbability` + min/max 钳位为准 | 待代码接入后再用 |
**阶梯优先级(与代码一致)**
1. `offsetCsvByWeapon` 命中 → 只用显式 offset。
2. 否则 `gap <= 0``+0`
3. `0 < gap <= hitRateGapStep1Max``+hitRateStep1Offset`
4. `hitRateGapStep1Max < gap <= hitRateGapStep2Max``+hitRateStep2Offset`
5. `gap > hitRateGapStep2Max` → 仍按 **第二档 offset**(避免数量无上限膨胀)。
### 2.9 阵位规则参数(`阵位规则` 49→48
**规则过程**`prepareDeploymentPools` 用作战区/防区多边形生成候选点网格;`applyWeaponDeployment` 用蓝方航迹与防区关系得到 **部署模式** `deployMode`(近快/远快/近慢/默认)→ 选锚点 → `resolveFormationType`(人工阵型 / 自动阵型 / 默认)→ `buildFormationOffsets` 展开队形 → 写入 `weapon.coordinate`;地面高度固定、空中可走自动生成高度。
**输入依赖**`blueTask.warZoneLocation``blueTask.defZoneLocation`(各 4 点经纬);部署模式还依赖 `trackPoints`(算速度与距防区)。
#### 2.9.1 总开关与点位
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `enablePositionRules` | 阵位总开关 | `false` 时跳过点位池与赋位 | 仅要装配不要坐标时关闭 |
| `fireUnitSpacingMeters` | 作战区/防区内网格点间距(米) | 点密度:越小点越多、部署越密 | 地形细粒度要求高调小 |
| `airDeployZonePreference` | 空中锚点优先作战区还是防区 | `combat`/`defense` 影响 `pickAnchorByMode` 选取 | 想飞机靠前压则偏 `combat` |
| `defensePriorityWeapons` | 名单内武器优先取防区点 | 名单武器在无锚点回退时优先 `defense` 池 | 要扼守防区的装备写入 |
#### 2.9.2 部署模式(与 `speedFastThreshold`、距离阈值)
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `speedFastThreshold` | 蓝方平均速度是否算“快” | 与 `distanceNearDefenseThresholdMeters``distanceFarDefenseThresholdMeters` 组合成 **near_fast / far_fast / near_slow / default** | 高速标准提高则更少判成“快” |
| `distanceNearDefenseThresholdMeters` | 蓝方航迹末端距防区“近”的米阈值 | 参与部署模式与锚点策略 | 防区尺度大时略调大 |
| `distanceFarDefenseThresholdMeters` | “远”阈值 | 同上 | 与上配合拉开近/远带 |
#### 2.9.3 高度(地面固定 / 空中可自动)
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `groundDeployHeight` | 地面武器统一高度 | 地面编队 `moveCoordinateByMeters` / 克隆点高度 | 地表 DEM 约定高度 |
| `airDeployHeight` | 关闭自动或兜底时用 | 过程驱动关闭自动高度时的固定空高 | 与 `airHeightFallback` 一般同量级 |
| `enableAutoAirDeployHeight` | 空中是否按态势算高 | `false` 时空中全程用 `airDeployHeight` | 想完全手工高时关 |
| `airHeightFallback` | 无航迹且无蓝方武器高度时的基准 | `resolveBlueBaseHeight` 最后兜底 | 与默认战术层一致即可 |
| `airHeightMin` / `airHeightMax` | 自动高度钳位 | 防止算出过矮/过高 | 任务高度包线 |
| `airHeightSpeedThreshold` / `airHeightAdjustFast` | 快于阈值则加高度 | 快目标对应更高拦截层 | 拦截想更猛则加 `AdjustFast` |
| `airHeightNearDefenseDistance` / `airHeightFarDefenseDistance` | 距防区近/远分界 | 近用 `airHeightAdjustNear`(多为负)、远用 `airHeightAdjustFar` | 调整防区内外高度差 |
| `airHeightAdjustMain` / `airHeightAdjustWing` | 主僚高度差 | 主机略高、僚机略低 | 战术队形垂直疏开 |
#### 2.9.4 阵型类型(人工 / 自动 / 默认)
**说明(与部署模式共用阈值)**`resolveDeployModeByBlueState`**`speedFastThreshold`**、`distanceNearDefenseThresholdMeters``distanceFarDefenseThresholdMeters` 得到 `near_fast / far_fast / near_slow / default``autoSelectFormationType` 直接消费该 `deployMode` 字符串选 `formationRule_*`。配置里的 **`formationFastSpeedThreshold``formationNearDefenseDistance``formationFarDefenseDistance` 当前未参与运算**,调整无效;若要与部署模式解耦,需开发在代码中改为读取这三项。
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `formationDefaultType` | 阵型名兜底 | 非法或未选时 `normalizeFormationType` 回退 | 填 `TRIANGLE` 等合法枚举 |
| `enableAutoFormationSelect` | 是否 `autoSelectFormationType` | `false` 时只用 Task 指定或默认 | 想完全人工阵型时关 |
| `formationHighThreatLevel` | 威胁≥该值走 `formationRule_high_threat` | **优先于**速度距离分支 | 想更早用“高威胁阵型”则调低 |
| `formationLargeGroupCount` | **大编队**阈值 | 比较 **`redTask.taskWeapons.size()`(红方武器条数)** ≥ 阈值则走 `formationRule_large_group`(不是蓝方数量) | 想更早切换“大编队阵型”则调小 |
| `formationRule_near_fast` 等 | 各分支对应阵型名 | 决策序:**高威胁 > 近快/远快/近慢 > 大编队(红方条数)> 空中占比≥0.5 > default** | 改字符串即改映射 |
| `formationRule_air_majority` | 红方空中占比高时阵型 | `computeRedAirRatio` ≥ 0.5 | 无人机群战术时调整 |
#### 2.9.5 间距、主僚距、朝向(自动 + 兜底)
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `formationDefaultSpacingMeters` | 阵型间距兜底 | 自动间距失败时用 | 与最小安全间距匹配 |
| `formationSpacingMinMeters` / `formationSpacingMaxMeters` | 自动间距上下界 | 限制 `resolveFormationSpacing` 输出 | 地形窄/宽时收放 |
| `defenseScaleMinMeters` / `defenseScaleMaxMeters` | 防区尺度映射到间距的范围 | 防区越大间距可越大 | 与防区实际大小一致 |
| `mainWingDistanceDefaultMeters` | 主僚距兜底 | 自动主僚距失败时 | 编队纵向尺度 |
| `mainWingDistanceMinMeters` / `mainWingDistanceMaxMeters` | 主僚距钳位 | 限制自动主僚距 | 避免过近相撞 |
| `mainWingDistanceModeFactor_near_fast` 等 | 部署模式对主僚距的乘子 | 近快更紧、远快更疏等 | 战术疏密 |
| `formationHeadingDefaultDeg` | 朝向兜底 | 无航迹、无 Task 朝向时 | 默认机头方向 |
**实体覆盖优先级(与代码一致)**
- 阵型类型:`Task.formationType`(非空)> 自动选阵型 > `formationDefaultType`
- 间距:`Task.formationSpacingMeters` > 防区尺度自动 > `formationDefaultSpacingMeters`
- 主僚距:`Weapon.wingRelativeDistanceMeters` > `Task.mainWingDistanceMeters` > 自动 > `mainWingDistanceDefaultMeters`
- 朝向:`Task.formationHeadingDeg` > 航迹末段方向 > `formationHeadingDefaultDeg`
**实体字段建议**`Task``formationType``formationSpacingMeters``mainWingDistanceMeters``formationHeadingDeg``Weapon``formationRole``wingRelativeDistanceMeters``wingRelativeBearingDeg`
阵位输入示例仅经纬度4点
@@ -133,7 +268,7 @@
}
```
### 2.9 航迹规则参数(新增)
### 2.10 航迹规则参数(新增)
- `enableTrajectoryRules`:航迹规则总开关。
- `strategyMode``auto/shortest/flank/interfere`
- `auto`:智能选择策略。
@@ -159,38 +294,40 @@
## 3. 当前规则行为(简版)
- `装备组件匹配``组件参数匹配`已作为 `legacy` 占位不承担当前业务决策
- 主决策在 `红方武器自适应装配规则`调用 `configureRedWeaponsByBlue(...)`映射配置添加武器
- 主决策在 `红方武器自适应装配规则`调用 `configureRedWeaponsByBlue(...)`默认走过程驱动整数加分选武器
- 过程驱动链路蓝方特征提取 -> 候选整数加分 -> 最高分并列全选 -> 动态分配数量与 targetId。
- 导弹增强在 `导弹联动增强规则`:调用 `applyMissileLinkage(...)`,受开关和阈值控制。
- 全组件数量匹配在 `全组件数量匹配规则`按红方 `targetId` 绑定蓝方装备覆盖非导弹组件 `componentParams[0].number`找不到组件/targetId 允许跳过
- 命中率驱动数量在 `命中率规则-动态数量与offset` `hitRate` 与目标毁伤概率推导火力数量显式 offset 配置优先
- `全组件数量匹配规则` 当前语义已收敛为“仅导弹组件匹配”:只改导弹组件数量与首参数,非导弹不改。
- 命中率驱动数量在 `命中率规则-动态数量与offset`:按 `hitRateThreshold``gap` 阶梯增量计算数量;显式 offset 配置优先
- 任务命名在 `任务自动匹配规则`:调用 `assignTaskNameByRedWeapons(...)`,按红方最终武器自动生成任务名和 `dataType`
- 炮类约束:命中炮类条件时,炮类武器只保留 `炮弹` 组件,单位 `范围米`
- `targetId` 绑定在装配后自动执行按命中率动态给蓝目标分配多个红方武器受上下限约束允许少量空值冗余
- 阵位部署按多边形区域和武器类型自动赋位保证防区火力覆盖
- `targetId`**过程驱动**下在装配时直接写入对应蓝方 `equipmentId`**白名单路径**下用“可行性 + 五维评分 + 边际递减”分配(见 2.6)。
- 阵位部署:按“速度距离驱动锚点 + 阵型偏移 + 主僚机相对位移”自动赋位,最终输出经纬高。
- 射程合理性在 `射程合理性校验规则`:基于蓝/红武器坐标计算距离,自动避免“射程不足却打击”的不合理情况(可自动调参)。
- 航迹生成:根据蓝方 `trackPoints` 生成红方 `trackPoints`,点数与蓝方一致,支持三套策略和智能选择。
## 3.1 任务名称自动匹配(新增
## 3.1 任务名称自动匹配(`任务自动匹配规则`salience 50
任务命名依据**红方最终武器**不是蓝方任务名关键字)。
**规则过程**:在武器与数量基本落定之后,按 **红方最终 `taskWeapons` 列表** 做分类(不看蓝方 `drawName` 关键字),写入 `redTask.drawName``redTask.dataType`
当前分类优先级
- 导弹突击导弹发射车
- 防空压制防空导弹武器/火力打击无人机/武装直升机
- 反装甲打击反坦克火箭/反坦克导弹系统
- 炮火压制迫榴炮/车载迫击炮
- 通用打击兜底
**分类优先级(先命中先生效)**
业务可调模板 `buildBusinessConfig()`
- `taskName_missile_strike` / `taskDataType_missile_strike`
- `taskName_air_defence` / `taskDataType_air_defence`
- `taskName_anti_armor` / `taskDataType_anti_armor`
- `taskName_artillery` / `taskDataType_artillery`
- `taskName_general` / `taskDataType_general`
1. 导弹突击:含导弹发射车类武器名
2. 防空压制:防空导弹 / 火力打击无人机 / 武装直升机
3. 反装甲打击:反坦克火箭 / 反坦克导弹系统
4. 炮火压制:迫榴炮 / 车载迫击炮
5. 通用打击:兜底
效果说明
- 只改这些模板文字不改函数也能改变最终任务展示名
- 若分类与武器不一致会自动回落到 `通用打击任务`避免任务名和武器不符”。
| 参数 | 作用 | 影响什么 | 怎么调整 |
|------|------|----------|----------|
| `taskName_missile_strike` | 导弹突击类展示名 | `drawName` 当命中导弹突击分支时 | 改中文任务标题 |
| `taskDataType_missile_strike` | 导弹突击类业务类型 | `dataType` 同步写入 | 与前端/报表枚举对齐 |
| `taskName_air_defence` / `taskDataType_air_defence` | 防空压制类 | 同上 | 同上 |
| `taskName_anti_armor` / `taskDataType_anti_armor` | 反装甲类 | 同上 | 同上 |
| `taskName_artillery` / `taskDataType_artillery` | 炮火类 | 同上 | 同上 |
| `taskName_general` / `taskDataType_general` | 兜底类 | 无上述特征或冲突回落时使用 | 默认任务名与类型 |
**效果说明**:只改模板字符串即可改展示;若红方武器组合与期望分类不一致,会落到 `taskName_general`,避免“名不副实”。
## 4. 快速修改示例(业务常用)
@@ -330,7 +467,7 @@
- **联动门控**`applyMissileLinkage(...)` 必须同时满足:
- `enableMissileLinkage=true`
- 蓝方导弹数量 `>= minBlueMissileCountForLinkage`
- **目标绑定**`bindTargetIdsForRedWeapons(...)` 基于蓝方 `equipmentId` 分配 `targetId`支持优先匹配 + 绑定率阈值 + 冗余空目标”。
- **目标绑定**`bindTargetIdsForRedWeapons(...)` 基于蓝方 `equipmentId` 执行“可行性过滤 + 打分 + 边际收益递减分配 + 回退兜底”。
- **阵位部署**`prepareDeploymentPools(...)` + `applyWeaponDeployment(...)` 负责区域解析、点位生成与部署赋位。
- **航迹生成**`applyTrajectoryGeneration(...)` + `chooseTrajectoryStrategy(...)` + `generateRedTrackPoints(...)` 负责红方航迹策略生成。
- **任务命名**`assignTaskNameByRedWeapons(...)` 仅基于红方最终武器,避免旧版按蓝方 `drawName` 关键字造成误判。

View File

@@ -0,0 +1,220 @@
package rules;
import com.solution.rule.domain.ultimately.fact.DroolsFact;
import java.util.Map;
import static com.solution.rule.utils.RuleFunction.equipmentRule;
import static com.solution.rule.utils.RuleFunction.target;
import static com.solution.rule.utils.RuleFunction.position;
import static com.solution.rule.utils.RuleFunction.trackRoute;
global java.util.Map globalParams;
/**
* 构建装备匹配所需的全部可调参数(会 merge 进 globalParams覆盖 Java 侧同名默认值)。
*
* ========== 总体运算逻辑(与 RuleFunction.equipmentRule 一致)==========
* 1先拼「蓝方文本串」blueBlob任务 drawName、dataType、taskWeapons 下各武器的 name/supportType/equipmentId、组件 deviceName。
* 2对每个红方装备拼「红方文本串」redBlobname、platform_type、SupportType。
* 3每件红装得分 score = 规则槽得分(scoreRuleSlots) + 兼容层得分(scoreLegacyLayer),均为整数。
* - 规则槽:对 i=1..ruleSlotCount若 blueBlob 命中 blueRuleKeywords_i 且 redBlob 命中 redRuleKeywords_i
* 则加上 ruleScore_i * weight。
* - 兼容层:多组「蓝关键词 + 红关键词 + 对应分数」,见下方各键说明;每组条件同时满足则加上 对应Score * weight。
* 4在池中取 score 最大者;若多人并列,由 tieBreak 决定(见 tieBreak
* 5若 maxScore < minSelectedScore视为未匹配不往 fireRuleInputs 追加行redWeapons 输出仍为当前池。
* 6若匹配成功从池中 remove 该件fireRuleInputs 追加一行drawName 后接 outputDrawNameSuffixtaskWeapons 填选中红装映射。
*
* 关键词格式英文逗号分隔子串包含即算命中contains不要求整词匹配。
*/
function Map buildParam(){
Map param = new java.util.HashMap();
// ---------- 全局倍率与门槛 ----------
// weight对上述所有「基础分数」的统一乘数规则槽的 ruleScore_i、兼容层的 *Score 都会乘 weight
param.put("weight", 1);
// minSelectedScore单件红装总分达到该值及以上才会被选中并写入 fireRuleInputs否则本任务视为未匹配到装备。
param.put("minSelectedScore", 1);
// tieBreak并列最高分时的决胜方式。当前实现仅支持 "equipmentId":装备 ID 字典序更小的优先。
param.put("tieBreak", "equipmentId");
// outputDrawNameSuffix匹配成功写入 fireRuleInputs 时,在蓝方原 drawName 后面拼接的后缀(如「打击任务」)。
param.put("outputDrawNameSuffix", "打击任务");
// ---------- 规则槽(可配置条数,便于只改本文件而不改 Java----------
// ruleSlotCount启用几条槽规则第 i 条使用 blueRuleKeywords_i、redRuleKeywords_i、ruleScore_i。
param.put("ruleSlotCount", 3);
// 槽1蓝方文本中出现任一子串 且 红方文本中出现任一子串 → 加 ruleScore_1 * weight。
param.put("blueRuleKeywords_1", "F-16,F-35");
param.put("redRuleKeywords_1", "防空,导弹,无人机");
param.put("ruleScore_1", 5);
param.put("blueRuleKeywords_2", "坦克,装甲");
param.put("redRuleKeywords_2", "反坦克");
param.put("ruleScore_2", 4);
param.put("blueRuleKeywords_3", "地面,突击");
param.put("redRuleKeywords_3", "远火,榴弹,炮");
param.put("ruleScore_3", 2);
// ---------- 兼容层:按「场景关键词」配对加分(与 RuleFunction.scoreLegacyLayer 一一对应)----------
// 以下每组均为:蓝方文本命中第一列关键词 且 红方文本命中第二列关键词 → 加 第三列分数 * weight。
//
// ① 空中平台类:蓝方像「对空/机型」且红方像对空装备 → + airScore * weight
param.put("bluePlatformKeywords_air", "F-16,J-10,F-35");
param.put("redPreferredWhenBlueAir", "防空,导弹,无人机,直升机,空空");
param.put("airScore", 2);
// ② 任务文案像空中任务 且 红方偏好对空 → + airTaskScore * weight可与①叠加
param.put("airTaskKeywords", "空中,制空,拦截,空战");
param.put("airTaskScore", 10);
// ③ 任务文案像地面任务 且 红方偏好地面火力 → + groundScore * weight
param.put("groundTaskKeywords", "地面,突击,登陆");
param.put("redPreferredWhenGround", "远火,榴弹,炮,火箭");
param.put("groundScore", 1);
// ④ 蓝方像坦克/装甲目标 且 红方文本命中 redMatchKeywords_tank → + tankScore * weight
param.put("tankKeywords", "坦克,装甲");
param.put("redMatchKeywords_tank", "反坦克");
param.put("tankScore", 1);
// ⑤ 蓝方像导弹类 且 红方文本命中 redMatchKeywords_missile → + missileScore * weight
param.put("missileKeywords", "导弹,火箭弹,巡航");
param.put("redMatchKeywords_missile", "防空,导弹,导弹发射");
param.put("missileScore", 1);
// ===================== 目标分配参数(写入 Tasks.task.execute =====================
// executeTypeDefault生成 execute[0] 的类型字段
param.put("executeTypeDefault", "assault");
// targetPickModeroundRobin(稳定轮询) / random(伪随机但同输入稳定)
param.put("targetPickMode", "roundRobin");
// minTargetsPerRed / maxTargetsPerRedCap每个红方任务最少/最多分配的目标数
param.put("minTargetsPerRed", 1);
param.put("maxTargetsPerRedCap", 3);
// radToTargetsCsvsuccessTargetRad(命中率) -> 每红装目标数 的映射(阈值:目标数),按阈值从大到小匹配
// 例0.8:1,0.5:2,0.2:3 表示 successTargetRad>=0.8 分1个>=0.5 分2个>=0.2 分3个
param.put("radToTargetsCsv", "0.8:1,0.5:2,0.2:3");
// rangeParseRegex从 attDefaultValue/attExplain 中提取射程数值的正则取第1个数字
param.put("rangeParseRegex", "(\\\\d+(?:\\\\.\\\\d+)?)");
// rangeUnit提取数值的单位km/m二选一
param.put("rangeUnit", "km");
// minRangeToAllowAssignKm若解析到的蓝方射程小于该值则该蓝方装备不参与被分配无法解析则忽略此过滤
param.put("minRangeToAllowAssignKm", 0);
// ===================== 低命中率补拿装备参数 =====================
// redHitRateThreshold红方装备命中率阈值低于该值时触发补拿
param.put("redHitRateThreshold", 0.6);
// maxExtraWeaponsPerTask每条蓝方任务最多补拿几件红装
param.put("maxExtraWeaponsPerTask", 2);
// maxSupplementRounds补拿循环最大轮次防死循环
param.put("maxSupplementRounds", 2);
// extraPickMinScore补拿时红装最低匹配分
param.put("extraPickMinScore", 1);
// ===================== 阵位规则参数(写入 SubComponents.platform[].positions =====================
// positionRuleEnabled是否启用阵位规则。true=执行阵位生成false=跳过,不改 platform.positions。
param.put("positionRuleEnabled", true);
// positionAnchorMode锚点模式。当前实现使用 hybrid蓝方 taskWeapons.coordinate 的中心点作为主锚点)。
param.put("positionAnchorMode", "hybrid");
// trackPointDirectionMode航向计算模式。
// - head2next取 trackPoints[0] -> trackPoints[1] 作为方向(默认)
// - tail2prev取倒数第二个 -> 最后一个点作为方向
param.put("trackPointDirectionMode", "head2next");
// fallbackBearingDeg当 trackPoints 缺失或无法计算方位时使用该默认方位角0-360
param.put("fallbackBearingDeg", 0);
// deployDistanceKmMin部署距离下限km。最终距离不会小于该值。
param.put("deployDistanceKmMin", 8);
// deployDistanceKmMax部署距离上限km。最终距离不会大于该值。
param.put("deployDistanceKmMax", 30);
// deployDistanceKmDefault默认部署距离km
// 当 distanceByPlatformCsv 未命中任何关键词时,使用该值。
param.put("deployDistanceKmDefault", 15);
// distanceByPlatformCsv按“关键词”覆盖部署距离km不写死具体类型完全由业务配置。
// 格式:关键词:距离,关键词:距离(示例:防空:18,反坦克:10,迫击炮:8
// 匹配范围:红方装备 Name / Platform_type 文本包含关键词即命中。
// 优先级:命中后覆盖 deployDistanceKmDefault但最终仍受 deployDistanceKmMin 与 deployDistanceKmMax 约束。
param.put("distanceByPlatformCsv", "");
// formationType编队样式可选 line / wedge / circle。
param.put("formationType", "line");
// formationSpacingMeters编队间距影响同一红装下 platform[] 点位离散程度。
// 说明Java 侧会与 minInterPlatformDistanceMeters 比较,取更大值,避免平台重叠过近。
param.put("formationSpacingMeters", 300);
// formationHeadingOffsetDeg编队相对主航向的偏转角主要用于 wedge/circle 的分散方向。
param.put("formationHeadingOffsetDeg", 15);
// defaultDeployHeight默认部署高度用于 positions 第3位高度值基线。
param.put("defaultDeployHeight", 30);
// heightFollowBlueRatio高度跟随蓝方比例>=0
// 计算方式:高度 = defaultDeployHeight + 蓝方锚点平均高度 * heightFollowBlueRatio。
// 0 表示不跟随蓝方高度,仅使用默认高度。
param.put("heightFollowBlueRatio", 0.0);
// enableWarZoneClamp是否启用作战区约束。true=超出 warZoneLocation 时回拉到区内。
param.put("enableWarZoneClamp", true);
// warZoneClampMode作战区约束模式。当前实现使用 nearestInside沿锚点到目标点方向二分回拉到区内
param.put("warZoneClampMode", "nearestInside");
// minInterPlatformDistanceMeters平台最小间距下限用于抑制平台点位过度重叠。
param.put("minInterPlatformDistanceMeters", 80);
// ===================== 航迹规则参数(写入 TrackParam 动态 key + execute.targetList.moveRouteId =====================
// trackRuleEnabled是否启用航迹生成与 moveRouteId 绑定。
param.put("trackRuleEnabled", true);
// trackRouteAlgorithm航迹变形算法。followBlue(默认) / shortestPath / flank / jam
param.put("trackRouteAlgorithm", "followBlue");
// trackRouteNameSuffix航迹名称 = 红方任务 drawName + 此后缀(默认「航迹」→ 如 xxx打击任务航迹
param.put("trackRouteNameSuffix", "航迹");
// trackAirDataTypeCsv蓝方 dataType 命中任一子串(忽略大小写)则 TrackType=routeLineAir
param.put("trackAirDataTypeCsv", "taskPlane,air,plane,flight");
// trackAirKeywordsCsv蓝方 drawName 或红方 name/platformType 命中任一子串则视为飞行航迹
param.put("trackAirKeywordsCsv", "机,飞,空,J-,F-,无人机,直升机");
// trackGroundTrackType非飞行类时 TrackType 取值(可先占位,后续再接地面路网)
param.put("trackGroundTrackType", "routeLineGround");
// 航迹侧向算法复用上方「阵位规则」中的 trackPointDirectionModehead2next / tail2prev缺省回退见 trackFallbackBearingDeg
param.put("trackFallbackBearingDeg", 0);
// enableTrackWarZoneClamp航迹点是否约束在 warZoneLocation 多边形内
param.put("enableTrackWarZoneClamp", true);
// trackExtraNodesMax在蓝方航迹点基础上最多额外插入的点数0=与蓝方点数持平;>0 时在中段均匀插值)
param.put("trackExtraNodesMax", 0);
// shortestPath相邻两点间直线插值分段数>=1越大折线越平滑非真实路网最短路径
param.put("trackShortPathSegments", 3);
// flank侧向偏移距离trackFlankSideModealternate / left / right
param.put("trackFlankOffsetMeters", 800);
param.put("trackFlankSideMode", "alternate");
// jam正弦扰动振幅、沿航迹起伏周期数越大摆动越密
param.put("trackJamWobbleMeters", 400);
param.put("trackJamSegments", 4);
return param;
}
rule "装备匹配"
salience 100
when
$fact : DroolsFact(task != null)
then
// 以本文件 buildParam 为真源覆盖同名键,再执行 Java 侧匹配逻辑
globalParams.putAll(buildParam());
equipmentRule($fact, globalParams);
end
rule "目标匹配"
salience 90
when
$fact : DroolsFact(task != null)
then
// 显式目标分配规则:填充 Tasks.task.execute.targetList[*].targetId
globalParams.putAll(buildParam());
target($fact, globalParams);
end
rule "阵位匹配"
salience 80
when
$fact : DroolsFact(task != null)
then
// 显式阵位规则:填充 redWeapons.SubComponents.platform[].positions
globalParams.putAll(buildParam());
position($fact, globalParams);
end
rule "航迹匹配"
salience 70
when
$fact : DroolsFact(task != null)
then
// 显式航迹规则:填充 TrackParam 下各航迹 id并绑定 execute[0].targetList[*].moveRouteId
globalParams.putAll(buildParam());
trackRoute($fact, globalParams);
end

View File

@@ -0,0 +1,4 @@
# 已废弃:请在仓库根目录使用 Dockerfile 与 docker-compose.yml 构建镜像。
# Deprecated — use the Dockerfile at the repository root.
FROM alpine:3.19
RUN echo "ERROR: build from repo root (../Dockerfile). See docker/README.md" >&2 && exit 1

98
docker-compose.yml Normal file
View File

@@ -0,0 +1,98 @@
# 若依后端 + MySQL 8 + Redis 7
# 使用1) 将 SQL 放入 docker/mysql/init/(见该目录 README
# 2) 复制 .env.example 为 .env 并按需修改密码
# 3) docker compose up -d --build
#
# 应用访问http://localhost:1777容器内 8080 映射到宿主机 1777
services:
mysql:
image: mysql:8.0
container_name: autosolution-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root}
MYSQL_DATABASE: ${MYSQL_DATABASE:-autosolution_db}
TZ: Asia/Shanghai
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --default-authentication-plugin=mysql_native_password
ports:
- "${MYSQL_PORT:-3307}:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./docker/mysql/init:/docker-entrypoint-initdb.d:ro
healthcheck:
test:
[
"CMD-SHELL",
"mysql -h 127.0.0.1 -uroot -p$${MYSQL_ROOT_PASSWORD:-root} -Nse \"SELECT 1 FROM information_schema.tables WHERE table_schema='$${MYSQL_DATABASE:-autosolution_db}' AND table_name='sys_config' LIMIT 1\" | grep -q 1",
]
interval: 10s
timeout: 5s
retries: 10
start_period: 40s
redis:
image: redis:7-alpine
container_name: autosolution-redis
restart: unless-stopped
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
entrypoint: ["/bin/sh", "-c"]
command:
- |
if [ -n "$$REDIS_PASSWORD" ]; then
exec redis-server --appendonly yes --requirepass "$$REDIS_PASSWORD"
else
exec redis-server --appendonly yes
fi
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- redis_data:/data
healthcheck:
test:
[
"CMD-SHELL",
'if [ -n "$$REDIS_PASSWORD" ]; then redis-cli -a "$$REDIS_PASSWORD" ping | grep -q PONG; else redis-cli ping | grep -q PONG; fi',
]
interval: 5s
timeout: 3s
retries: 5
app:
# 运行已构建好的应用镜像(推荐:在有网络的机器上 docker build然后 docker save/load 到 CentOS
# 如需在本机从 Dockerfile 构建,请在另一份 compose 文件中加入 build 配置,或临时手动 docker build。
image: auto-solution-admin:${APP_IMAGE_TAG:-latest}
container_name: autosolution-app
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
environment:
MYSQL_HOST: mysql
MYSQL_PORT: "3306"
MYSQL_DATABASE: ${MYSQL_DATABASE:-autosolution_db}
MYSQL_USER: root
MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root}
REDIS_HOST: redis
REDIS_PORT: "6379"
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
REDIS_DB: "0"
SERVER_PORT: "8080"
SOLUTION_UPLOAD_PATH: /app/uploadPath
TZ: Asia/Shanghai
JAVA_OPTS: ${JAVA_OPTS:--Xms512m -Xmx1024m}
ports:
- "${APP_PORT:-1777}:8080"
volumes:
- app_upload:/app/uploadPath
volumes:
mysql_data:
redis_data:
app_upload:

52
docker/README.md Normal file
View File

@@ -0,0 +1,52 @@
# Docker 部署说明
## 前置条件
- 安装 [Docker Desktop](https://www.docker.com/products/docker-desktop/)Windows 需开启 WSL2
- 项目根目录:`auto-solution`(与 `Dockerfile``docker-compose.yml` 同级)。
## 快速开始
1. **准备数据库脚本**(首次必做)
将 SQL 放到 `docker/mysql/init/`,详见 [mysql/init/README.md](mysql/init/README.md)。
2. **环境变量(可选)**
```bash
copy .env.example .env
```
按需修改 `MYSQL_ROOT_PASSWORD`、`REDIS_PASSWORD` 等;若 Redis 设密码,需在 `.env` 中填写 `REDIS_PASSWORD`,并与应用一致。
3. **构建并启动**
```bash
docker compose build
docker compose up -d
```
4. **访问**
- 后端:<http://localhost:1777>(默认映射,可在 `.env` 改 `APP_PORT`
- MySQL宿主机端口默认 `3307`(避免与本机 3306 冲突)
- Redis宿主机端口默认 `6379`(与容器内端口一致,可通过 `.env` 中 `REDIS_PORT` 修改)
## 仅构建应用镜像
```bash
docker build -t auto-solution-admin:latest .
```
## 配置说明
- 容器内使用 Spring 配置:`druid` + `docker`,见 `auto-solution-admin/src/main/resources/application-docker.yml`。
- 数据源与 Redis 主机名在 Compose 中为 `mysql`、`redis`,勿改服务名除非同步改配置。
## 上传文件
附件目录使用数据卷 `app_upload`,持久化在 Docker volume `autosolution_app_upload`(名称前缀随项目目录可能略有不同)。
## 常见问题
- **应用连不上库**:确认 MySQL 健康检查已通过;`init` SQL 是否已执行(空库首次启动才会执行)。
- **Redis 认证失败**:本仓库 `application.yml` 里开发环境 Redis 带密码Compose 中 Redis 默认无密码。若需密码,在 `.env` 设置 `REDIS_PASSWORD`,并确保与 `application-docker.yml` 中 `REDIS_PASSWORD` 环境变量一致(已支持 `${REDIS_PASSWORD}`)。

View File

View File

@@ -0,0 +1,2 @@
CREATE DATABASE IF NOT EXISTS autosolution_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE autosolution_db;

View File

@@ -0,0 +1,704 @@
-- ----------------------------
-- 1、部门表
-- ----------------------------
drop table if exists sys_dept;
create table sys_dept (
dept_id bigint(20) not null auto_increment comment '部门id',
parent_id bigint(20) default 0 comment '父部门id',
ancestors varchar(50) default '' comment '祖级列表',
dept_name varchar(30) default '' comment '部门名称',
order_num int(4) default 0 comment '显示顺序',
leader varchar(20) default null comment '负责人',
phone varchar(11) default null comment '联系电话',
email varchar(50) default null comment '邮箱',
status char(1) default '0' comment '部门状态0正常 1停用',
del_flag char(1) default '0' comment '删除标志0代表存在 2代表删除',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
primary key (dept_id)
) engine=innodb auto_increment=200 comment = '部门表';
-- ----------------------------
-- 初始化-部门表数据
-- ----------------------------
insert into sys_dept values(100, 0, '0', '若依科技', 0, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(101, 100, '0,100', '深圳总公司', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(102, 100, '0,100', '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(103, 101, '0,100,101', '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(104, 101, '0,100,101', '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(105, 101, '0,100,101', '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(106, 101, '0,100,101', '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(107, 101, '0,100,101', '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(108, 102, '0,100,102', '市场部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
insert into sys_dept values(109, 102, '0,100,102', '财务部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null);
-- ----------------------------
-- 2、用户信息表
-- ----------------------------
drop table if exists sys_user;
create table sys_user (
user_id bigint(20) not null auto_increment comment '用户ID',
dept_id bigint(20) default null comment '部门ID',
user_name varchar(30) not null comment '用户账号',
nick_name varchar(30) not null comment '用户昵称',
user_type varchar(2) default '00' comment '用户类型00系统用户',
email varchar(50) default '' comment '用户邮箱',
phonenumber varchar(11) default '' comment '手机号码',
sex char(1) default '0' comment '用户性别0男 1女 2未知',
avatar varchar(100) default '' comment '头像地址',
password varchar(100) default '' comment '密码',
status char(1) default '0' comment '账号状态0正常 1停用',
del_flag char(1) default '0' comment '删除标志0代表存在 2代表删除',
login_ip varchar(128) default '' comment '最后登录IP',
login_date datetime comment '最后登录时间',
pwd_update_date datetime comment '密码最后更新时间',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (user_id)
) engine=innodb auto_increment=100 comment = '用户信息表';
-- ----------------------------
-- 初始化-用户信息表数据
-- ----------------------------
insert into sys_user values(1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
insert into sys_user values(2, 105, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), sysdate(), 'admin', sysdate(), '', null, '测试员');
-- ----------------------------
-- 3、岗位信息表
-- ----------------------------
drop table if exists sys_post;
create table sys_post
(
post_id bigint(20) not null auto_increment comment '岗位ID',
post_code varchar(64) not null comment '岗位编码',
post_name varchar(50) not null comment '岗位名称',
post_sort int(4) not null comment '显示顺序',
status char(1) not null comment '状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (post_id)
) engine=innodb comment = '岗位信息表';
-- ----------------------------
-- 初始化-岗位信息表数据
-- ----------------------------
insert into sys_post values(1, 'ceo', '董事长', 1, '0', 'admin', sysdate(), '', null, '');
insert into sys_post values(2, 'se', '项目经理', 2, '0', 'admin', sysdate(), '', null, '');
insert into sys_post values(3, 'hr', '人力资源', 3, '0', 'admin', sysdate(), '', null, '');
insert into sys_post values(4, 'user', '普通员工', 4, '0', 'admin', sysdate(), '', null, '');
-- ----------------------------
-- 4、角色信息表
-- ----------------------------
drop table if exists sys_role;
create table sys_role (
role_id bigint(20) not null auto_increment comment '角色ID',
role_name varchar(30) not null comment '角色名称',
role_key varchar(100) not null comment '角色权限字符串',
role_sort int(4) not null comment '显示顺序',
data_scope char(1) default '1' comment '数据范围1全部数据权限 2自定数据权限 3本部门数据权限 4本部门及以下数据权限',
menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示',
dept_check_strictly tinyint(1) default 1 comment '部门树选择项是否关联显示',
status char(1) not null comment '角色状态0正常 1停用',
del_flag char(1) default '0' comment '删除标志0代表存在 2代表删除',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (role_id)
) engine=innodb auto_increment=100 comment = '角色信息表';
-- ----------------------------
-- 初始化-角色信息表数据
-- ----------------------------
insert into sys_role values('1', '超级管理员', 'admin', 1, 1, 1, 1, '0', '0', 'admin', sysdate(), '', null, '超级管理员');
insert into sys_role values('2', '普通角色', 'common', 2, 2, 1, 1, '0', '0', 'admin', sysdate(), '', null, '普通角色');
-- ----------------------------
-- 5、菜单权限表
-- ----------------------------
drop table if exists sys_menu;
create table sys_menu (
menu_id bigint(20) not null auto_increment comment '菜单ID',
menu_name varchar(50) not null comment '菜单名称',
parent_id bigint(20) default 0 comment '父菜单ID',
order_num int(4) default 0 comment '显示顺序',
path varchar(200) default '' comment '路由地址',
component varchar(255) default null comment '组件路径',
query varchar(255) default null comment '路由参数',
route_name varchar(50) default '' comment '路由名称',
is_frame int(1) default 1 comment '是否为外链0是 1否',
is_cache int(1) default 0 comment '是否缓存0缓存 1不缓存',
menu_type char(1) default '' comment '菜单类型M目录 C菜单 F按钮',
visible char(1) default 0 comment '菜单状态0显示 1隐藏',
status char(1) default 0 comment '菜单状态0正常 1停用',
perms varchar(100) default null comment '权限标识',
icon varchar(100) default '#' comment '菜单图标',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (menu_id)
) engine=innodb auto_increment=2000 comment = '菜单权限表';
-- ----------------------------
-- 初始化-菜单信息表数据
-- ----------------------------
-- 一级菜单
insert into sys_menu values('1', '系统管理', '0', '1', 'system', null, '', '', 1, 0, 'M', '0', '0', '', 'system', 'admin', sysdate(), '', null, '系统管理目录');
insert into sys_menu values('2', '系统监控', '0', '2', 'monitor', null, '', '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', sysdate(), '', null, '系统监控目录');
insert into sys_menu values('3', '系统工具', '0', '3', 'tool', null, '', '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', sysdate(), '', null, '系统工具目录');
insert into sys_menu values('4', '若依官网', '0', '4', 'http://ruoyi.vip', null, '', '', 0, 0, 'M', '0', '0', '', 'guide', 'admin', sysdate(), '', null, '若依官网地址');
-- 二级菜单
insert into sys_menu values('100', '用户管理', '1', '1', 'user', 'system/user/index', '', '', 1, 0, 'C', '0', '0', 'system:user:list', 'user', 'admin', sysdate(), '', null, '用户管理菜单');
insert into sys_menu values('101', '角色管理', '1', '2', 'role', 'system/role/index', '', '', 1, 0, 'C', '0', '0', 'system:role:list', 'peoples', 'admin', sysdate(), '', null, '角色管理菜单');
insert into sys_menu values('102', '菜单管理', '1', '3', 'menu', 'system/menu/index', '', '', 1, 0, 'C', '0', '0', 'system:menu:list', 'tree-table', 'admin', sysdate(), '', null, '菜单管理菜单');
insert into sys_menu values('103', '部门管理', '1', '4', 'dept', 'system/dept/index', '', '', 1, 0, 'C', '0', '0', 'system:dept:list', 'tree', 'admin', sysdate(), '', null, '部门管理菜单');
insert into sys_menu values('104', '岗位管理', '1', '5', 'post', 'system/post/index', '', '', 1, 0, 'C', '0', '0', 'system:post:list', 'post', 'admin', sysdate(), '', null, '岗位管理菜单');
insert into sys_menu values('105', '字典管理', '1', '6', 'dict', 'system/dict/index', '', '', 1, 0, 'C', '0', '0', 'system:dict:list', 'dict', 'admin', sysdate(), '', null, '字典管理菜单');
insert into sys_menu values('106', '参数设置', '1', '7', 'config', 'system/config/index', '', '', 1, 0, 'C', '0', '0', 'system:config:list', 'edit', 'admin', sysdate(), '', null, '参数设置菜单');
insert into sys_menu values('107', '通知公告', '1', '8', 'notice', 'system/notice/index', '', '', 1, 0, 'C', '0', '0', 'system:notice:list', 'message', 'admin', sysdate(), '', null, '通知公告菜单');
insert into sys_menu values('108', '日志管理', '1', '9', 'log', '', '', '', 1, 0, 'M', '0', '0', '', 'log', 'admin', sysdate(), '', null, '日志管理菜单');
insert into sys_menu values('109', '在线用户', '2', '1', 'online', 'monitor/online/index', '', '', 1, 0, 'C', '0', '0', 'monitor:online:list', 'online', 'admin', sysdate(), '', null, '在线用户菜单');
insert into sys_menu values('110', '定时任务', '2', '2', 'job', 'monitor/job/index', '', '', 1, 0, 'C', '0', '0', 'monitor:job:list', 'job', 'admin', sysdate(), '', null, '定时任务菜单');
insert into sys_menu values('111', '数据监控', '2', '3', 'druid', 'monitor/druid/index', '', '', 1, 0, 'C', '0', '0', 'monitor:druid:list', 'druid', 'admin', sysdate(), '', null, '数据监控菜单');
insert into sys_menu values('112', '服务监控', '2', '4', 'server', 'monitor/server/index', '', '', 1, 0, 'C', '0', '0', 'monitor:server:list', 'server', 'admin', sysdate(), '', null, '服务监控菜单');
insert into sys_menu values('113', '缓存监控', '2', '5', 'cache', 'monitor/cache/index', '', '', 1, 0, 'C', '0', '0', 'monitor:cache:list', 'redis', 'admin', sysdate(), '', null, '缓存监控菜单');
insert into sys_menu values('114', '缓存列表', '2', '6', 'cacheList', 'monitor/cache/list', '', '', 1, 0, 'C', '0', '0', 'monitor:cache:list', 'redis-list', 'admin', sysdate(), '', null, '缓存列表菜单');
insert into sys_menu values('115', '表单构建', '3', '1', 'build', 'tool/build/index', '', '', 1, 0, 'C', '0', '0', 'tool:build:list', 'build', 'admin', sysdate(), '', null, '表单构建菜单');
insert into sys_menu values('116', '代码生成', '3', '2', 'gen', 'tool/gen/index', '', '', 1, 0, 'C', '0', '0', 'tool:gen:list', 'code', 'admin', sysdate(), '', null, '代码生成菜单');
insert into sys_menu values('117', '系统接口', '3', '3', 'swagger', 'tool/swagger/index', '', '', 1, 0, 'C', '0', '0', 'tool:swagger:list', 'swagger', 'admin', sysdate(), '', null, '系统接口菜单');
-- 三级菜单
insert into sys_menu values('500', '操作日志', '108', '1', 'operlog', 'monitor/operlog/index', '', '', 1, 0, 'C', '0', '0', 'monitor:operlog:list', 'form', 'admin', sysdate(), '', null, '操作日志菜单');
insert into sys_menu values('501', '登录日志', '108', '2', 'logininfor', 'monitor/logininfor/index', '', '', 1, 0, 'C', '0', '0', 'monitor:logininfor:list', 'logininfor', 'admin', sysdate(), '', null, '登录日志菜单');
-- 用户管理按钮
insert into sys_menu values('1000', '用户查询', '100', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:user:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1001', '用户新增', '100', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:user:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1002', '用户修改', '100', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:user:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1003', '用户删除', '100', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:user:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1004', '用户导出', '100', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'system:user:export', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1005', '用户导入', '100', '6', '', '', '', '', 1, 0, 'F', '0', '0', 'system:user:import', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1006', '重置密码', '100', '7', '', '', '', '', 1, 0, 'F', '0', '0', 'system:user:resetPwd', '#', 'admin', sysdate(), '', null, '');
-- 角色管理按钮
insert into sys_menu values('1007', '角色查询', '101', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:role:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1008', '角色新增', '101', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:role:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1009', '角色修改', '101', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:role:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1010', '角色删除', '101', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:role:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1011', '角色导出', '101', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'system:role:export', '#', 'admin', sysdate(), '', null, '');
-- 菜单管理按钮
insert into sys_menu values('1012', '菜单查询', '102', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1013', '菜单新增', '102', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1014', '菜单修改', '102', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1015', '菜单删除', '102', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:menu:remove', '#', 'admin', sysdate(), '', null, '');
-- 部门管理按钮
insert into sys_menu values('1016', '部门查询', '103', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1017', '部门新增', '103', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1018', '部门修改', '103', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1019', '部门删除', '103', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:dept:remove', '#', 'admin', sysdate(), '', null, '');
-- 岗位管理按钮
insert into sys_menu values('1020', '岗位查询', '104', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:post:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1021', '岗位新增', '104', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:post:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1022', '岗位修改', '104', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:post:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1023', '岗位删除', '104', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:post:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1024', '岗位导出', '104', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'system:post:export', '#', 'admin', sysdate(), '', null, '');
-- 字典管理按钮
insert into sys_menu values('1025', '字典查询', '105', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:dict:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1026', '字典新增', '105', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:dict:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1027', '字典修改', '105', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:dict:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1028', '字典删除', '105', '4', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:dict:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1029', '字典导出', '105', '5', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:dict:export', '#', 'admin', sysdate(), '', null, '');
-- 参数设置按钮
insert into sys_menu values('1030', '参数查询', '106', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:config:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1031', '参数新增', '106', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:config:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1032', '参数修改', '106', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:config:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1033', '参数删除', '106', '4', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:config:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1034', '参数导出', '106', '5', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:config:export', '#', 'admin', sysdate(), '', null, '');
-- 通知公告按钮
insert into sys_menu values('1035', '公告查询', '107', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:notice:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1036', '公告新增', '107', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:notice:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1037', '公告修改', '107', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:notice:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1038', '公告删除', '107', '4', '#', '', '', '', 1, 0, 'F', '0', '0', 'system:notice:remove', '#', 'admin', sysdate(), '', null, '');
-- 操作日志按钮
insert into sys_menu values('1039', '操作查询', '500', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1040', '操作删除', '500', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1041', '日志导出', '500', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:export', '#', 'admin', sysdate(), '', null, '');
-- 登录日志按钮
insert into sys_menu values('1042', '登录查询', '501', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1043', '登录删除', '501', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1044', '日志导出', '501', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:export', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1045', '账户解锁', '501', '4', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:unlock', '#', 'admin', sysdate(), '', null, '');
-- 在线用户按钮
insert into sys_menu values('1046', '在线查询', '109', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:online:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1047', '批量强退', '109', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:online:batchLogout', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1048', '单条强退', '109', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:online:forceLogout', '#', 'admin', sysdate(), '', null, '');
-- 定时任务按钮
insert into sys_menu values('1049', '任务查询', '110', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:job:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1050', '任务新增', '110', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:job:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1051', '任务修改', '110', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:job:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1052', '任务删除', '110', '4', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:job:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1053', '状态修改', '110', '5', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:job:changeStatus', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1054', '任务导出', '110', '6', '#', '', '', '', 1, 0, 'F', '0', '0', 'monitor:job:export', '#', 'admin', sysdate(), '', null, '');
-- 代码生成按钮
insert into sys_menu values('1055', '生成查询', '116', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'tool:gen:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1056', '生成修改', '116', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'tool:gen:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1057', '生成删除', '116', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'tool:gen:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1058', '导入代码', '116', '4', '#', '', '', '', 1, 0, 'F', '0', '0', 'tool:gen:import', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1059', '预览代码', '116', '5', '#', '', '', '', 1, 0, 'F', '0', '0', 'tool:gen:preview', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1060', '生成代码', '116', '6', '#', '', '', '', 1, 0, 'F', '0', '0', 'tool:gen:code', '#', 'admin', sysdate(), '', null, '');
-- ----------------------------
-- 6、用户和角色关联表 用户N-1角色
-- ----------------------------
drop table if exists sys_user_role;
create table sys_user_role (
user_id bigint(20) not null comment '用户ID',
role_id bigint(20) not null comment '角色ID',
primary key(user_id, role_id)
) engine=innodb comment = '用户和角色关联表';
-- ----------------------------
-- 初始化-用户和角色关联表数据
-- ----------------------------
insert into sys_user_role values ('1', '1');
insert into sys_user_role values ('2', '2');
-- ----------------------------
-- 7、角色和菜单关联表 角色1-N菜单
-- ----------------------------
drop table if exists sys_role_menu;
create table sys_role_menu (
role_id bigint(20) not null comment '角色ID',
menu_id bigint(20) not null comment '菜单ID',
primary key(role_id, menu_id)
) engine=innodb comment = '角色和菜单关联表';
-- ----------------------------
-- 初始化-角色和菜单关联表数据
-- ----------------------------
insert into sys_role_menu values ('2', '1');
insert into sys_role_menu values ('2', '2');
insert into sys_role_menu values ('2', '3');
insert into sys_role_menu values ('2', '4');
insert into sys_role_menu values ('2', '100');
insert into sys_role_menu values ('2', '101');
insert into sys_role_menu values ('2', '102');
insert into sys_role_menu values ('2', '103');
insert into sys_role_menu values ('2', '104');
insert into sys_role_menu values ('2', '105');
insert into sys_role_menu values ('2', '106');
insert into sys_role_menu values ('2', '107');
insert into sys_role_menu values ('2', '108');
insert into sys_role_menu values ('2', '109');
insert into sys_role_menu values ('2', '110');
insert into sys_role_menu values ('2', '111');
insert into sys_role_menu values ('2', '112');
insert into sys_role_menu values ('2', '113');
insert into sys_role_menu values ('2', '114');
insert into sys_role_menu values ('2', '115');
insert into sys_role_menu values ('2', '116');
insert into sys_role_menu values ('2', '117');
insert into sys_role_menu values ('2', '500');
insert into sys_role_menu values ('2', '501');
insert into sys_role_menu values ('2', '1000');
insert into sys_role_menu values ('2', '1001');
insert into sys_role_menu values ('2', '1002');
insert into sys_role_menu values ('2', '1003');
insert into sys_role_menu values ('2', '1004');
insert into sys_role_menu values ('2', '1005');
insert into sys_role_menu values ('2', '1006');
insert into sys_role_menu values ('2', '1007');
insert into sys_role_menu values ('2', '1008');
insert into sys_role_menu values ('2', '1009');
insert into sys_role_menu values ('2', '1010');
insert into sys_role_menu values ('2', '1011');
insert into sys_role_menu values ('2', '1012');
insert into sys_role_menu values ('2', '1013');
insert into sys_role_menu values ('2', '1014');
insert into sys_role_menu values ('2', '1015');
insert into sys_role_menu values ('2', '1016');
insert into sys_role_menu values ('2', '1017');
insert into sys_role_menu values ('2', '1018');
insert into sys_role_menu values ('2', '1019');
insert into sys_role_menu values ('2', '1020');
insert into sys_role_menu values ('2', '1021');
insert into sys_role_menu values ('2', '1022');
insert into sys_role_menu values ('2', '1023');
insert into sys_role_menu values ('2', '1024');
insert into sys_role_menu values ('2', '1025');
insert into sys_role_menu values ('2', '1026');
insert into sys_role_menu values ('2', '1027');
insert into sys_role_menu values ('2', '1028');
insert into sys_role_menu values ('2', '1029');
insert into sys_role_menu values ('2', '1030');
insert into sys_role_menu values ('2', '1031');
insert into sys_role_menu values ('2', '1032');
insert into sys_role_menu values ('2', '1033');
insert into sys_role_menu values ('2', '1034');
insert into sys_role_menu values ('2', '1035');
insert into sys_role_menu values ('2', '1036');
insert into sys_role_menu values ('2', '1037');
insert into sys_role_menu values ('2', '1038');
insert into sys_role_menu values ('2', '1039');
insert into sys_role_menu values ('2', '1040');
insert into sys_role_menu values ('2', '1041');
insert into sys_role_menu values ('2', '1042');
insert into sys_role_menu values ('2', '1043');
insert into sys_role_menu values ('2', '1044');
insert into sys_role_menu values ('2', '1045');
insert into sys_role_menu values ('2', '1046');
insert into sys_role_menu values ('2', '1047');
insert into sys_role_menu values ('2', '1048');
insert into sys_role_menu values ('2', '1049');
insert into sys_role_menu values ('2', '1050');
insert into sys_role_menu values ('2', '1051');
insert into sys_role_menu values ('2', '1052');
insert into sys_role_menu values ('2', '1053');
insert into sys_role_menu values ('2', '1054');
insert into sys_role_menu values ('2', '1055');
insert into sys_role_menu values ('2', '1056');
insert into sys_role_menu values ('2', '1057');
insert into sys_role_menu values ('2', '1058');
insert into sys_role_menu values ('2', '1059');
insert into sys_role_menu values ('2', '1060');
-- ----------------------------
-- 8、角色和部门关联表 角色1-N部门
-- ----------------------------
drop table if exists sys_role_dept;
create table sys_role_dept (
role_id bigint(20) not null comment '角色ID',
dept_id bigint(20) not null comment '部门ID',
primary key(role_id, dept_id)
) engine=innodb comment = '角色和部门关联表';
-- ----------------------------
-- 初始化-角色和部门关联表数据
-- ----------------------------
insert into sys_role_dept values ('2', '100');
insert into sys_role_dept values ('2', '101');
insert into sys_role_dept values ('2', '105');
-- ----------------------------
-- 9、用户与岗位关联表 用户1-N岗位
-- ----------------------------
drop table if exists sys_user_post;
create table sys_user_post
(
user_id bigint(20) not null comment '用户ID',
post_id bigint(20) not null comment '岗位ID',
primary key (user_id, post_id)
) engine=innodb comment = '用户与岗位关联表';
-- ----------------------------
-- 初始化-用户与岗位关联表数据
-- ----------------------------
insert into sys_user_post values ('1', '1');
insert into sys_user_post values ('2', '2');
-- ----------------------------
-- 10、操作日志记录
-- ----------------------------
drop table if exists sys_oper_log;
create table sys_oper_log (
oper_id bigint(20) not null auto_increment comment '日志主键',
title varchar(50) default '' comment '模块标题',
business_type int(2) default 0 comment '业务类型0其它 1新增 2修改 3删除',
method varchar(200) default '' comment '方法名称',
request_method varchar(10) default '' comment '请求方式',
operator_type int(1) default 0 comment '操作类别0其它 1后台用户 2手机端用户',
oper_name varchar(50) default '' comment '操作人员',
dept_name varchar(50) default '' comment '部门名称',
oper_url varchar(255) default '' comment '请求URL',
oper_ip varchar(128) default '' comment '主机地址',
oper_location varchar(255) default '' comment '操作地点',
oper_param varchar(2000) default '' comment '请求参数',
json_result varchar(2000) default '' comment '返回参数',
status int(1) default 0 comment '操作状态0正常 1异常',
error_msg varchar(2000) default '' comment '错误消息',
oper_time datetime comment '操作时间',
cost_time bigint(20) default 0 comment '消耗时间',
primary key (oper_id),
key idx_sys_oper_log_bt (business_type),
key idx_sys_oper_log_s (status),
key idx_sys_oper_log_ot (oper_time)
) engine=innodb auto_increment=100 comment = '操作日志记录';
-- ----------------------------
-- 11、字典类型表
-- ----------------------------
drop table if exists sys_dict_type;
create table sys_dict_type
(
dict_id bigint(20) not null auto_increment comment '字典主键',
dict_name varchar(100) default '' comment '字典名称',
dict_type varchar(100) default '' comment '字典类型',
status char(1) default '0' comment '状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (dict_id),
unique (dict_type)
) engine=innodb auto_increment=100 comment = '字典类型表';
insert into sys_dict_type values(1, '用户性别', 'sys_user_sex', '0', 'admin', sysdate(), '', null, '用户性别列表');
insert into sys_dict_type values(2, '菜单状态', 'sys_show_hide', '0', 'admin', sysdate(), '', null, '菜单状态列表');
insert into sys_dict_type values(3, '系统开关', 'sys_normal_disable', '0', 'admin', sysdate(), '', null, '系统开关列表');
insert into sys_dict_type values(4, '任务状态', 'sys_job_status', '0', 'admin', sysdate(), '', null, '任务状态列表');
insert into sys_dict_type values(5, '任务分组', 'sys_job_group', '0', 'admin', sysdate(), '', null, '任务分组列表');
insert into sys_dict_type values(6, '系统是否', 'sys_yes_no', '0', 'admin', sysdate(), '', null, '系统是否列表');
insert into sys_dict_type values(7, '通知类型', 'sys_notice_type', '0', 'admin', sysdate(), '', null, '通知类型列表');
insert into sys_dict_type values(8, '通知状态', 'sys_notice_status', '0', 'admin', sysdate(), '', null, '通知状态列表');
insert into sys_dict_type values(9, '操作类型', 'sys_oper_type', '0', 'admin', sysdate(), '', null, '操作类型列表');
insert into sys_dict_type values(10, '系统状态', 'sys_common_status', '0', 'admin', sysdate(), '', null, '登录状态列表');
-- ----------------------------
-- 12、字典数据表
-- ----------------------------
drop table if exists sys_dict_data;
create table sys_dict_data
(
dict_code bigint(20) not null auto_increment comment '字典编码',
dict_sort int(4) default 0 comment '字典排序',
dict_label varchar(100) default '' comment '字典标签',
dict_value varchar(100) default '' comment '字典键值',
dict_type varchar(100) default '' comment '字典类型',
css_class varchar(100) default null comment '样式属性(其他样式扩展)',
list_class varchar(100) default null comment '表格回显样式',
is_default char(1) default 'N' comment '是否默认Y是 N否',
status char(1) default '0' comment '状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (dict_code)
) engine=innodb auto_increment=100 comment = '字典数据表';
insert into sys_dict_data values(1, 1, '', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', sysdate(), '', null, '性别男');
insert into sys_dict_data values(2, 2, '', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别女');
insert into sys_dict_data values(3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别未知');
insert into sys_dict_data values(4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '显示菜单');
insert into sys_dict_data values(5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '隐藏菜单');
insert into sys_dict_data values(6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
insert into sys_dict_data values(7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态');
insert into sys_dict_data values(8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
insert into sys_dict_data values(9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态');
insert into sys_dict_data values(10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '0', 'admin', sysdate(), '', null, '默认分组');
insert into sys_dict_data values(11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '0', 'admin', sysdate(), '', null, '系统分组');
insert into sys_dict_data values(12, 1, '', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '系统默认是');
insert into sys_dict_data values(13, 2, '', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '系统默认否');
insert into sys_dict_data values(14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', sysdate(), '', null, '通知');
insert into sys_dict_data values(15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '公告');
insert into sys_dict_data values(16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
insert into sys_dict_data values(17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '关闭状态');
insert into sys_dict_data values(18, 99, '其他', '0', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '其他操作');
insert into sys_dict_data values(19, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '新增操作');
insert into sys_dict_data values(20, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '修改操作');
insert into sys_dict_data values(21, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '删除操作');
insert into sys_dict_data values(22, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '授权操作');
insert into sys_dict_data values(23, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导出操作');
insert into sys_dict_data values(24, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导入操作');
insert into sys_dict_data values(25, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '强退操作');
insert into sys_dict_data values(26, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '生成操作');
insert into sys_dict_data values(27, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '清空操作');
insert into sys_dict_data values(28, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '正常状态');
insert into sys_dict_data values(29, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态');
-- ----------------------------
-- 13、参数配置表
-- ----------------------------
drop table if exists sys_config;
create table sys_config (
config_id int(5) not null auto_increment comment '参数主键',
config_name varchar(100) default '' comment '参数名称',
config_key varchar(100) default '' comment '参数键名',
config_value varchar(500) default '' comment '参数键值',
config_type char(1) default 'N' comment '系统内置Y是 N否',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (config_id)
) engine=innodb auto_increment=100 comment = '参数配置表';
insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow' );
insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456' );
insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深色主题theme-dark浅色主题theme-light' );
insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启验证码功能true开启false关闭');
insert into sys_config values(5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能true开启false关闭');
insert into sys_config values(6, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', sysdate(), '', null, '设置登录IP黑名单限制多个匹配项以;分隔,支持匹配(*通配、网段)');
insert into sys_config values(7, '用户管理-初始密码修改策略', 'sys.account.initPasswordModify', '1', 'Y', 'admin', sysdate(), '', null, '0初始密码修改策略关闭没有任何提示1提醒用户如果未修改初始密码则在登录时就会提醒修改密码对话框');
insert into sys_config values(8, '用户管理-账号密码更新周期', 'sys.account.passwordValidateDays', '0', 'Y', 'admin', sysdate(), '', null, '密码更新周期填写数字数据初始化值为0不限制若修改必须为大于0小于365的正整数如果超过这个周期登录系统时则在登录时就会提醒修改密码对话框');
-- ----------------------------
-- 14、系统访问记录
-- ----------------------------
drop table if exists sys_logininfor;
create table sys_logininfor (
info_id bigint(20) not null auto_increment comment '访问ID',
user_name varchar(50) default '' comment '用户账号',
ipaddr varchar(128) default '' comment '登录IP地址',
login_location varchar(255) default '' comment '登录地点',
browser varchar(50) default '' comment '浏览器类型',
os varchar(50) default '' comment '操作系统',
status char(1) default '0' comment '登录状态0成功 1失败',
msg varchar(255) default '' comment '提示消息',
login_time datetime comment '访问时间',
primary key (info_id),
key idx_sys_logininfor_s (status),
key idx_sys_logininfor_lt (login_time)
) engine=innodb auto_increment=100 comment = '系统访问记录';
-- ----------------------------
-- 15、定时任务调度表
-- ----------------------------
drop table if exists sys_job;
create table sys_job (
job_id bigint(20) not null auto_increment comment '任务ID',
job_name varchar(64) default '' comment '任务名称',
job_group varchar(64) default 'DEFAULT' comment '任务组名',
invoke_target varchar(500) not null comment '调用目标字符串',
cron_expression varchar(255) default '' comment 'cron执行表达式',
misfire_policy varchar(20) default '3' comment '计划执行错误策略1立即执行 2执行一次 3放弃执行',
concurrent char(1) default '1' comment '是否并发执行0允许 1禁止',
status char(1) default '0' comment '状态0正常 1暂停',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注信息',
primary key (job_id, job_name, job_group)
) engine=innodb auto_increment=100 comment = '定时任务调度表';
insert into sys_job values(1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
insert into sys_job values(2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
insert into sys_job values(3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
-- ----------------------------
-- 16、定时任务调度日志表
-- ----------------------------
drop table if exists sys_job_log;
create table sys_job_log (
job_log_id bigint(20) not null auto_increment comment '任务日志ID',
job_name varchar(64) not null comment '任务名称',
job_group varchar(64) not null comment '任务组名',
invoke_target varchar(500) not null comment '调用目标字符串',
job_message varchar(500) comment '日志信息',
status char(1) default '0' comment '执行状态0正常 1失败',
exception_info varchar(2000) default '' comment '异常信息',
create_time datetime comment '创建时间',
primary key (job_log_id)
) engine=innodb comment = '定时任务调度日志表';
-- ----------------------------
-- 17、通知公告表
-- ----------------------------
drop table if exists sys_notice;
create table sys_notice (
notice_id int(4) not null auto_increment comment '公告ID',
notice_title varchar(50) not null comment '公告标题',
notice_type char(1) not null comment '公告类型1通知 2公告',
notice_content longblob default null comment '公告内容',
status char(1) default '0' comment '公告状态0正常 1关闭',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(255) default null comment '备注',
primary key (notice_id)
) engine=innodb auto_increment=10 comment = '通知公告表';
-- ----------------------------
-- 初始化-公告信息表数据
-- ----------------------------
insert into sys_notice values('1', '温馨提醒2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', sysdate(), '', null, '管理员');
insert into sys_notice values('2', '维护通知2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', sysdate(), '', null, '管理员');
-- ----------------------------
-- 18、代码生成业务表
-- ----------------------------
drop table if exists gen_table;
create table gen_table (
table_id bigint(20) not null auto_increment comment '编号',
table_name varchar(200) default '' comment '表名称',
table_comment varchar(500) default '' comment '表描述',
sub_table_name varchar(64) default null comment '关联子表的表名',
sub_table_fk_name varchar(64) default null comment '子表关联的外键名',
class_name varchar(100) default '' comment '实体类名称',
tpl_category varchar(200) default 'crud' comment '使用的模板crud单表操作 tree树表操作',
tpl_web_type varchar(30) default '' comment '前端模板类型element-ui模版 element-plus模版',
package_name varchar(100) comment '生成包路径',
module_name varchar(30) comment '生成模块名',
business_name varchar(30) comment '生成业务名',
function_name varchar(50) comment '生成功能名',
function_author varchar(50) comment '生成功能作者',
gen_type char(1) default '0' comment '生成代码方式0zip压缩包 1自定义路径',
gen_path varchar(200) default '/' comment '生成路径(不填默认项目路径)',
options varchar(1000) comment '其它生成选项',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (table_id)
) engine=innodb auto_increment=1 comment = '代码生成业务表';
-- ----------------------------
-- 19、代码生成业务表字段
-- ----------------------------
drop table if exists gen_table_column;
create table gen_table_column (
column_id bigint(20) not null auto_increment comment '编号',
table_id bigint(20) comment '归属表编号',
column_name varchar(200) comment '列名称',
column_comment varchar(500) comment '列描述',
column_type varchar(100) comment '列类型',
java_type varchar(500) comment 'JAVA类型',
java_field varchar(200) comment 'JAVA字段名',
is_pk char(1) comment '是否主键1是',
is_increment char(1) comment '是否自增1是',
is_required char(1) comment '是否必填1是',
is_insert char(1) comment '是否为插入字段1是',
is_edit char(1) comment '是否编辑字段1是',
is_list char(1) comment '是否列表字段1是',
is_query char(1) comment '是否查询字段1是',
query_type varchar(200) default 'EQ' comment '查询方式(等于、不等于、大于、小于、范围)',
html_type varchar(200) comment '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)',
dict_type varchar(200) default '' comment '字典类型',
sort int comment '排序',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
primary key (column_id)
) engine=innodb auto_increment=1 comment = '代码生成业务表字段';

View File

@@ -0,0 +1,174 @@
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
-- ----------------------------
-- 1、存储每一个已配置的 jobDetail 的详细信息
-- ----------------------------
create table QRTZ_JOB_DETAILS (
sched_name varchar(120) not null comment '调度名称',
job_name varchar(200) not null comment '任务名称',
job_group varchar(200) not null comment '任务组名',
description varchar(250) null comment '相关介绍',
job_class_name varchar(250) not null comment '执行任务类名称',
is_durable varchar(1) not null comment '是否持久化',
is_nonconcurrent varchar(1) not null comment '是否并发',
is_update_data varchar(1) not null comment '是否更新数据',
requests_recovery varchar(1) not null comment '是否接受恢复执行',
job_data blob null comment '存放持久化job对象',
primary key (sched_name, job_name, job_group)
) engine=innodb comment = '任务详细信息表';
-- ----------------------------
-- 2、 存储已配置的 Trigger 的信息
-- ----------------------------
create table QRTZ_TRIGGERS (
sched_name varchar(120) not null comment '调度名称',
trigger_name varchar(200) not null comment '触发器的名字',
trigger_group varchar(200) not null comment '触发器所属组的名字',
job_name varchar(200) not null comment 'qrtz_job_details表job_name的外键',
job_group varchar(200) not null comment 'qrtz_job_details表job_group的外键',
description varchar(250) null comment '相关介绍',
next_fire_time bigint(13) null comment '上一次触发时间(毫秒)',
prev_fire_time bigint(13) null comment '下一次触发时间(默认为-1表示不触发',
priority integer null comment '优先级',
trigger_state varchar(16) not null comment '触发器状态',
trigger_type varchar(8) not null comment '触发器的类型',
start_time bigint(13) not null comment '开始时间',
end_time bigint(13) null comment '结束时间',
calendar_name varchar(200) null comment '日程表名称',
misfire_instr smallint(2) null comment '补偿执行的策略',
job_data blob null comment '存放持久化job对象',
primary key (sched_name, trigger_name, trigger_group),
foreign key (sched_name, job_name, job_group) references QRTZ_JOB_DETAILS(sched_name, job_name, job_group)
) engine=innodb comment = '触发器详细信息表';
-- ----------------------------
-- 3、 存储简单的 Trigger包括重复次数间隔以及已触发的次数
-- ----------------------------
create table QRTZ_SIMPLE_TRIGGERS (
sched_name varchar(120) not null comment '调度名称',
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
repeat_count bigint(7) not null comment '重复的次数统计',
repeat_interval bigint(12) not null comment '重复的间隔时间',
times_triggered bigint(10) not null comment '已经触发的次数',
primary key (sched_name, trigger_name, trigger_group),
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
) engine=innodb comment = '简单触发器的信息表';
-- ----------------------------
-- 4、 存储 Cron Trigger包括 Cron 表达式和时区信息
-- ----------------------------
create table QRTZ_CRON_TRIGGERS (
sched_name varchar(120) not null comment '调度名称',
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
cron_expression varchar(200) not null comment 'cron表达式',
time_zone_id varchar(80) comment '时区',
primary key (sched_name, trigger_name, trigger_group),
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
) engine=innodb comment = 'Cron类型的触发器表';
-- ----------------------------
-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型JobStore 并不知道如何存储实例的时候)
-- ----------------------------
create table QRTZ_BLOB_TRIGGERS (
sched_name varchar(120) not null comment '调度名称',
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
blob_data blob null comment '存放持久化Trigger对象',
primary key (sched_name, trigger_name, trigger_group),
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
) engine=innodb comment = 'Blob类型的触发器表';
-- ----------------------------
-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围
-- ----------------------------
create table QRTZ_CALENDARS (
sched_name varchar(120) not null comment '调度名称',
calendar_name varchar(200) not null comment '日历名称',
calendar blob not null comment '存放持久化calendar对象',
primary key (sched_name, calendar_name)
) engine=innodb comment = '日历信息表';
-- ----------------------------
-- 7、 存储已暂停的 Trigger 组的信息
-- ----------------------------
create table QRTZ_PAUSED_TRIGGER_GRPS (
sched_name varchar(120) not null comment '调度名称',
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
primary key (sched_name, trigger_group)
) engine=innodb comment = '暂停的触发器表';
-- ----------------------------
-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息
-- ----------------------------
create table QRTZ_FIRED_TRIGGERS (
sched_name varchar(120) not null comment '调度名称',
entry_id varchar(95) not null comment '调度器实例id',
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
instance_name varchar(200) not null comment '调度器实例名',
fired_time bigint(13) not null comment '触发的时间',
sched_time bigint(13) not null comment '定时器制定的时间',
priority integer not null comment '优先级',
state varchar(16) not null comment '状态',
job_name varchar(200) null comment '任务名称',
job_group varchar(200) null comment '任务组名',
is_nonconcurrent varchar(1) null comment '是否并发',
requests_recovery varchar(1) null comment '是否接受恢复执行',
primary key (sched_name, entry_id)
) engine=innodb comment = '已触发的触发器表';
-- ----------------------------
-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例
-- ----------------------------
create table QRTZ_SCHEDULER_STATE (
sched_name varchar(120) not null comment '调度名称',
instance_name varchar(200) not null comment '实例名称',
last_checkin_time bigint(13) not null comment '上次检查时间',
checkin_interval bigint(13) not null comment '检查间隔时间',
primary key (sched_name, instance_name)
) engine=innodb comment = '调度器状态表';
-- ----------------------------
-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁)
-- ----------------------------
create table QRTZ_LOCKS (
sched_name varchar(120) not null comment '调度名称',
lock_name varchar(40) not null comment '悲观锁名称',
primary key (sched_name, lock_name)
) engine=innodb comment = '存储的悲观锁信息表';
-- ----------------------------
-- 11、 Quartz集群实现同步机制的行锁表
-- ----------------------------
create table QRTZ_SIMPROP_TRIGGERS (
sched_name varchar(120) not null comment '调度名称',
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
str_prop_1 varchar(512) null comment 'String类型的trigger的第一个参数',
str_prop_2 varchar(512) null comment 'String类型的trigger的第二个参数',
str_prop_3 varchar(512) null comment 'String类型的trigger的第三个参数',
int_prop_1 int null comment 'int类型的trigger的第一个参数',
int_prop_2 int null comment 'int类型的trigger的第二个参数',
long_prop_1 bigint null comment 'long类型的trigger的第一个参数',
long_prop_2 bigint null comment 'long类型的trigger的第二个参数',
dec_prop_1 numeric(13,4) null comment 'decimal类型的trigger的第一个参数',
dec_prop_2 numeric(13,4) null comment 'decimal类型的trigger的第二个参数',
bool_prop_1 varchar(1) null comment 'Boolean类型的trigger的第一个参数',
bool_prop_2 varchar(1) null comment 'Boolean类型的trigger的第二个参数',
primary key (sched_name, trigger_name, trigger_group),
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group)
) engine=innodb comment = '同步机制的行锁表';
commit;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
# MySQL 首次初始化 SQL
MySQL 官方镜像会在**数据目录为空**时,按文件名顺序执行本目录下:
- `*.sql`
- `*.sql.gz`
- `*.sh`
## 你需要做的事
1. 从本机现有库导出(示例):
```bash
mysqldump -uroot -p --databases autosolution_db --single-transaction --quick > docker/mysql/init/01-autosolution_db.sql
```
2. 或放入若依官方 `ry_*.sql` 与 Quartz 等脚本,**按依赖顺序**命名前缀(如 `01-`、`02-`)。
3. 若容器/卷里已经有数据,这些脚本**不会再次执行**。需要重新初始化时:
```bash
docker compose down -v
docker compose up -d
```
注意:`-v` 会删除 `mysql_data` 卷,请确认无重要数据。
## 字符集
`docker-compose.yml` 中 MySQL 已配置 `utf8mb4`,导入脚本建议同为 UTF-8。