作者 RuoYi

菜单路由配置支持内链访问

@@ -24,6 +24,6 @@ public class SysIndexController @@ -24,6 +24,6 @@ public class SysIndexController
24 @RequestMapping("/") 24 @RequestMapping("/")
25 public String index() 25 public String index()
26 { 26 {
27 - return StringUtils.format("欢迎使用RuoYi后台管理框架,当前版本:v{}", ruoyiConfig.getVersion()); 27 + return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
28 } 28 }
29 } 29 }
@@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestBody; @@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestBody;
13 import org.springframework.web.bind.annotation.RequestMapping; 13 import org.springframework.web.bind.annotation.RequestMapping;
14 import org.springframework.web.bind.annotation.RestController; 14 import org.springframework.web.bind.annotation.RestController;
15 import com.ruoyi.common.annotation.Log; 15 import com.ruoyi.common.annotation.Log;
16 -import com.ruoyi.common.constant.Constants;  
17 import com.ruoyi.common.constant.UserConstants; 16 import com.ruoyi.common.constant.UserConstants;
18 import com.ruoyi.common.core.controller.BaseController; 17 import com.ruoyi.common.core.controller.BaseController;
19 import com.ruoyi.common.core.domain.AjaxResult; 18 import com.ruoyi.common.core.domain.AjaxResult;
@@ -102,8 +101,7 @@ public class SysMenuController extends BaseController @@ -102,8 +101,7 @@ public class SysMenuController extends BaseController
102 { 101 {
103 return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); 102 return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
104 } 103 }
105 - else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())  
106 - && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)) 104 + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
107 { 105 {
108 return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); 106 return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
109 } 107 }
@@ -123,8 +121,7 @@ public class SysMenuController extends BaseController @@ -123,8 +121,7 @@ public class SysMenuController extends BaseController
123 { 121 {
124 return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); 122 return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
125 } 123 }
126 - else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())  
127 - && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)) 124 + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
128 { 125 {
129 return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); 126 return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
130 } 127 }
@@ -57,6 +57,9 @@ public class UserConstants @@ -57,6 +57,9 @@ public class UserConstants
57 /** ParentView组件标识 */ 57 /** ParentView组件标识 */
58 public final static String PARENT_VIEW = "ParentView"; 58 public final static String PARENT_VIEW = "ParentView";
59 59
  60 + /** InnerLink组件标识 */
  61 + public final static String INNER_LINK = "InnerLink";
  62 +
60 /** 校验返回结果码 */ 63 /** 校验返回结果码 */
61 public final static String UNIQUE = "0"; 64 public final static String UNIQUE = "0";
62 public final static String NOT_UNIQUE = "1"; 65 public final static String NOT_UNIQUE = "1";
@@ -6,6 +6,7 @@ import java.util.HashSet; @@ -6,6 +6,7 @@ import java.util.HashSet;
6 import java.util.List; 6 import java.util.List;
7 import java.util.Map; 7 import java.util.Map;
8 import java.util.Set; 8 import java.util.Set;
  9 +import com.ruoyi.common.constant.Constants;
9 import com.ruoyi.common.core.text.StrFormatter; 10 import com.ruoyi.common.core.text.StrFormatter;
10 11
11 /** 12 /**
@@ -261,6 +262,17 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils @@ -261,6 +262,17 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
261 } 262 }
262 263
263 /** 264 /**
  265 + * 是否为http(s)://开头
  266 + *
  267 + * @param link 链接
  268 + * @return 结果
  269 + */
  270 + public static boolean ishttp(String link)
  271 + {
  272 + return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
  273 + }
  274 +
  275 + /**
264 * 字符串转set 276 * 字符串转set
265 * 277 *
266 * @param str 字符串 278 * @param str 字符串
1 package com.ruoyi.system.domain.vo; 1 package com.ruoyi.system.domain.vo;
2 2
  3 +import com.ruoyi.common.utils.StringUtils;
  4 +
3 /** 5 /**
4 * 路由显示信息 6 * 路由显示信息
5 * 7 *
@@ -22,6 +24,11 @@ public class MetaVo @@ -22,6 +24,11 @@ public class MetaVo
22 */ 24 */
23 private boolean noCache; 25 private boolean noCache;
24 26
  27 + /**
  28 + * 内链地址(http(s)://开头)
  29 + */
  30 + private String link;
  31 +
