diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/PlatformLibController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/PlatformLibController.java index f69aa6d..5354071 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/PlatformLibController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/PlatformLibController.java @@ -1,17 +1,11 @@ package com.ruoyi.web.controller; +import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; @@ -20,6 +14,9 @@ import com.ruoyi.system.domain.PlatformLib; import com.ruoyi.system.service.IPlatformLibService; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.config.RuoYiConfig; +import org.springframework.web.multipart.MultipartFile; /** * 平台模版库Controller @@ -74,9 +71,18 @@ public class PlatformLibController extends BaseController */ @PreAuthorize("@ss.hasPermi('system:lib:add')") @Log(title = "平台模版库", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody PlatformLib platformLib) + @PostMapping("/add") + public AjaxResult add(PlatformLib platformLib, @RequestParam("file") MultipartFile file) throws IOException { + // 判断前端是否有文件传过来 + if (file != null && !file.isEmpty()) + { + String fileName = FileUploadUtils.upload(RuoYiConfig.getProfile(), file); + // 把这个路径存入实体类的 iconUrl 属性,对应数据库 icon_url 字段 + platformLib.setIconUrl(fileName); + } + + // 执行原有的插入逻辑 return toAjax(platformLibService.insertPlatformLib(platformLib)); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoutesController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoutesController.java index 15ee0d2..18a57c5 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoutesController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoutesController.java @@ -77,7 +77,12 @@ public class RoutesController extends BaseController @PostMapping public AjaxResult add(@RequestBody Routes routes) { - return toAjax(routesService.insertRoutes(routes)); + // 1. 执行插入,MyBatis 会通过 useGeneratedKeys="true" 自动将新 ID 注入 routes 对象 + int rows = routesService.insertRoutes(routes); + + // 2. 不要用 toAjax,直接返回 success 并带上 routes 对象 + // 这样前端 response.data 就会包含这个带有 ID 的完整对象 + return rows > 0 ? AjaxResult.success(routes) : AjaxResult.error("新增航线失败"); } /** diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml index c40f2aa..037db5c 100644 --- a/ruoyi-admin/src/main/resources/application-druid.yml +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -8,7 +8,7 @@ spring: master: url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root - password: A20040303ctw! + password: 123456 # 从库数据源 slave: # 从数据源开关/默认关闭 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java index cc1b6f4..88d3615 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java @@ -172,7 +172,9 @@ public class FileUploadUtils { int dirLastIndex = RuoYiConfig.getProfile().length() + 1; String currentDir = StringUtils.substring(uploadDir, dirLastIndex); - return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + String path = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + + return path.replaceAll("/+", "/"); } /** diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index 511842b..d5f704e 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -23,19 +23,18 @@ import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; /** * spring security配置 - * + * * @author ruoyi */ @EnableMethodSecurity(prePostEnabled = true, securedEnabled = true) @Configuration -public class SecurityConfig -{ +public class SecurityConfig { /** * 自定义用户认证逻辑 */ @Autowired private UserDetailsService userDetailsService; - + /** * 认证失败处理类 */ @@ -53,7 +52,7 @@ public class SecurityConfig */ @Autowired private JwtAuthenticationTokenFilter authenticationTokenFilter; - + /** * 跨域过滤器 */ @@ -70,8 +69,7 @@ public class SecurityConfig * 身份验证实现 */ @Bean - public AuthenticationManager authenticationManager() - { + public AuthenticationManager authenticationManager() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService); daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); @@ -94,46 +92,45 @@ public class SecurityConfig * authenticated | 用户登录后可访问 */ @Bean - protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception - { + protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { return httpSecurity - // CSRF禁用,因为不使用session - .csrf(csrf -> csrf.disable()) - // 禁用HTTP响应标头 - .headers((headersCustomizer) -> { - headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin()); - }) - // 认证失败处理类 - .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler)) - // 基于token,所以不需要session - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - // 注解标记允许匿名访问的url - .authorizeHttpRequests((requests) -> { - permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll()); - // 对于登录login 注册register 验证码captchaImage 允许匿名访问 - requests.antMatchers("/login", "/register", "/captchaImage").permitAll() - // 静态资源,可匿名访问 - .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() - .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() - // 除上面外的所有请求全部需要鉴权认证 - .anyRequest().authenticated(); - }) - // 添加Logout filter - .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler)) - // 添加JWT filter - .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class) - // 添加CORS filter - .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class) - .addFilterBefore(corsFilter, LogoutFilter.class) - .build(); + // CSRF禁用,因为不使用session + .csrf(csrf -> csrf.disable()) + // 禁用HTTP响应标头 + .headers((headersCustomizer) -> { + headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin()); + }) + // 认证失败处理类 + .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler)) + // 基于token,所以不需要session + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + // 注解标记允许匿名访问的url + .authorizeHttpRequests((requests) -> { + permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll()); + // 对于登录login 注册register 验证码captchaImage 允许匿名访问 + requests.antMatchers("/login", "/register", "/captchaImage").permitAll() + // 静态资源,可匿名访问 + .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() + .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() + .antMatchers("/profile/**").permitAll() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated(); + }) + // 添加Logout filter + .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler)) + // 添加JWT filter + .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class) + // 添加CORS filter + .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class) + .addFilterBefore(corsFilter, LogoutFilter.class) + .build(); } /** * 强散列哈希加密实现 */ @Bean - public BCryptPasswordEncoder bCryptPasswordEncoder() - { + public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/PlatformLib.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PlatformLib.java index 902ebd5..b0d1087 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/PlatformLib.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PlatformLib.java @@ -7,76 +7,88 @@ import com.ruoyi.common.core.domain.BaseEntity; /** * 平台模版库对象 platform_lib - * + * * @author ruoyi * @date 2026-01-14 */ -public class PlatformLib extends BaseEntity -{ +public class PlatformLib extends BaseEntity { private static final long serialVersionUID = 1L; - /** 平台库ID */ + /** + * 平台库ID + */ private Long id; - /** 平台名称 (如: F-22 猛禽) */ + /** + * 平台名称 (如: F-22 猛禽) + */ @Excel(name = "平台名称 (如: F-22 猛禽)") private String name; - /** 类型: Aircraft, Vehicle, Radar, Ship */ - @Excel(name = "类型: Aircraft, Vehicle, Radar, Ship") + /** + * 类型: Aircraft, Vehicle, Radar, Ship + */ + @Excel(name = "类型: Air, Sea, Ground") private String type; - /** 核心参数JSON: {icon_url, max_speed, max_fuel, radar_range...} */ + /** + * 核心参数JSON: {icon_url, max_speed, max_fuel, radar_range...} + */ @Excel(name = "核心参数JSON: {icon_url, max_speed, max_fuel, radar_range...}") private String specsJson; - public void setId(Long id) - { + @Excel(name = "平台图标路径") + private String iconUrl; + + public void setId(Long id) { this.id = id; } - public Long getId() - { + public Long getId() { return id; } - public void setName(String name) - { + public void setName(String name) { this.name = name; } - public String getName() - { + public String getName() { return name; } - public void setType(String type) - { + public void setType(String type) { this.type = type; } - public String getType() - { + public String getType() { return type; } - public void setSpecsJson(String specsJson) - { + public void setSpecsJson(String specsJson) { this.specsJson = specsJson; } - public String getSpecsJson() - { + public String getSpecsJson() { return specsJson; } + public void setIconUrl(String iconUrl) { + this.iconUrl = iconUrl; + } + + public String getIconUrl() { + return iconUrl; + } + + @Override public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("id", getId()) - .append("name", getName()) - .append("type", getType()) - .append("specsJson", getSpecsJson()) - .toString(); + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("type", getType()) + .append("specsJson", getSpecsJson()) + .append("iconUrl", getIconUrl()) + .toString(); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/RouteWaypoints.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/RouteWaypoints.java index f8349fc..45bc77e 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/RouteWaypoints.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/RouteWaypoints.java @@ -41,11 +41,11 @@ public class RouteWaypoints extends BaseEntity /** 高度 (米) */ @Excel(name = "高度 (米)") - private Long alt; + private Double alt; /** 速度 (km/h) */ @Excel(name = "速度 (km/h)") - private Long speed; + private Double speed; /** 起始时间 (如: K+00:40:00) */ @Excel(name = "起始时间 (如: K+00:40:00)") @@ -53,7 +53,7 @@ public class RouteWaypoints extends BaseEntity /** 转弯角度 (用于计算转弯半径) */ @Excel(name = "转弯角度 (用于计算转弯半径)") - private Long turnAngle; + private Double turnAngle; public void setId(Long id) { @@ -115,22 +115,22 @@ public class RouteWaypoints extends BaseEntity return lng; } - public void setAlt(Long alt) + public void setAlt(Double alt) { this.alt = alt; } - public Long getAlt() + public Double getAlt() { return alt; } - public void setSpeed(Long speed) + public void setSpeed(Double speed) { this.speed = speed; } - public Long getSpeed() + public Double getSpeed() { return speed; } @@ -145,12 +145,12 @@ public class RouteWaypoints extends BaseEntity return startTime; } - public void setTurnAngle(Long turnAngle) + public void setTurnAngle(Double turnAngle) { this.turnAngle = turnAngle; } - public Long getTurnAngle() + public Double getTurnAngle() { return turnAngle; } @@ -183,7 +183,7 @@ public class RouteWaypoints extends BaseEntity // 单位换算:速度从 km/h 转为 m/s double v_mps = this.speed / 3.6; // 单位换算:角度从 度(Degree) 转为 弧度(Radians) - double radians = Math.toRadians(this.turnAngle.doubleValue()); + double radians = Math.toRadians(this.turnAngle); // 重力加速度 g double g = 9.8; // 计算半径 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RouteWaypointsMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RouteWaypointsMapper.java index 2e77e10..07ff430 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RouteWaypointsMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RouteWaypointsMapper.java @@ -55,6 +55,14 @@ public interface RouteWaypointsMapper public int deleteRouteWaypointsById(Long id); /** + * 删除航线具体航点明细 + * + * @param routeId 航线主键 + * @return 结果 + */ + public int deleteRouteWaypointsByRouteId(Long routeId); + + /** * 批量删除航线具体航点明细 * * @param ids 需要删除的数据主键集合 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IRouteWaypointsService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IRouteWaypointsService.java index fc046e8..3e74e8d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/IRouteWaypointsService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IRouteWaypointsService.java @@ -58,4 +58,12 @@ public interface IRouteWaypointsService * @return 结果 */ public int deleteRouteWaypointsById(Long id); + + /** + * 删除航线具体航点明细信息 + * + * @param routeId 航线具体航点明细主键 + * @return 结果 + */ + public int deleteRouteWaypointsByRouteId(Long routeId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MissionScenarioServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MissionScenarioServiceImpl.java index 600effa..ed72252 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MissionScenarioServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MissionScenarioServiceImpl.java @@ -1,11 +1,15 @@ package com.ruoyi.system.service.impl; import java.util.List; + +import com.ruoyi.system.domain.Routes; +import com.ruoyi.system.service.IRoutesService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.system.mapper.MissionScenarioMapper; import com.ruoyi.system.domain.MissionScenario; import com.ruoyi.system.service.IMissionScenarioService; +import org.springframework.transaction.annotation.Transactional; /** * 任务方案/沙箱Service业务层处理 @@ -19,6 +23,9 @@ public class MissionScenarioServiceImpl implements IMissionScenarioService @Autowired private MissionScenarioMapper missionScenarioMapper; + @Autowired + private IRoutesService routesService; + /** * 查询任务方案/沙箱 * @@ -74,9 +81,15 @@ public class MissionScenarioServiceImpl implements IMissionScenarioService * @return 结果 */ @Override + @Transactional public int deleteMissionScenarioByIds(Long[] ids) { - return missionScenarioMapper.deleteMissionScenarioByIds(ids); + int rows = 0; + for (Long id : ids) { + // 循环调用单条删除逻辑,确保每套方案下的从属数据都被清理干净 + rows += this.deleteMissionScenarioById(id); + } + return rows; } /** @@ -86,8 +99,19 @@ public class MissionScenarioServiceImpl implements IMissionScenarioService * @return 结果 */ @Override + @Transactional public int deleteMissionScenarioById(Long id) { + // 查找属于该方案的所有航线 + Routes queryRoute = new Routes(); + queryRoute.setScenarioId(id); + List relatedRoutes = routesService.selectRoutesList(queryRoute); + // 循环删除每一条航线 + if (relatedRoutes != null) { + for (Routes route : relatedRoutes) { + routesService.deleteRoutesById(route.getId()); + } + } return missionScenarioMapper.deleteMissionScenarioById(id); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RouteWaypointsServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RouteWaypointsServiceImpl.java index fbc0848..63be94c 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RouteWaypointsServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RouteWaypointsServiceImpl.java @@ -101,4 +101,9 @@ public class RouteWaypointsServiceImpl implements IRouteWaypointsService { return routeWaypointsMapper.deleteRouteWaypointsById(id); } + + @Override + public int deleteRouteWaypointsByRouteId(Long routeId) { + return routeWaypointsMapper.deleteRouteWaypointsByRouteId(routeId); + } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoutesServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoutesServiceImpl.java index 93b1ded..cf781a4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoutesServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoutesServiceImpl.java @@ -35,7 +35,18 @@ public class RoutesServiceImpl implements IRoutesService @Override public Routes selectRoutesById(Long id) { - return routesMapper.selectRoutesById(id); + // 查出航线基本信息 + Routes routes = routesMapper.selectRoutesById(id); + // 如果查到了航线,就再去查属于它的航点 + if (routes != null) { + RouteWaypoints queryWp = new RouteWaypoints(); + queryWp.setRouteId(id); // 根据航线ID查询 + List wpList = routeWaypointsService.selectRouteWaypointsList(queryWp); + + // 把查出来的航点列表塞进 routes 对象的 waypoints 属性里 + routes.setWaypoints(wpList); + } + return routes; } /** @@ -47,7 +58,16 @@ public class RoutesServiceImpl implements IRoutesService @Override public List selectRoutesList(Routes routes) { - return routesMapper.selectRoutesList(routes); + // 获取基础列表 + List list = routesMapper.selectRoutesList(routes); + // 遍历列表,为每一条航线补全它的航点信息 + for (Routes r : list) { + RouteWaypoints queryWp = new RouteWaypoints(); + queryWp.setRouteId(r.getId()); + List wpList = routeWaypointsService.selectRouteWaypointsList(queryWp); + r.setWaypoints(wpList); + } + return list; } /** @@ -98,9 +118,17 @@ public class RoutesServiceImpl implements IRoutesService * @return 结果 */ @Override + @Transactional public int deleteRoutesByIds(Long[] ids) { - return routesMapper.deleteRoutesByIds(ids); + int rows = 0; + for (Long id : ids) { + // 1. 清理航点 + routeWaypointsService.deleteRouteWaypointsByRouteId(id); + // 2. 累加删除航线的行数 + rows += routesMapper.deleteRoutesById(id); + } + return rows; } /** @@ -110,8 +138,10 @@ public class RoutesServiceImpl implements IRoutesService * @return 结果 */ @Override + @Transactional public int deleteRoutesById(Long id) { + routeWaypointsService.deleteRouteWaypointsByRouteId(id); return routesMapper.deleteRoutesById(id); } } diff --git a/ruoyi-system/src/main/resources/mapper/system/PlatformLibMapper.xml b/ruoyi-system/src/main/resources/mapper/system/PlatformLibMapper.xml index b72202a..7161fdc 100644 --- a/ruoyi-system/src/main/resources/mapper/system/PlatformLibMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/PlatformLibMapper.xml @@ -9,10 +9,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + - select id, name, type, specs_json from platform_lib + select id, name, type, specs_json,icon_url from platform_lib @@ -35,11 +37,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" name, type, specs_json, + icon_url, #{name}, #{type}, #{specsJson}, + #{iconUrl}, @@ -49,6 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" name = #{name}, type = #{type}, specs_json = #{specsJson}, + icon_url = #{iconUrl}, where id = #{id} diff --git a/ruoyi-system/src/main/resources/mapper/system/RouteWaypointsMapper.xml b/ruoyi-system/src/main/resources/mapper/system/RouteWaypointsMapper.xml index f6209fb..7ccc118 100644 --- a/ruoyi-system/src/main/resources/mapper/system/RouteWaypointsMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/RouteWaypointsMapper.xml @@ -91,6 +91,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" delete from route_waypoints where id = #{id} + + delete from route_waypoints where route_id = #{routeId} + + delete from route_waypoints where id in diff --git a/ruoyi-system/src/main/resources/mapper/system/RoutesMapper.xml b/ruoyi-system/src/main/resources/mapper/system/RoutesMapper.xml index e51edf9..2a99e7f 100644 --- a/ruoyi-system/src/main/resources/mapper/system/RoutesMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/RoutesMapper.xml @@ -10,6 +10,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + diff --git a/ruoyi-ui/.env.development b/ruoyi-ui/.env.development index 09f4bb3..ebae234 100644 --- a/ruoyi-ui/.env.development +++ b/ruoyi-ui/.env.development @@ -7,5 +7,8 @@ ENV = 'development' # 若依管理系统/开发环境 VUE_APP_BASE_API = '/dev-api' +# 访问地址(绕过 /dev-api 代理,用于解决静态资源/图片访问 401 认证问题) +VUE_APP_BACKEND_URL = 'http://192.168.50.145:8080' + # 路由懒加载 VUE_CLI_BABEL_TRANSPILE_MODULES = true diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 9f0562f..4aa7fcd 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -6,6 +6,7 @@ "license": "MIT", "scripts": { "dev": "vue-cli-service serve", + "move-tiles": "node scripts/move-tiles-out-of-public.js", "build:prod": "vue-cli-service build", "build:stage": "vue-cli-service build --mode staging", "preview": "node build/index.js --preview" @@ -61,6 +62,7 @@ "chalk": "4.1.0", "compression-webpack-plugin": "6.1.2", "connect": "3.6.6", + "express": "^4.18.2", "sass": "1.32.13", "sass-loader": "10.1.1", "script-ext-html-webpack-plugin": "2.1.5", diff --git a/ruoyi-ui/src/api/system/lib.js b/ruoyi-ui/src/api/system/lib.js index 89f6aa5..59420c5 100644 --- a/ruoyi-ui/src/api/system/lib.js +++ b/ruoyi-ui/src/api/system/lib.js @@ -20,9 +20,12 @@ export function getLib(id) { // 新增平台模版库 export function addLib(data) { return request({ - url: '/system/lib', + url: '/system/lib/add', method: 'post', - data: data + data: data, + headers: { + 'Content-Type': 'multipart/form-data' + } }) } diff --git a/ruoyi-ui/src/store/getters.js b/ruoyi-ui/src/store/getters.js index 3680f95..a3906cf 100644 --- a/ruoyi-ui/src/store/getters.js +++ b/ruoyi-ui/src/store/getters.js @@ -13,6 +13,7 @@ const getters = { introduction: state => state.user.introduction, roles: state => state.user.roles, permissions: state => state.user.permissions, + userLevel: state => state.user.userLevel, permission_routes: state => state.permission.routes, topbarRouters: state => state.permission.topbarRouters, defaultRoutes: state => state.permission.defaultRoutes, diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 6a7b710..5ea90a2 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -13,7 +13,8 @@ const user = { nickName: '', avatar: '', roles: [], - permissions: [] + permissions: [], + userLevel: '' }, mutations: { @@ -37,6 +38,9 @@ const user = { }, SET_PERMISSIONS: (state, permissions) => { state.permissions = permissions + }, + SET_USER_LEVEL: (state, userLevel) => { + state.userLevel = userLevel } }, @@ -77,6 +81,7 @@ const user = { commit('SET_NAME', user.userName) commit('SET_NICK_NAME', user.nickName) commit('SET_AVATAR', avatar) + commit('SET_USER_LEVEL', user.userLevel || '') /* 初始密码提示 */ if(res.isDefaultModifyPwd) { MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { diff --git a/ruoyi-ui/src/views/cesiumMap/DrawingToolbar.vue b/ruoyi-ui/src/views/cesiumMap/DrawingToolbar.vue index 9acf607..de6a0f0 100644 --- a/ruoyi-ui/src/views/cesiumMap/DrawingToolbar.vue +++ b/ruoyi-ui/src/views/cesiumMap/DrawingToolbar.vue @@ -30,23 +30,47 @@ export default { hasEntities: { type: Boolean, default: false + }, + toolMode: { + type: String, + default: 'airspace' // 'airspace' or 'ranging' } }, data() { return { - toolbarItems: [ - { id: 'point', name: '点', icon: 'el-icon-location' }, - { id: 'line', name: '线', icon: 'el-icon-edit-outline' }, - { id: 'polygon', name: '面', icon: 'el-icon-s-grid' }, - { id: 'rectangle', name: '矩形', icon: 'el-icon-s-data' }, + // 完整工具列表(空域模式,移除点和线) + allToolbarItems: [ + { id: 'mouse', name: '鼠标', icon: 'el-icon-position' }, + { id: 'polygon', name: '面', icon: 'el-icon-house' }, + { id: 'rectangle', name: '矩形', icon: 'el-icon-crop' }, { id: 'circle', name: '圆形', icon: 'el-icon-circle-plus-outline' }, + { id: 'sector', name: '扇形', icon: 'el-icon-pie-chart' }, + { id: 'arrow', name: '箭头', icon: 'el-icon-right' }, + { id: 'text', name: '文本', icon: 'el-icon-document' }, + { id: 'image', name: '图片', icon: 'el-icon-picture-outline' }, { id: 'locate', name: '定位', icon: 'el-icon-aim' }, { id: 'clear', name: '清除', icon: 'el-icon-delete' }, { id: 'import', name: '导入', icon: 'el-icon-upload' }, { id: 'export', name: '导出', icon: 'el-icon-download' } + ], + // 测距模式工具列表 + rangingToolbarItems: [ + { id: 'mouse', name: '鼠标', icon: 'el-icon-position' }, + { id: 'point', name: '点', icon: 'el-icon-location' }, + { id: 'line', name: '线', icon: 'el-icon-edit-outline' }, + { id: 'clear', name: '清除', icon: 'el-icon-delete' } ] } }, + computed: { + toolbarItems() { + if (this.toolMode === 'ranging') { + return this.rangingToolbarItems; + } else { + return this.allToolbarItems; + } + } + }, methods: { handleItemClick(item) { if (item.id === 'clear') { @@ -57,6 +81,8 @@ export default { this.$emit('import-data') } else if (item.id === 'locate') { this.$emit('locate') + } else if (item.id === 'mouse') { + this.$emit('toggle-drawing', null) } else { this.$emit('toggle-drawing', item.id) } diff --git a/ruoyi-ui/src/views/cesiumMap/index.vue b/ruoyi-ui/src/views/cesiumMap/index.vue index a068ed9..47a57ae 100644 --- a/ruoyi-ui/src/views/cesiumMap/index.vue +++ b/ruoyi-ui/src/views/cesiumMap/index.vue @@ -6,26 +6,60 @@ :draw-dom-click="drawDomClick" :drawing-mode="drawingMode" :has-entities="allEntities.length > 0" + :tool-mode="toolMode" @toggle-drawing="toggleDrawing" @clear-all="clearAll" @export-data="exportData" @import-data="importData" @locate="handleLocate" /> - + + + +
+
+ {{ scaleBarText }} +
+ + +
+
+
+ {{ coordinatesText }} +
+
- \ No newline at end of file + diff --git a/ruoyi-ui/src/views/dialogs/PlatformImportDialog.vue b/ruoyi-ui/src/views/dialogs/PlatformImportDialog.vue new file mode 100644 index 0000000..0efc954 --- /dev/null +++ b/ruoyi-ui/src/views/dialogs/PlatformImportDialog.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/ruoyi-ui/src/views/dialogs/WaypointEditDialog.vue b/ruoyi-ui/src/views/dialogs/WaypointEditDialog.vue index 57e05d4..6bb0006 100644 --- a/ruoyi-ui/src/views/dialogs/WaypointEditDialog.vue +++ b/ruoyi-ui/src/views/dialogs/WaypointEditDialog.vue @@ -14,9 +14,9 @@ - + - + +
+ ⚠️ 首尾航点坡度已锁定为 0,不可编辑 +
@@ -78,7 +82,6 @@ export default { } }, data() { - // 定义一个通用的数字校验函数,允许 0 const validateNumber = (rule, value, callback) => { // 检查 value 是否为 undefined, null 或 空字符串 // 注意:这里不能简单用 !value,因为 !0 是 true @@ -92,16 +95,19 @@ export default { return { formData: { name: '', - altitude: 0, - speed: 0, - turnBank: 0, - startTime: '' + alt: 5000, + speed: 800, + turnAngle: 0, + startTime: '', + currentIndex: -1, + totalPoints: 0, + isBankDisabled: false }, rules: { name: [ { required: true, message: '请输入航点名称', trigger: 'blur' } ], - altitude: [ + alt: [ // 使用自定义 validator 替代 type: 'number' 组合,确保 0 被接受 { required: true, validator: validateNumber, message: '请输入有效高度', trigger: ['blur', 'change'] } ], @@ -109,7 +115,7 @@ export default { // 重点修改:使用自定义 validator,允许速度为 0 { required: true, validator: validateNumber, message: '请输入有效速度', trigger: ['blur', 'change'] } ], - turnBank: [ + turnAngle: [ // 同样应用到转弯坡度 { required: true, validator: validateNumber, message: '请输入有效转弯坡度', trigger: ['blur', 'change'] } ], @@ -133,17 +139,21 @@ export default { }, methods: { initFormData() { - // 保持数据类型正确,确保是 Number 类型 + const index = this.waypoint.currentIndex !== undefined ? this.waypoint.currentIndex : -1; + const total = this.waypoint.totalPoints || 0; + const locked = (index === 0) || (total > 0 && index === total - 1); + this.formData = { name: this.waypoint.name || '', - // 确保初始化时也是数字类型 - altitude: this.waypoint.altitude !== undefined && this.waypoint.altitude !== null ? Number(this.waypoint.altitude) : 0, + alt: this.waypoint.alt !== undefined && this.waypoint.alt !== null ? Number(this.waypoint.alt) : 0, speed: this.waypoint.speed !== undefined && this.waypoint.speed !== null ? Number(this.waypoint.speed) : 0, - turnBank: this.waypoint.turnBank !== undefined && this.waypoint.turnBank !== null ? Number(this.waypoint.turnBank) : 0, - startTime: this.waypoint.startTime || '' + startTime: this.waypoint.startTime || '', + currentIndex: index, + totalPoints: total, + isBankDisabled: locked, + turnAngle: locked ? 0 : (Number(this.waypoint.turnAngle) || 0) }; - // 弹窗打开时,尝试清除之前的校验痕迹 this.$nextTick(() => { if (this.$refs.formRef) { this.$refs.formRef.clearValidate(); diff --git a/ruoyi-ui/src/views/selectRoom/index.vue b/ruoyi-ui/src/views/selectRoom/index.vue index 0f4daef..6740b94 100644 --- a/ruoyi-ui/src/views/selectRoom/index.vue +++ b/ruoyi-ui/src/views/selectRoom/index.vue @@ -46,7 +46,6 @@ -
-

暂无房间

点击下方按钮创建您的第一个房间

-
- -
删除房间
-