军标库

This commit is contained in:
ZZX9599
2025-09-23 16:45:42 +08:00
parent 521efbafac
commit 8479d174be
33 changed files with 373 additions and 506 deletions

View File

@ -1,5 +1,6 @@
package com.yj.earth.business.controller;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.auth.AuthInfo;
import com.yj.earth.auth.AuthValidator;
import com.yj.earth.common.util.ApiResponse;

View File

@ -20,6 +20,7 @@ import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.drew.metadata.MetadataException;
import com.drew.metadata.exif.GpsDirectory;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.business.domain.FileInfo;
import com.yj.earth.business.service.FileInfoService;
import com.yj.earth.common.util.ApiResponse;
@ -44,6 +45,7 @@ import java.util.HashMap;
import java.util.Map;
@Tag(name = "文件数据管理")
@CheckAuth
@RestController
@RequestMapping("/fileInfo")
public class FileInfoController {

View File

@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
@Data
@Slf4j
@Tag(name = "路径规划管理")
@CheckAuth
@RestController
@RequestMapping("/graphhopper")
public class GraphHopperController {

View File

@ -1,6 +1,7 @@
package com.yj.earth.business.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.business.domain.Role;
import com.yj.earth.business.service.RoleService;
import com.yj.earth.common.util.ApiResponse;
@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Tag(name = "角色数据管理")
@CheckAuth
@RestController
@RequestMapping("/role")
public class RoleController {

View File

@ -1,6 +1,7 @@
package com.yj.earth.business.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.business.domain.RoleSource;
import com.yj.earth.business.service.RoleService;
import com.yj.earth.business.service.RoleSourceService;
@ -21,6 +22,7 @@ import java.util.List;
import java.util.stream.Collectors;
@Tag(name = "角色资源管理")
@CheckAuth
@RestController
@RequestMapping("/roleSource")
public class RoleSourceController {

View File

@ -4,6 +4,7 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.business.domain.Source;
import com.yj.earth.business.service.*;
import com.yj.earth.common.service.SourceDataGenerator;
@ -30,6 +31,7 @@ import static com.yj.earth.common.constant.GlobalConstant.SHOW;
@Slf4j
@Tag(name = "树形结构管理")
@CheckAuth
@RestController
@RequestMapping("/source")
public class SourceController {

View File

@ -1,436 +0,0 @@
package com.yj.earth.business.controller;
import com.yj.earth.common.util.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Tag(name = "战斗计算相关")
@RestController
@RequestMapping("/api/tactical")
public class TacticalCalculationController {
// 日期时间格式化器
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@PostMapping("/meet")
@Operation(summary = "计算相遇结果")
public ApiResponse calculateMeet(@Valid @RequestBody MeetInputDTO input) {
MeetResultDTO result = new MeetResultDTO();
// 计算相遇时间(小时)
double meetTimeHours;
if (input.isSameDirection()) {
// 同向而行:时间 = 距离 / (速度差)
double speedDiff = Math.abs(input.getSpeed1() - input.getSpeed2());
if (speedDiff <= 0) {
throw new IllegalArgumentException("同向而行时、速度不能相等或后方速度小于前方");
}
meetTimeHours = input.getInitialDistance() / speedDiff;
} else {
// 相向而行:时间 = 距离 / (速度和)
meetTimeHours = input.getInitialDistance() / (input.getSpeed1() + input.getSpeed2());
}
// 格式化时间结果
result.setMeetTime(formatDuration(Duration.ofHours((long) meetTimeHours)
.plusMinutes((long) ((meetTimeHours % 1) * 60))));
// 计算相遇点距离
result.setMeetDistanceFrom1(input.getSpeed1() * meetTimeHours);
result.setMeetDistanceFrom2(input.getSpeed2() * meetTimeHours);
return ApiResponse.success(result);
}
@PostMapping("/pursuit")
@Operation(summary = "计算追击结果")
public ApiResponse calculatePursuit(@Valid @RequestBody PursuitInputDTO input) {
PursuitResultDTO result = new PursuitResultDTO();
// 检查速度合理性
if (input.getPursuerSpeed() <= input.getTargetSpeed()) {
throw new IllegalArgumentException("追击速度必须大于目标速度");
}
// 计算追击时间(小时)
double pursuitTimeHours = input.getDistance() / (input.getPursuerSpeed() - input.getTargetSpeed());
result.setPursuitTime(formatDuration(Duration.ofHours((long) pursuitTimeHours)
.plusMinutes((long) ((pursuitTimeHours % 1) * 60))));
// 计算追击距离
result.setPursuitDistance(input.getPursuerSpeed() * pursuitTimeHours);
return ApiResponse.success(result);
}
@PostMapping("/formation/person")
@Operation(summary = "计算人员队列长度")
public ApiResponse calculatePersonFormation(@Valid @RequestBody PersonFormationInputDTO input) {
FormationLengthResultDTO result = new FormationLengthResultDTO();
// 人员队列长度 = (人数 - 1) * 间距
if (input.getPersonCount() <= 1) {
result.setTotalLength(0.0);
} else {
result.setTotalLength((input.getPersonCount() - 1) * input.getDistanceBetween());
}
return ApiResponse.success(result);
}
@PostMapping("/formation/vehicle")
@Operation(summary = "计算车辆队列长度")
public ApiResponse calculateVehicleFormation(@Valid @RequestBody VehicleFormationInputDTO input) {
FormationLengthResultDTO result = new FormationLengthResultDTO();
// 车辆队列长度 = (单辆车长 * 数量) + (间距 * (数量 - 1))
if (input.getVehicleCount() <= 0) {
result.setTotalLength(0.0);
} else if (input.getVehicleCount() == 1) {
result.setTotalLength(input.getVehicleLength());
} else {
result.setTotalLength((input.getVehicleLength() * input.getVehicleCount()) +
(input.getDistanceBetween() * (input.getVehicleCount() - 1)));
}
return ApiResponse.success(result);
}
@PostMapping("/formation/gun")
@Operation(summary = "计算火炮队列长度")
public ApiResponse calculateGunFormation(@Valid @RequestBody GunFormationInputDTO input) {
FormationLengthResultDTO result = new FormationLengthResultDTO();
// 火炮本身长度
double gunTotalLength = input.getGunLength() * input.getGunCount();
// 牵引车辆长度
double vehicleTotalLength = input.getVehicleLength() * input.getVehicleCount();
// 车辆间距
double vehicleDistance = input.getVehicleDistance() * (input.getVehicleCount() - 1);
// 总长度
result.setTotalLength(gunTotalLength + vehicleTotalLength + vehicleDistance);
return ApiResponse.success(result);
}
@PostMapping("/march/time")
@Operation(summary = "计算行军时间")
public ApiResponse calculateMarchTime(@Valid @RequestBody MarchTimeInputDTO input) {
MarchTimeResultDTO result = new MarchTimeResultDTO();
// 总行军距离 = 行军距离 + 部队长度(需要完全通过)
double totalDistance = input.getMarchDistance() + input.getFormationLength();
// 行军时间(小时)= 总距离 / 速度 + 等待时间
double marchTimeHours = (totalDistance / input.getSpeed()) + input.getWaitHours();
// 格式化行军时间
result.setTotalMarchTime(formatDuration(Duration.ofHours((long) marchTimeHours)
.plusMinutes((long) ((marchTimeHours % 1) * 60))));
// 计算出发时间(如果提供了要求抵达时间)
if (input.getRequiredArriveTime() != null) {
long hours = (long) marchTimeHours;
long minutes = (long) ((marchTimeHours - hours) * 60);
LocalDateTime departTime = input.getRequiredArriveTime()
.minusHours(hours)
.minusMinutes(minutes);
result.setDepartureTime(departTime.format(DATE_TIME_FORMATTER));
}
return ApiResponse.success(result);
}
@PostMapping("/material/consumption")
@Operation(summary = "计算物资消耗")
public ApiResponse calculateMaterialConsumption(@Valid @RequestBody MaterialConsumptionInputDTO input) {
MaterialConsumptionResultDTO result = new MaterialConsumptionResultDTO();
switch (input.getMaterialType()) {
case AMMUNITION:
// 弹药消耗 = 单位基数 * 装备数量 * 时间
result.setTotalConsumption(input.getBaseConsumption() * input.getEquipmentCount() * input.getHours());
break;
case OIL:
// 油料消耗 = 单位时间耗油量 * 装备数量 * 时间
result.setTotalConsumption(input.getBaseConsumption() * input.getEquipmentCount() * input.getHours());
break;
case WEAPON:
// 武器需求 = 总需求 / (单装备配备数)
result.setTotalConsumption(Math.ceil(input.getTotalRequirement() / input.getBaseConsumption()));
break;
}
return ApiResponse.success(result);
}
@PostMapping("/unit/formation")
@Operation(summary = "计算部队编成")
public ApiResponse calculateUnitFormation(@Valid @RequestBody UnitFormationInputDTO input) {
UnitFormationResultDTO result = new UnitFormationResultDTO();
// 计算编成数量
result.setFormationCount(Math.ceil(input.getTotalStrength() / input.getUnitStrength()));
// 计算最后一个编成的兵力
double lastFormationStrength = input.getTotalStrength() % input.getUnitStrength();
if (lastFormationStrength <= 0) {
lastFormationStrength = input.getUnitStrength();
}
result.setLastFormationStrength(lastFormationStrength);
return ApiResponse.success(result);
}
@PostMapping("/special/crossRiver")
@Operation(summary = "计算渡河时间")
public ApiResponse calculateCrossRiverTime(@Valid @RequestBody CrossRiverInputDTO input) {
SpecialTimeResultDTO result = new SpecialTimeResultDTO();
// 计算批次数量
double batchCount = Math.ceil(input.getPersonCount() / input.getBatchCapacity());
// 总时间 = 批次 * 单批次时间 + 准备时间
double totalHours = (batchCount * input.getBatchHours()) + input.getPrepareHours();
// 格式化结果
result.setTotalTime(formatDuration(Duration.ofHours((long) totalHours)
.plusMinutes((long) ((totalHours % 1) * 60))));
return ApiResponse.success(result);
}
@PostMapping("/loss/rate")
@Operation(summary = "计算损失率")
public ApiResponse calculateLossRate(@Valid @RequestBody LossRateInputDTO input) {
LossRateResultDTO result = new LossRateResultDTO();
if (input.getTotalStrength() <= 0) {
throw new IllegalArgumentException("总兵力必须大于0");
}
// 计算损失率
result.setLossRate((input.getLostStrength() / input.getTotalStrength()) * 100);
// 计算剩余兵力
result.setRemainingStrength(input.getTotalStrength() - input.getLostStrength());
return ApiResponse.success(result);
}
// 格式化Duration为"X天X时X分X秒"
private String formatDuration(Duration duration) {
long days = duration.toDays();
long hours = duration.toHours() % 24;
long minutes = duration.toMinutes() % 60;
long seconds = duration.getSeconds() % 60;
return String.format("%d天%d时%d分%d秒", days, hours, minutes, seconds);
}
// 解析时间字符串为Duration
private Duration parseTimeString(String timeStr) {
Pattern pattern = Pattern.compile("(?<d>\\d+)天(?<h>\\d+)时(?<m>\\d+)分(?<s>\\d+)秒");
Matcher matcher = pattern.matcher(timeStr);
if (matcher.matches()) {
int days = Integer.parseInt(matcher.group("d"));
int hours = Integer.parseInt(matcher.group("h"));
int minutes = Integer.parseInt(matcher.group("m"));
int seconds = Integer.parseInt(matcher.group("s"));
return Duration.ofDays(days)
.plusHours(hours)
.plusMinutes(minutes)
.plusSeconds(seconds);
}
return Duration.ZERO;
}
@Data
public static class MeetInputDTO {
@Schema(description = "初始距离")
private double initialDistance;
@Schema(description = "速度1")
private double speed1;
@Schema(description = "速度2")
private double speed2;
@Schema(description = "是否同向")
private boolean isSameDirection;
}
@Data
public static class MeetResultDTO {
@Schema(description = "相遇时间")
private String meetTime;
@Schema(description = "距离1的距离")
private double meetDistanceFrom1;
@Schema(description = "距离2的距离")
private double meetDistanceFrom2;
}
@Data
public static class PursuitInputDTO {
@Schema(description = "初始距离")
private double distance;
@Schema(description = "追击者速度")
private double pursuerSpeed;
@Schema(description = "目标速度")
private double targetSpeed;
}
@Data
public static class PursuitResultDTO {
@Schema(description = "追击时间")
private String pursuitTime;
@Schema(description = "追击距离")
private double pursuitDistance;
}
@Data
public static class PersonFormationInputDTO {
@Schema(description = "人数")
private int personCount;
@Schema(description = "人间距")
private double distanceBetween;
}
@Data
public static class VehicleFormationInputDTO {
@Schema(description = "车辆数量")
private int vehicleCount;
@Schema(description = "车辆长")
private double vehicleLength;
@Schema(description = "车辆距")
private double distanceBetween;
}
@Data
public static class GunFormationInputDTO {
@Schema(description = "火炮数量")
private int gunCount;
@Schema(description = "单门炮长")
private double gunLength;
@Schema(description = "牵引车辆数量")
private int vehicleCount;
@Schema(description = "单辆车长")
private double vehicleLength;
@Schema(description = "车距")
private double vehicleDistance;
}
@Data
public static class FormationLengthResultDTO {
@Schema(description = "总长度")
private double totalLength;
}
@Data
public static class MarchTimeInputDTO {
@Schema(description = "行军距离")
private double marchDistance;
@Schema(description = "部队长度")
private double formationLength;
@Schema(description = "速度")
private double speed;
@Schema(description = "等待时间(小时)")
private double waitHours;
@Schema(description = "要求抵达时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime requiredArriveTime;
}
@Data
public static class MarchTimeResultDTO {
@Schema(description = "总行军时间")
private String totalMarchTime;
@Schema(description = "出发时间")
private String departureTime;
}
@Data
public static class MaterialConsumptionInputDTO {
@Schema(description = "物资类型")
private MaterialType materialType;
@Schema(description = "单位消耗/配备数")
private double baseConsumption;
@Schema(description = "装备数量")
private int equipmentCount;
@Schema(description = "时间(小时)")
private double hours;
@Schema(description = "总需求")
private double totalRequirement;
public enum MaterialType {
AMMUNITION, OIL, WEAPON
}
}
@Data
public static class MaterialConsumptionResultDTO {
@Schema(description = "总消耗量/需求量")
private double totalConsumption;
}
@Data
public static class UnitFormationInputDTO {
@Schema(description = "总兵力")
private double totalStrength;
@Schema(description = "单位兵力")
private double unitStrength;
}
@Data
public static class UnitFormationResultDTO {
@Schema(description = "编成数量")
private double formationCount;
@Schema(description = "最后一个编成的兵力")
private double lastFormationStrength;
}
@Data
public static class CrossRiverInputDTO {
@Schema(description = "总人数")
private int personCount;
@Schema(description = "单批次容量")
private int batchCapacity;
@Schema(description = "单批次时间(小时)")
private double batchHours;
@Schema(description = "准备时间(小时)")
private double prepareHours;
}
@Data
public static class SpecialTimeResultDTO {
@Schema(description = "总时间")
private String totalTime;
}
@Data
public static class LossRateInputDTO {
@Schema(description = "总兵力")
private double totalStrength;
@Schema(description = "损失兵力")
private double lostStrength;
}
@Data
public static class LossRateResultDTO {
@Schema(description = "损失率(百分比)")
private double lossRate;
@Schema(description = "剩余兵力")
private double remainingStrength;
}
}

View File

@ -5,6 +5,7 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.annotation.EncryptResponse;
import com.yj.earth.annotation.ExcludeField;
import com.yj.earth.annotation.RoleAccess;
@ -37,6 +38,7 @@ public class UserController {
@Resource
private RoleService roleService;
@CheckAuth
@Operation(summary = "新增用户")
@PostMapping("/add")
@RoleAccess(roleNames = "管理员")
@ -56,6 +58,7 @@ public class UserController {
return ApiResponse.success(null);
}
@CheckAuth
@Operation(summary = "删除用户")
@PostMapping("/delete")
@RoleAccess(roleNames = "管理员")
@ -64,6 +67,7 @@ public class UserController {
return ApiResponse.success(null);
}
@CheckAuth
@Operation(summary = "更新信息")
@PostMapping("/update")
public ApiResponse update(@RequestBody UpdateUserDto updateUserDto) {
@ -73,6 +77,7 @@ public class UserController {
return ApiResponse.success(null);
}
@CheckAuth
@Operation(summary = "更新密码")
@PostMapping("/updatePassword")
public ApiResponse updatePassword(@RequestBody UpdatePasswordDto updatePasswordDto) {
@ -88,12 +93,14 @@ public class UserController {
return ApiResponse.success(null);
}
@CheckAuth
@Operation(summary = "用户详情")
@GetMapping("/getById")
public ApiResponse get(@Parameter(description = "用户ID") String id) {
return ApiResponse.success(userService.getById(id));
}
@CheckAuth
@Operation(summary = "用户列表")
@GetMapping("/list")
@RoleAccess(roleNames = "管理员")
@ -102,6 +109,15 @@ public class UserController {
return ApiResponse.success(userPage);
}
@CheckAuth
@Operation(summary = "设置角色")
@PostMapping("/userBindOrUnBindRole")
@RoleAccess(roleNames = "管理员")
public ApiResponse userBindOrUnBindRole(@RequestBody UserBindOrUnBindRoleDto userBindOrUnBindRoleDto) {
userService.lambdaUpdate().set(User::getRoleId, userBindOrUnBindRoleDto.getRoleId()).eq(User::getId, userBindOrUnBindRoleDto.getUserId()).update();
return ApiResponse.success(null);
}
@Operation(summary = "用户登录")
@PostMapping("/login")
public ApiResponse login(@RequestBody UserLoginDto userLoginDto) {
@ -124,14 +140,6 @@ public class UserController {
return ApiResponse.success(null);
}
@Operation(summary = "设置角色")
@PostMapping("/userBindOrUnBindRole")
@RoleAccess(roleNames = "管理员")
public ApiResponse userBindOrUnBindRole(@RequestBody UserBindOrUnBindRoleDto userBindOrUnBindRoleDto) {
userService.lambdaUpdate().set(User::getRoleId, userBindOrUnBindRoleDto.getRoleId()).eq(User::getId, userBindOrUnBindRoleDto.getUserId()).update();
return ApiResponse.success(null);
}
@Operation(summary = "获取当前用户信息")
@GetMapping("/getCurrentUserInfo")
public ApiResponse getCurrentUserInfo() {