25 public MetaVo() 32 public MetaVo()
26 { 33 {
27 } 34 }
@@ -39,6 +46,24 @@ public class MetaVo @@ -39,6 +46,24 @@ public class MetaVo
39 this.noCache = noCache; 46 this.noCache = noCache;
40 } 47 }
41 48
  49 + public MetaVo(String title, String icon, String link)
  50 + {
  51 + this.title = title;
  52 + this.icon = icon;
  53 + this.link = link;
  54 + }
  55 +
  56 + public MetaVo(String title, String icon, boolean noCache, String link)
  57 + {
  58 + this.title = title;
  59 + this.icon = icon;
  60 + this.noCache = noCache;
  61 + if (StringUtils.ishttp(link))
  62 + {
  63 + this.link = link;
  64 + }
  65 + }
  66 +
42 public boolean isNoCache() 67 public boolean isNoCache()
43 { 68 {
44 return noCache; 69 return noCache;
@@ -68,4 +93,14 @@ public class MetaVo @@ -68,4 +93,14 @@ public class MetaVo
68 { 93 {
69 this.icon = icon; 94 this.icon = icon;
70 } 95 }
  96 +
  97 + public String getLink()
  98 + {
  99 + return link;
  100 + }
  101 +
  102 + public void setLink(String link)
  103 + {
  104 + this.link = link;
  105 + }
71 } 106 }
@@ -10,6 +10,7 @@ import java.util.Set; @@ -10,6 +10,7 @@ import java.util.Set;
10 import java.util.stream.Collectors; 10 import java.util.stream.Collectors;
11 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
  13 +import com.ruoyi.common.constant.Constants;
13 import com.ruoyi.common.constant.UserConstants; 14 import com.ruoyi.common.constant.UserConstants;
14 import com.ruoyi.common.core.domain.TreeSelect; 15 import com.ruoyi.common.core.domain.TreeSelect;
15 import com.ruoyi.common.core.domain.entity.SysMenu; 16 import com.ruoyi.common.core.domain.entity.SysMenu;
@@ -150,7 +151,7 @@ public class SysMenuServiceImpl implements ISysMenuService @@ -150,7 +151,7 @@ public class SysMenuServiceImpl implements ISysMenuService
150 router.setName(getRouteName(menu)); 151 router.setName(getRouteName(menu));
151 router.setPath(getRouterPath(menu)); 152 router.setPath(getRouterPath(menu));
152 router.setComponent(getComponent(menu)); 153 router.setComponent(getComponent(menu));
153 - router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()))); 154 + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
154 List<SysMenu> cMenus = menu.getChildren(); 155 List<SysMenu> cMenus = menu.getChildren();
155 if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) 156 if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
156 { 157 {
@@ -166,7 +167,21 @@ public class SysMenuServiceImpl implements ISysMenuService @@ -166,7 +167,21 @@ public class SysMenuServiceImpl implements ISysMenuService
166 children.setPath(menu.getPath()); 167 children.setPath(menu.getPath());
167 children.setComponent(menu.getComponent()); 168 children.setComponent(menu.getComponent());
168 children.setName(StringUtils.capitalize(menu.getPath())); 169 children.setName(StringUtils.capitalize(menu.getPath()));
169 - children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()))); 170 + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
  171 + childrenList.add(children);
  172 + router.setChildren(childrenList);
  173 + }
  174 + else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
  175 + {
  176 + router.setMeta(null);
  177 + router.setPath("/inner");
  178 + List<RouterVo> childrenList = new ArrayList<RouterVo>();
  179 + RouterVo children = new RouterVo();
  180 + String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
  181 + children.setPath(routerPath);
  182 + children.setComponent(UserConstants.INNER_LINK);
  183 + children.setName(StringUtils.capitalize(routerPath));
  184 + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
170 childrenList.add(children); 185 childrenList.add(children);
171 router.setChildren(childrenList); 186 router.setChildren(childrenList);
172 } 187 }
@@ -338,6 +353,11 @@ public class SysMenuServiceImpl implements ISysMenuService @@ -338,6 +353,11 @@ public class SysMenuServiceImpl implements ISysMenuService
338 public String getRouterPath(SysMenu menu) 353 public String getRouterPath(SysMenu menu)
339 { 354 {
340 String routerPath = menu.getPath(); 355 String routerPath = menu.getPath();
  356 + // 内链打开外网方式
  357 + if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
  358 + {
  359 + routerPath = StringUtils.replaceEach(routerPath, new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
  360 + }
341 // 非外链并且是一级目录(类型为目录) 361 // 非外链并且是一级目录(类型为目录)
342 if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) 362 if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
343 && UserConstants.NO_FRAME.equals(menu.getIsFrame())) 363 && UserConstants.NO_FRAME.equals(menu.getIsFrame()))
@@ -365,6 +385,10 @@ public class SysMenuServiceImpl implements ISysMenuService @@ -365,6 +385,10 @@ public class SysMenuServiceImpl implements ISysMenuService
365 { 385 {
366 component = menu.getComponent(); 386 component = menu.getComponent();
367 } 387 }
  388 + else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
  389 + {
  390 + component = UserConstants.INNER_LINK;
  391 + }
