在若依(RuoYi)框架中,新增页面后访问返回404,是最常见的集成问题之一。根本原因通常有两个:一是前端路由未在 `router/index.js`(或 `src/router/modules/` 对应模块)中正确声明,导致 Vue Router 无法匹配路径;二是后端菜单权限未配置——即未在系统管理 → 菜单管理中添加对应菜单项(需填写组件路径、路由名称、权限标识等),导致即使路由存在,也因权限校验失败被拦截跳转至404页。此外,若使用了动态路由加载(如按模块懒加载),还需检查组件路径是否正确、文件导出是否为 `default export`。特别注意:菜单的“组件路径”必须与路由 `component` 字段严格一致(如 `@/views/system/user/index`),且“权限字符”需与前端按钮指令 `v-permission="['system:user:edit']"` 及后端 `@RequiresPermissions` 注解保持同步。漏配任一环节,均会导致页面不可见或直接404。
1条回答 默认 最新
玛勒隔壁的老王 2026-03-15 15:35关注```html一、现象层:404错误的表象识别与快速定位
在若依(RuoYi)V3/V4(Spring Boot + Vue 2/3)多模块架构中,新增页面后直接访问 URL(如
/system/custom-page)返回浏览器原生 404 或前端自定义 404 页面,是高频集成阻塞点。需首先区分是 前端路由未命中(Vue Router 层 404)还是 后端接口未注册(Spring MVC 层 404)。可通过浏览器 DevTools 的 Network 面板观察请求目标:GET /system/custom-page若状态码为200但渲染空白 → 前端路由问题;若为404且响应体含Whitelabel Error Page→ 后端 Controller 未映射。二、结构层:若依前后端协同路由模型解析
若依采用“双路由”解耦设计:
- 前端路由(Vue Router):由
src/router/index.js统一管理,支持静态路由(基础布局)+ 动态路由(权限菜单驱动);模块化路由存于src/router/modules/(如system.js); - 后端菜单路由(RBAC 路由):由数据库表
sys_menu驱动,字段包括path(前端路径)、component(组件路径)、perms(权限标识)、is_frame(是否外链)等。
二者非一一对应,而是通过
component字段强绑定——该值必须同时满足:router.meta.component === sys_menu.component,否则权限校验通过后仍无法加载组件。三、诊断层:四维交叉验证排查法
维度 检查项 验证命令/操作 典型失败表现 前端路由 router/index.js是否注入模块import systemRouter from '@/router/modules/system'+addRoute(...)DevTools 中 router.getRoutes()无目标路由组件路径 component字符串是否精确匹配对比 sys_menu.component = '@/views/custom/index'与文件src/views/custom/index.vue导出控制台报错 Failed to resolve component: undefined权限同步 v-permission与@RequiresPermissions是否一致前端指令 v-permission="['custom:page:view']"↔ 后端注解@RequiresPermissions("custom:page:view")菜单可见但点击跳转至 404,或按钮灰显 四、修复层:标准化新增页面五步法
- 创建视图文件:在
src/views/custom/下新建index.vue,确保含export default { name: 'CustomPage' }; - 声明前端路由:在
src/router/modules/custom.js中定义路由对象,component: () => import('@/views/custom/index')(Vue 2)或defineAsyncComponent(() => import('@/views/custom/index'))(Vue 3); - 注入路由模块:在
src/router/index.js的const modulesRoutes = [...]中追加...customRouter; - 配置后台菜单:系统管理 → 菜单管理 → 新增,关键字段:
路径=/custom、组件=@/views/custom/index、权限字符=custom:page:view、类型=菜单; - 同步权限控制:前端按钮加
v-permission="['custom:page:view']",后端 Controller 方法加@RequiresPermissions("custom:page:view")。
五、进阶层:动态路由加载与懒加载陷阱图解
若依默认启用动态路由(基于用户角色从后端拉取菜单并生成路由)。其执行流程如下:
graph LR A[用户登录] --> B[调用 /getRouters 接口] B --> C{后端查询 sys_menu} C -->|返回菜单树| D[前端遍历菜单生成 route[]] D --> E[router.addRoute dynamic route] E --> F[匹配 path 触发 component 加载] F --> G{组件路径是否有效?} G -->|否| H[控制台报错 + 404] G -->|是| I[成功渲染]六、高阶避坑:易被忽略的七个细节
- ✅
component路径中的@别名必须与vue.config.js中configureWebpack.resolve.alias定义完全一致; - ✅ Vue 3 中
defineAsyncComponent必须包裹import(),不可直接写component: import(...); - ✅ 若菜单
is_frame=1(外链),则component字段应为空,否则强制走内部组件加载逻辑; - ✅ 权限字符中禁止空格、中文、特殊符号,仅允许字母、数字、冒号、短横线;
- ✅ 新增菜单后需清空浏览器缓存(或关闭“禁用缓存”调试模式),因菜单数据存在前端 localStorage 缓存;
- ✅ 后端
SysMenuController.getRouters()返回的component字段值,必须与前端路由声明的component字符串字面量完全相等(含大小写); - ✅ 若使用 TypeScript,
index.vue需导出default,而非具名导出export const CustomPage。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 前端路由(Vue Router):由