diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoomPlatformIconController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoomPlatformIconController.java index e0b97b4..bfbbbd4 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoomPlatformIconController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/RoomPlatformIconController.java @@ -9,6 +9,7 @@ import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.system.domain.RoomPlatformIcon; import com.ruoyi.system.service.IRoomPlatformIconService; @@ -26,16 +27,46 @@ public class RoomPlatformIconController extends BaseController { private RedisTemplate redisTemplate; /** - * 按房间ID查询该房间下所有地图平台图标(不分页) + * 查询房间地图平台图标列表(分页) */ @PreAuthorize("@ss.hasPermi('system:roomPlatformIcon:list')") @GetMapping("/list") - public AjaxResult list(@RequestParam Long roomId) { + public TableDataInfo list(RoomPlatformIcon roomPlatformIcon) { + // 兜底:若前端将未选择的筛选值传为 0,则按“未传入”处理,避免 where room_id=0 导致空表 + if (roomPlatformIcon != null) { + if (roomPlatformIcon.getRoomId() != null && roomPlatformIcon.getRoomId() <= 0) { + roomPlatformIcon.setRoomId(null); + } + if (roomPlatformIcon.getPlatformId() != null && roomPlatformIcon.getPlatformId() <= 0) { + roomPlatformIcon.setPlatformId(null); + } + } + startPage(); + List list = roomPlatformIconService.selectRoomPlatformIconList(roomPlatformIcon); + return getDataTable(list); + } + + /** + * 按房间ID查询该房间下所有地图平台图标(不分页,用于 Cesium 地图渲染) + */ + @PreAuthorize("@ss.hasPermi('system:roomPlatformIcon:list')") + @GetMapping("/listByRoomId") + public AjaxResult listByRoomId(@RequestParam Long roomId) { List list = roomPlatformIconService.selectListByRoomId(roomId); return success(list); } /** + * 查询房间地图平台图标详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:roomPlatformIcon:list')") + @GetMapping("/{id}") + public AjaxResult getInfo(@PathVariable Long id) { + RoomPlatformIcon icon = roomPlatformIconService.selectById(id); + return success(icon); + } + + /** * 新增 */ @PreAuthorize("@ss.hasPermi('system:roomPlatformIcon:add')") @@ -61,15 +92,22 @@ public class RoomPlatformIconController extends BaseController { */ @PreAuthorize("@ss.hasPermi('system:roomPlatformIcon:remove')") @Log(title = "房间地图平台图标", businessType = BusinessType.DELETE) - @DeleteMapping("/{id}") - public AjaxResult remove(@PathVariable Long id) { - RoomPlatformIcon icon = roomPlatformIconService.selectById(id); - if (icon != null && icon.getRoomId() != null) { - String key = "room:" + icon.getRoomId() + ":platformIcons:platforms"; - redisTemplate.opsForHash().delete(key, String.valueOf(id)); - String oldKey = "room:" + icon.getRoomId() + ":route:0:platforms"; - redisTemplate.opsForHash().delete(oldKey, String.valueOf(id)); + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) { + int rows = 0; + if (ids == null || ids.length == 0) return success(); + + for (Long id : ids) { + if (id == null) continue; + RoomPlatformIcon icon = roomPlatformIconService.selectById(id); + if (icon != null && icon.getRoomId() != null) { + String key = "room:" + icon.getRoomId() + ":platformIcons:platforms"; + redisTemplate.opsForHash().delete(key, String.valueOf(id)); + String oldKey = "room:" + icon.getRoomId() + ":route:0:platforms"; + redisTemplate.opsForHash().delete(oldKey, String.valueOf(id)); + } + rows += roomPlatformIconService.deleteById(id); } - return toAjax(roomPlatformIconService.deleteById(id)); + return toAjax(rows); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IRoomPlatformIconService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IRoomPlatformIconService.java index 9c7f7f8..3763c34 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/IRoomPlatformIconService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IRoomPlatformIconService.java @@ -10,6 +10,11 @@ public interface IRoomPlatformIconService { List selectListByRoomId(Long roomId); + /** + * 查询房间地图平台图标列表(支持按 roomId/platformId 过滤,由分页控制) + */ + List selectRoomPlatformIconList(RoomPlatformIcon roomPlatformIcon); + RoomPlatformIcon selectById(Long id); int insert(RoomPlatformIcon roomPlatformIcon); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoomPlatformIconServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoomPlatformIconServiceImpl.java index 4cfea80..d1d3d3f 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoomPlatformIconServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RoomPlatformIconServiceImpl.java @@ -25,6 +25,11 @@ public class RoomPlatformIconServiceImpl implements IRoomPlatformIconService { } @Override + public List selectRoomPlatformIconList(RoomPlatformIcon roomPlatformIcon) { + return roomPlatformIconMapper.selectRoomPlatformIconList(roomPlatformIcon); + } + + @Override public RoomPlatformIcon selectById(Long id) { return roomPlatformIconMapper.selectRoomPlatformIconById(id); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java index 16466c9..e4b939a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -462,6 +462,17 @@ public class SysMenuServiceImpl implements ISysMenuService { component = menu.getComponent(); } + // 兜底:二级菜单(menuType=C)若 component 为空,会导致前端无法加载页面(白屏且无任何请求) + // 按若依约定:system//index + else if (StringUtils.isEmpty(menu.getComponent()) + && menu.getParentId().intValue() != MENU_ROOT_ID + && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && StringUtils.isNotEmpty(menu.getPath()) + && !isInnerLink(menu) + && !isParentView(menu)) + { + component = "system/" + menu.getPath() + "/index"; + } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != MENU_ROOT_ID && isInnerLink(menu)) { component = UserConstants.INNER_LINK; diff --git a/ruoyi-ui/src/api/system/roomPlatformIcon.js b/ruoyi-ui/src/api/system/roomPlatformIcon.js index d160f78..7261924 100644 --- a/ruoyi-ui/src/api/system/roomPlatformIcon.js +++ b/ruoyi-ui/src/api/system/roomPlatformIcon.js @@ -3,12 +3,29 @@ import request from '@/utils/request' /** 按房间ID查询该房间下所有地图平台图标 */ export function listByRoomId(roomId) { return request({ - url: '/system/roomPlatformIcon/list', + url: '/system/roomPlatformIcon/listByRoomId', method: 'get', params: { roomId } }) } +/** 查询房间地图平台图标列表(分页) */ +export function listRoomPlatformIcon(query) { + return request({ + url: '/system/roomPlatformIcon/list', + method: 'get', + params: query + }) +} + +/** 查询房间地图平台图标详细 */ +export function getRoomPlatformIcon(id) { + return request({ + url: '/system/roomPlatformIcon/' + id, + method: 'get' + }) +} + /** 新增房间地图平台图标 */ export function addRoomPlatformIcon(data) { return request({ diff --git a/ruoyi-ui/src/store/modules/permission.js b/ruoyi-ui/src/store/modules/permission.js index f21d328..efea480 100644 --- a/ruoyi-ui/src/store/modules/permission.js +++ b/ruoyi-ui/src/store/modules/permission.js @@ -38,13 +38,16 @@ const permission = { const rdata = JSON.parse(JSON.stringify(res.data)) const sidebarRoutes = filterAsyncRouter(sdata) const rewriteRoutes = filterAsyncRouter(rdata, false, true) + // 二次排序:有图标的菜单优先展示;无图标的在下方。 + // 说明:后端按 orderNum 排序,但若部分菜单 icon 为空会显得“乱套”。 + const orderedSidebarRoutes = sortRoutesByIconPresence(sidebarRoutes) const asyncRoutes = filterDynamicRoutes(dynamicRoutes) rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) router.addRoutes(asyncRoutes) commit('SET_ROUTES', rewriteRoutes) - commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes)) - commit('SET_DEFAULT_ROUTES', sidebarRoutes) - commit('SET_TOPBAR_ROUTES', sidebarRoutes) + commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(orderedSidebarRoutes)) + commit('SET_DEFAULT_ROUTES', orderedSidebarRoutes) + commit('SET_TOPBAR_ROUTES', orderedSidebarRoutes) resolve(rewriteRoutes) }) }) @@ -103,6 +106,38 @@ function filterChildren(childrenMap, lastRouter = false) { return children } +/** + * 侧边栏排序:优先展示带图标的菜单;不带图标的排后。 + * 稳定排序:同组内相对顺序保持不变。 + */ +function sortRoutesByIconPresence(routes) { + if (!Array.isArray(routes) || routes.length === 0) return routes + + const withIcon = [] + const withoutIcon = [] + routes.forEach(r => { + // 图标字段来源: + // - 标准若依:meta.icon + // - 个别定制:直接放在 icon + const icon = + (r && r.meta && r.meta.icon) != null ? r.meta.icon + : (r && r.icon) != null ? r.icon + : '' + const iconStr = String(icon).trim() + // 约定:'#' 代表“未设置图标”,视为无图标 + if (iconStr !== '' && iconStr !== '#') withIcon.push(r) + else withoutIcon.push(r) + }) + + const sorted = withIcon.concat(withoutIcon) + sorted.forEach(r => { + if (r && Array.isArray(r.children) && r.children.length > 0) { + r.children = sortRoutesByIconPresence(r.children) + } + }) + return sorted +} + // 动态路由遍历,验证是否具备权限 export function filterDynamicRoutes(routes) { const res = []