368 else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) 392 else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
369 { 393 {
370 component = UserConstants.PARENT_VIEW; 394 component = UserConstants.PARENT_VIEW;
@@ -385,6 +409,17 @@ public class SysMenuServiceImpl implements ISysMenuService @@ -385,6 +409,17 @@ public class SysMenuServiceImpl implements ISysMenuService
385 } 409 }
386 410
387 /** 411 /**
  412 + * 是否为内链组件
  413 + *
  414 + * @param menu 菜单信息
  415 + * @return 结果
  416 + */
  417 + public boolean isInnerLink(SysMenu menu)
  418 + {
  419 + return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
  420 + }
  421 +
  422 + /**
388 * 是否为parent_view组件 423 * 是否为parent_view组件
389 * 424 *
390 * @param menu 菜单信息 425 * @param menu 菜单信息
@@ -70,9 +70,11 @@ export default { @@ -70,9 +70,11 @@ export default {
70 this.show = false 70 this.show = false
71 }, 71 },
72 change(val) { 72 change(val) {
  73 + const path = val.path;
73 if(this.ishttp(val.path)) { 74 if(this.ishttp(val.path)) {
74 // http(s):// 路径新窗口打开 75 // http(s):// 路径新窗口打开
75 - window.open(val.path, "_blank"); 76 + const pindex = path.indexOf("http");
  77 + window.open(path.substr(pindex, path.length), "_blank");
76 } else { 78 } else {
77 this.$router.push(val.path) 79 this.$router.push(val.path)
78 } 80 }
@@ -51,7 +51,7 @@ export default { @@ -51,7 +51,7 @@ export default {
51 // fix css style bug in open el-dialog 51 // fix css style bug in open el-dialog
52 .el-popup-parent--hidden { 52 .el-popup-parent--hidden {
53 .fixed-header { 53 .fixed-header {
54 - padding-right: 15px; 54 + padding-right: 17px;
55 } 55 }
56 } 56 }
57 </style> 57 </style>
  1 +<script>
  2 +export default {
  3 + data() {
  4 + return {};
  5 + },
  6 + render() {
  7 + const { $route: { meta: { link } }, } = this;
  8 + if ({ link }.link === "") {
  9 + return "404";
  10 + }
  11 + let url = { link }.link;
  12 + const height = document.documentElement.clientHeight - 94.5 + "px";
  13 + const style = { height: height };
  14 +
  15 + return (
  16 + <div style={style}>
  17 + <iframe
  18 + src={url}
  19 + frameborder="no"
  20 + style="width: 100%; height: 100%"
  21 + scrolling="auto"
  22 + ></iframe>
  23 + </div>
  24 + );
  25 + },
  26 +};
  27 +</script>
@@ -6,6 +6,7 @@ Vue.use(Router) @@ -6,6 +6,7 @@ Vue.use(Router)
6 /* Layout */ 6 /* Layout */
7 import Layout from '@/layout' 7 import Layout from '@/layout'
8 import ParentView from '@/components/ParentView'; 8 import ParentView from '@/components/ParentView';
  9 +import InnerLink from '@/layout/components/InnerLink'
9 10
10 /** 11 /**
11 * Note: 路由配置项 12 * Note: 路由配置项
@@ -2,6 +2,7 @@ import { constantRoutes } from '@/router' @@ -2,6 +2,7 @@ import { constantRoutes } from '@/router'
2 import { getRouters } from '@/api/menu' 2 import { getRouters } from '@/api/menu'
3 import Layout from '@/layout/index' 3 import Layout from '@/layout/index'
4 import ParentView from '@/components/ParentView'; 4 import ParentView from '@/components/ParentView';
  5 +import InnerLink from '@/layout/components/InnerLink'
5 6
6 const permission = { 7 const permission = {
7 state: { 8 state: {
@@ -65,6 +66,8 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { @@ -65,6 +66,8 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
65 route.component = Layout 66 route.component = Layout
66 } else if (route.component === 'ParentView') { 67 } else if (route.component === 'ParentView') {
67 route.component = ParentView 68 route.component = ParentView
  69 + } else if (route.component === 'InnerLink') {
  70 + route.component = InnerLink
68 } else { 71 } else {
69 route.component = loadView(route.component) 72 route.component = loadView(route.component)
70 } 73 }