使用mybatis-flex重构“菜单管理”模块代码

This commit is contained in:
dataprince 2023-09-21 11:40:53 +08:00
parent 7a4a0d926d
commit 89e8ec72c7
22 changed files with 339 additions and 632 deletions

View File

@ -50,7 +50,7 @@ Ruoyi-Flex是一套全部开源的快速开发平台使用MIT开源许可协
<td>[Ruoyi-Flex交流一群]</td>
</tr>
<tr>
<td>2、付费微信VIP交流群加好友捐助99元</td>
<td>2、付费微信VIP交流群扫码捐助99元后加好友入群</td>
<td><img src="https://gitee.com/dataprince/ruoyi-flex/raw/master/image/dataprince.jpg"/></td>
</tr>
</table>

View File

@ -61,11 +61,6 @@ public class UserConstants {
*/
public static final String POST_DISABLE = "1";
/**
* 字典正常状态
*/
public static final String DICT_NORMAL = "0";
/**
* 是否为系统默认
*/
@ -81,6 +76,16 @@ public class UserConstants {
*/
public static final String NO_FRAME = "1";
/**
* 菜单正常状态
*/
public static final String MENU_NORMAL = "0";
/**
* 菜单停用状态
*/
public static final String MENU_DISABLE = "1";
/**
* 菜单类型目录
*/

View File

@ -14,6 +14,6 @@ public class BlackListException extends UserException
public BlackListException()
{
super("login.blocked", null);
super("login.blocked", (Object)null);
}
}

View File

@ -14,6 +14,6 @@ public class CaptchaException extends UserException
public CaptchaException()
{
super("user.jcaptcha.error", null);
super("user.jcaptcha.error", (Object)null);
}
}

View File

@ -14,6 +14,6 @@ public class CaptchaExpireException extends UserException
public CaptchaExpireException()
{
super("user.jcaptcha.expire", null);
super("user.jcaptcha.expire", (Object)null);
}
}

View File

@ -14,6 +14,6 @@ public class UserNotExistsException extends UserException
public UserNotExistsException()
{
super("user.not.exists", null);
super("user.not.exists", (Object)null);
}
}

View File

@ -14,6 +14,6 @@ public class UserPasswordNotMatchException extends UserException
public UserPasswordNotMatchException()
{
super("user.password.not.match", null);
super("user.password.not.match", (Object)null);
}
}

View File

@ -0,0 +1,35 @@
package com.ruoyi.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.lang.tree.parser.NodeParser;
import com.ruoyi.common.core.utils.reflect.ReflectUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 扩展 hutool TreeUtil 封装系统树构建
*
* @author Lion Li
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TreeBuildUtils extends TreeUtil {
/**
* 根据前端定制差异化字段
*/
public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
public static <T, K> List<Tree<K>> build(List<T> list, NodeParser<T, K> nodeParser) {
if (CollUtil.isEmpty(list)) {
return null;
}
K k = ReflectUtils.invokeGetter(list.get(0), "parentId");
return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser);
}
}

View File

@ -3,10 +3,16 @@ package com.ruoyi.system.controller.system;
import java.util.List;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.tree.Tree;
import com.ruoyi.common.core.core.domain.R;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.system.domain.SysMenu;
import com.ruoyi.system.domain.bo.SysMenuBo;
import com.ruoyi.system.domain.vo.MenuTreeSelectVo;
import com.ruoyi.system.domain.vo.RouterVo;
import com.ruoyi.system.domain.vo.SysMenuVo;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
@ -20,7 +26,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.web.core.BaseController;
import com.ruoyi.common.core.core.domain.AjaxResult;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
@ -38,15 +43,26 @@ public class SysMenuController extends BaseController
@Resource
private ISysMenuService menuService;
/**
* 获取路由信息
*
* @return 路由信息
*/
@GetMapping("/getRouters")
public R<List<RouterVo>> getRouters() {
List<SysMenu> menus = menuService.selectMenuTreeByUserId(LoginHelper.getUserId());
return R.ok(menuService.buildMenus(menus));
}
/**
* 获取菜单列表
*/
@SaCheckPermission("system:menu:list")
@GetMapping("/list")
public AjaxResult list(SysMenu menu)
public R<List<SysMenuVo>> list(SysMenuBo menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
return success(menus);
List<SysMenuVo> menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
return R.ok(menus);
}
/**
@ -54,9 +70,9 @@ public class SysMenuController extends BaseController
*/
@SaCheckPermission("system:menu:query")
@GetMapping(value = "/{menuId}")
public AjaxResult getInfo(@PathVariable Long menuId)
public R<SysMenuVo> getInfo(@PathVariable Long menuId)
{
return success(menuService.selectMenuById(menuId));
return R.ok(menuService.selectMenuById(menuId));
}
/**
@ -64,10 +80,10 @@ public class SysMenuController extends BaseController
*/
@SaCheckPermission("system:menu:query")
@GetMapping("/treeselect")
public AjaxResult treeselect(SysMenu menu)
public R<List<Tree<Long>>> treeselect(SysMenuBo menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
return success(menuService.buildMenuTreeSelect(menus));
List<SysMenuVo> menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
return R.ok(menuService.buildMenuTreeSelect(menus));
}
/**
@ -75,13 +91,13 @@ public class SysMenuController extends BaseController
*/
@SaCheckPermission("system:menu:query")
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
public R<MenuTreeSelectVo> roleMenuTreeselect(@PathVariable("roleId") Long roleId)
{
List<SysMenu> menus = menuService.selectMenuList(LoginHelper.getUserId());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
ajax.put("menus", menuService.buildMenuTreeSelect(menus));
return ajax;
List<SysMenuVo> menus = menuService.selectMenuList(LoginHelper.getUserId());
MenuTreeSelectVo selectVo = new MenuTreeSelectVo();
selectVo.setCheckedKeys(menuService.selectMenuListByRoleId(roleId));
selectVo.setMenus(menuService.buildMenuTreeSelect(menus));
return R.ok(selectVo);
}
/**
@ -90,18 +106,21 @@ public class SysMenuController extends BaseController
@SaCheckPermission("system:menu:add")
@Log(title = "菜单管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysMenu menu)
public R<Void> add(@Validated @RequestBody SysMenuBo menu)
{
if (!menuService.checkMenuNameUnique(menu))
{
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
return R.fail("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
}
menu.setCreateBy(LoginHelper.getUserId());
return toAjax(menuService.insertMenu(menu));
int inserted = menuService.insertMenu(menu);
if (inserted != 1) {
return R.fail("新增菜单'" + menu.getMenuName() + "'失败!");
}
return R.ok();
}
/**
@ -110,22 +129,25 @@ public class SysMenuController extends BaseController
@SaCheckPermission("system:menu:edit")
@Log(title = "菜单管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysMenu menu)
public R<Void> edit(@Validated @RequestBody SysMenuBo menu)
{
if (!menuService.checkMenuNameUnique(menu))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
return R.fail("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
}
else if (menu.getMenuId().equals(menu.getParentId()))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
}
menu.setUpdateBy(LoginHelper.getUserId());
return toAjax(menuService.updateMenu(menu));
boolean updated = menuService.updateMenu(menu);
if (!updated) {
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
return R.ok();
}
/**
@ -134,16 +156,20 @@ public class SysMenuController extends BaseController
@SaCheckPermission("system:menu:remove")
@Log(title = "菜单管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{menuId}")
public AjaxResult remove(@PathVariable("menuId") Long menuId)
public R<Void> remove(@PathVariable("menuId") Long menuId)
{
if (menuService.hasChildByMenuId(menuId))
{
return warn("存在子菜单,不允许删除");
return R.warn("存在子菜单,不允许删除");
}
if (menuService.checkMenuExistRole(menuId))
{
return warn("菜单已分配,不允许删除");
return R.warn("菜单已分配,不允许删除");
}
return toAjax(menuService.deleteMenuById(menuId));
boolean deleted = menuService.deleteMenuById(menuId);
if (!deleted) {
R.fail("删除菜单记录失败!");
}
return R.ok();
}
}

View File

@ -1,13 +1,17 @@
package com.ruoyi.system.domain;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.utils.StringUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.ruoyi.common.orm.core.domain.BaseEntity;
/**
@ -15,18 +19,22 @@ import com.ruoyi.common.orm.core.domain.BaseEntity;
*
* @author ruoyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Table(value = "sys_menu")
public class SysMenu extends BaseEntity
{
@Serial
private static final long serialVersionUID = 1L;
/** 菜单ID */
@Id(keyType = KeyType.Auto)
private Long menuId;
/** 菜单名称 */
private String menuName;
/** 父菜单名称 */
@Column(ignore = true)
private String parentName;
/** 父菜单ID */
@ -65,210 +73,86 @@ public class SysMenu extends BaseEntity
/** 菜单图标 */
private String icon;
/**
* 备注
*/
/** 备注 */
private String remark;
/** 子菜单 */
private List<SysMenu> children = new ArrayList<SysMenu>();
private List<SysMenu> children = new ArrayList<>();
public Long getMenuId()
{
return menuId;
}
public void setMenuId(Long menuId)
{
this.menuId = menuId;
}
@NotBlank(message = "菜单名称不能为空")
@Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
public String getMenuName()
{
return menuName;
}
public void setMenuName(String menuName)
{
this.menuName = menuName;
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public Long getParentId()
{
return parentId;
}
public void setParentId(Long parentId)
{
this.parentId = parentId;
}
@NotNull(message = "显示顺序不能为空")
public Integer getOrderNum()
{
return orderNum;
}
public void setOrderNum(Integer orderNum)
{
this.orderNum = orderNum;
}
@Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
public String getPath()
{
return path;
}
public void setPath(String path)
{
this.path = path;
}
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
public String getComponent()
{
return component;
}
public void setComponent(String component)
{
this.component = component;
}
public String getQuery()
{
return query;
}
public void setQuery(String query)
{
this.query = query;
}
public String getIsFrame()
{
return isFrame;
}
public void setIsFrame(String isFrame)
{
this.isFrame = isFrame;
}
public String getIsCache()
{
return isCache;
}
public void setIsCache(String isCache)
{
this.isCache = isCache;
}
@NotBlank(message = "菜单类型不能为空")
public String getMenuType()
{
return menuType;
}
public void setMenuType(String menuType)
{
this.menuType = menuType;
}
public String getVisible()
{
return visible;
}
public void setVisible(String visible)
{
this.visible = visible;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
public String getPerms()
{
return perms;
}
public void setPerms(String perms)
{
this.perms = perms;
}
public String getIcon()
{
return icon;
}
public void setIcon(String icon)
{
this.icon = icon;
}
public List<SysMenu> getChildren()
{
return children;
}
public void setChildren(List<SysMenu> children)
{
this.children = children;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("menuId", getMenuId())
.append("menuName", getMenuName())
.append("parentId", getParentId())
.append("orderNum", getOrderNum())
.append("path", getPath())
.append("component", getComponent())
.append("isFrame", getIsFrame())
.append("IsCache", getIsCache())
.append("menuType", getMenuType())
.append("visible", getVisible())
.append("status ", getStatus())
.append("perms", getPerms())
.append("icon", getIcon())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
// /**
// * 获取路由名称
// */
// public String getRouteName() {
// String routerName = StringUtils.capitalize(path);
// // 非外链并且是一级目录类型为目录
// if (isMenuFrame()) {
// routerName = StringUtils.EMPTY;
// }
// return routerName;
// }
//
// /**
// * 获取路由地址
// */
// public String getRouterPath() {
// String routerPath = this.path;
// // 内链打开外网方式
// if (getParentId() != 0L && isInnerLink()) {
// routerPath = innerLinkReplaceEach(routerPath);
// }
// // 非外链并且是一级目录类型为目录
// if (0L == getParentId() && UserConstants.TYPE_DIR.equals(getMenuType())
// && UserConstants.NO_FRAME.equals(getIsFrame())) {
// routerPath = "/" + this.path;
// }
// // 非外链并且是一级目录类型为菜单
// else if (isMenuFrame()) {
// routerPath = "/";
// }
// return routerPath;
// }
//
// /**
// * 获取组件信息
// */
// public String getComponentInfo() {
// String component = UserConstants.LAYOUT;
// if (StringUtils.isNotEmpty(this.component) && !isMenuFrame()) {
// component = this.component;
// } else if (StringUtils.isEmpty(this.component) && getParentId() != 0L && isInnerLink()) {
// component = UserConstants.INNER_LINK;
// } else if (StringUtils.isEmpty(this.component) && isParentView()) {
// component = UserConstants.PARENT_VIEW;
// }
// return component;
// }
//
// /**
// * 是否为菜单内部跳转
// */
// public boolean isMenuFrame() {
// return getParentId() == 0L && UserConstants.TYPE_MENU.equals(menuType) && isFrame.equals(UserConstants.NO_FRAME);
// }
//
// /**
// * 是否为内链组件
// */
// public boolean isInnerLink() {
// return isFrame.equals(UserConstants.NO_FRAME) && StringUtils.ishttp(path);
// }
//
// /**
// * 是否为parent_view组件
// */
// public boolean isParentView() {
// return getParentId() != 0L && UserConstants.TYPE_DIR.equals(menuType);
// }
//
// /**
// * 内链域名特殊字符替换
// */
// public static String innerLinkReplaceEach(String path) {
// return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS, Constants.WWW, "."},
// new String[]{"", "", "", "/"});
// }
}

View File

@ -62,7 +62,7 @@ public class SysMenuBo extends BaseEntity {
/**
* 路由参数
*/
private String queryParam;
private String query;
/**
* 是否为外链0是 1否

View File

@ -56,7 +56,7 @@ public class SysMenuVo implements Serializable {
/**
* 路由参数
*/
private String queryParam;
private String query;
/**
* 是否为外链0是 1否

View File

@ -13,74 +13,5 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysDictTypeMapper extends BaseMapper<SysDictType>
{
// /**
// * 根据条件分页查询字典类型
// *
// * @param dictType 字典类型信息
// * @return 字典类型集合信息
// */
// List<SysDictType> selectDictTypeList(SysDictType dictType);
//
// /**
// * 根据所有字典类型
// *
// * @return 字典类型集合信息
// */
// List<SysDictType> selectDictTypeAll();
//
// /**
// * 根据字典类型ID查询信息
// *
// * @param dictId 字典类型ID
// * @return 字典类型
// */
// SysDictType selectDictTypeById(Long dictId);
//
// /**
// * 根据字典类型查询信息
// *
// * @param dictType 字典类型
// * @return 字典类型
// */
// SysDictType selectDictTypeByType(String dictType);
//
// /**
// * 通过字典ID删除字典信息
// *
// * @param dictId 字典ID
// * @return 结果
// */
// int deleteDictTypeById(Long dictId);
//
// /**
// * 批量删除字典类型信息
// *
// * @param dictIds 需要删除的字典ID
// * @return 结果
// */
// int deleteDictTypeByIds(Long[] dictIds);
//
// /**
// * 新增字典类型信息
// *
// * @param dictType 字典类型信息
// * @return 结果
// */
// int insertDictType(SysDictType dictType);
//
// /**
// * 修改字典类型信息
// *
// * @param dictType 字典类型信息
// * @return 结果
// */
// int updateDictType(SysDictType dictType);
//
// /**
// * 校验字典类型称是否唯一
// *
// * @param dictType 字典类型
// * @return 结果
// */
// SysDictType checkDictTypeUnique(String dictType);
}

View File

@ -2,7 +2,10 @@ package com.ruoyi.system.mapper;
import java.util.List;
import com.mybatisflex.core.BaseMapper;
import com.ruoyi.system.domain.SysMenu;
import com.ruoyi.system.domain.bo.SysMenuBo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
@ -10,16 +13,9 @@ import org.apache.ibatis.annotations.Param;
*
* @author ruoyi
*/
public interface SysMenuMapper
@Mapper
public interface SysMenuMapper extends BaseMapper<SysMenu>
{
/**
* 查询系统菜单列表
*
* @param menu 菜单信息
* @return 菜单列表
*/
List<SysMenu> selectMenuList(SysMenu menu);
/**
* 根据用户所有权限
*
@ -33,7 +29,7 @@ public interface SysMenuMapper
* @param menu 菜单信息
* @return 菜单列表
*/
List<SysMenu> selectMenuListByUserId(SysMenu menu);
List<SysMenu> selectMenuListByUserId(SysMenuBo menu);
/**
* 根据角色ID查询权限
@ -51,13 +47,6 @@ public interface SysMenuMapper
*/
List<String> selectMenuPermsByUserId(Long userId);
/**
* 根据用户ID查询菜单
*
* @return 菜单列表
*/
List<SysMenu> selectMenuTreeAll();
/**
* 根据用户ID查询菜单
*
@ -74,53 +63,4 @@ public interface SysMenuMapper
* @return 选中菜单列表
*/
List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
/**
* 根据菜单ID查询信息
*
* @param menuId 菜单ID
* @return 菜单信息
*/
SysMenu selectMenuById(Long menuId);
/**
* 是否存在菜单子节点
*
* @param menuId 菜单ID
* @return 结果
*/
int hasChildByMenuId(Long menuId);
/**
* 新增菜单信息
*
* @param menu 菜单信息
* @return 结果
*/
int insertMenu(SysMenu menu);
/**
* 修改菜单信息
*
* @param menu 菜单信息
* @return 结果
*/
int updateMenu(SysMenu menu);
/**
* 删除菜单管理信息
*
* @param menuId 菜单ID
* @return 结果
*/
int deleteMenuById(Long menuId);
/**
* 校验菜单名称是否唯一
*
* @param menuName 菜单名称
* @param parentId 父菜单ID
* @return 结果
*/
SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
}

View File

@ -4,6 +4,7 @@ import java.util.List;
import com.mybatisflex.core.service.IService;
import com.ruoyi.common.orm.core.page.TableDataInfo;
import com.ruoyi.common.orm.core.service.IBaseService;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.domain.bo.SysConfigBo;
import com.ruoyi.system.domain.vo.SysConfigVo;
@ -13,8 +14,7 @@ import com.ruoyi.system.domain.vo.SysConfigVo;
*
* @author ruoyi
*/
//public interface ISysConfigService extends IBaseService<SysConfig>
public interface ISysConfigService extends IService<SysConfig>
public interface ISysConfigService extends IBaseService<SysConfig>
{
/**
* 查询参数配置信息

View File

@ -1,8 +1,7 @@
package com.ruoyi.system.service;
import com.mybatisflex.core.service.IService;
import com.ruoyi.common.orm.core.page.TableDataInfo;
import com.ruoyi.system.domain.SysDictData;
import com.ruoyi.common.orm.core.service.IBaseService;
import com.ruoyi.system.domain.SysDictType;
import com.ruoyi.system.domain.bo.SysDictTypeBo;
import com.ruoyi.system.domain.vo.SysDictDataVo;
@ -15,7 +14,7 @@ import java.util.List;
*
* @author ruoyi
*/
public interface ISysDictTypeService extends IService<SysDictType>
public interface ISysDictTypeService extends IBaseService<SysDictType>
{
/**
* 根据条件分页查询字典类型

View File

@ -3,16 +3,19 @@ package com.ruoyi.system.service;
import java.util.List;
import java.util.Set;
import cn.hutool.core.lang.tree.Tree;
import com.ruoyi.common.orm.core.service.IBaseService;
import com.ruoyi.system.domain.SysMenu;
import com.ruoyi.system.domain.TreeSelect;
import com.ruoyi.system.domain.bo.SysMenuBo;
import com.ruoyi.system.domain.vo.RouterVo;
import com.ruoyi.system.domain.vo.SysMenuVo;
/**
* 菜单 业务层
*
* @author ruoyi
*/
public interface ISysMenuService
public interface ISysMenuService extends IBaseService<SysMenu>
{
/**
* 根据用户查询系统菜单列表
@ -20,7 +23,7 @@ public interface ISysMenuService
* @param userId 用户ID
* @return 菜单列表
*/
List<SysMenu> selectMenuList(Long userId);
List<SysMenuVo> selectMenuList(Long userId);
/**
* 根据用户查询系统菜单列表
@ -29,7 +32,7 @@ public interface ISysMenuService
* @param userId 用户ID
* @return 菜单列表
*/
List<SysMenu> selectMenuList(SysMenu menu, Long userId);
List<SysMenuVo> selectMenuList(SysMenuBo menu, Long userId);
/**
* 根据用户ID查询权限
@ -71,21 +74,13 @@ public interface ISysMenuService
*/
List<RouterVo> buildMenus(List<SysMenu> menus);
/**
* 构建前端所需要树结构
*
* @param menus 菜单列表
* @return 树结构列表
*/
List<SysMenu> buildMenuTree(List<SysMenu> menus);
/**
* 构建前端所需要下拉树结构
*
* @param menus 菜单列表
* @return 下拉树结构列表
*/
List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus);
List<Tree<Long>> buildMenuTreeSelect(List<SysMenuVo> menus);
/**
* 根据菜单ID查询信息
@ -93,7 +88,7 @@ public interface ISysMenuService
* @param menuId 菜单ID
* @return 菜单信息
*/
SysMenu selectMenuById(Long menuId);
SysMenuVo selectMenuById(Long menuId);
/**
* 是否存在菜单子节点
@ -114,26 +109,26 @@ public interface ISysMenuService
/**
* 新增保存菜单信息
*
* @param menu 菜单信息
* @return 结果
* @param menuBo 菜单信息
* @return 结果:受影响的行数
*/
int insertMenu(SysMenu menu);
int insertMenu(SysMenuBo menuBo);
/**
* 修改保存菜单信息
*
* @param menu 菜单信息
* @return 结果
* @param menuBo 菜单信息
* @return 结果:true 更新成功false 更新失败
*/
int updateMenu(SysMenu menu);
boolean updateMenu(SysMenuBo menuBo);
/**
* 删除菜单管理信息
*
* @param menuId 菜单ID
* @return 结果
* @return 结果:true 删除成功false 删除失败
*/
int deleteMenuById(Long menuId);
boolean deleteMenuById(Long menuId);
/**
* 校验菜单名称是否唯一
@ -141,5 +136,5 @@ public interface ISysMenuService
* @param menu 菜单信息
* @return 结果
*/
boolean checkMenuNameUnique(SysMenu menu);
boolean checkMenuNameUnique(SysMenuBo menu);
}

View File

@ -2,8 +2,8 @@ package com.ruoyi.system.service;
import java.util.List;
import com.mybatisflex.core.service.IService;
import com.ruoyi.common.orm.core.page.TableDataInfo;
import com.ruoyi.common.orm.core.service.IBaseService;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.domain.bo.SysNoticeBo;
import com.ruoyi.system.domain.vo.SysNoticeVo;
@ -13,7 +13,7 @@ import com.ruoyi.system.domain.vo.SysNoticeVo;
*
* @author 数据小王子
*/
public interface ISysNoticeService extends IService<SysNotice>
public interface ISysNoticeService extends IBaseService<SysNotice>
{
/**
* 查询公告信息

View File

@ -2,8 +2,8 @@ package com.ruoyi.system.service;
import java.util.List;
import com.mybatisflex.core.service.IService;
import com.ruoyi.common.orm.core.page.TableDataInfo;
import com.ruoyi.common.orm.core.service.IBaseService;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.domain.bo.SysPostBo;
import com.ruoyi.system.domain.vo.SysPostVo;
@ -13,7 +13,7 @@ import com.ruoyi.system.domain.vo.SysPostVo;
*
* @author ruoyi
*/
public interface ISysPostService extends IService<SysPost>
public interface ISysPostService extends IBaseService<SysPost>
{
/**
* 查询岗位信息集合

View File

@ -1,23 +1,27 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.mybatisflex.core.query.QueryWrapper;
import com.ruoyi.common.core.utils.MapstructUtils;
import com.ruoyi.common.core.utils.StreamUtils;
import com.ruoyi.common.core.utils.TreeBuildUtils;
import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.system.domain.SysMenu;
import com.ruoyi.system.domain.SysRole;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.SysMenuBo;
import com.ruoyi.system.domain.vo.SysMenuVo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.system.domain.TreeSelect;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.domain.vo.MetaVo;
import com.ruoyi.system.domain.vo.RouterVo;
@ -26,15 +30,15 @@ import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysRoleMenuMapper;
import com.ruoyi.system.service.ISysMenuService;
import static com.ruoyi.system.domain.table.SysMenuTableDef.SYS_MENU;
/**
* 菜单 业务层处理
*
* @author ruoyi
*/
@Service
public class SysMenuServiceImpl implements ISysMenuService {
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper,SysMenu> implements ISysMenuService {
@Resource
private SysMenuMapper menuMapper;
@ -43,6 +47,10 @@ public class SysMenuServiceImpl implements ISysMenuService {
@Resource
private SysRoleMenuMapper roleMenuMapper;
@Override
public QueryWrapper query() {
return super.query().from(SYS_MENU);
}
/**
* 根据用户查询系统菜单列表
@ -51,25 +59,43 @@ public class SysMenuServiceImpl implements ISysMenuService {
* @return 菜单列表
*/
@Override
public List<SysMenu> selectMenuList(Long userId) {
return selectMenuList(new SysMenu(), userId);
public List<SysMenuVo> selectMenuList(Long userId) {
return selectMenuList(new SysMenuBo(), userId);
}
private QueryWrapper buildQueryWrapper(SysMenuBo menuBo){
QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
if (StringUtils.isNotEmpty(menuBo.getMenuName())) {
queryWrapper.and(SYS_MENU.MENU_NAME.like(menuBo.getMenuName()));
}
if (StringUtils.isNotEmpty(menuBo.getVisible())) {
queryWrapper.and(SYS_MENU.VISIBLE.eq(menuBo.getVisible()));
}
if (StringUtils.isNotEmpty(menuBo.getStatus())) {
queryWrapper.and(SYS_MENU.STATUS.eq(menuBo.getStatus()));
}
queryWrapper.orderBy(SYS_MENU.PARENT_ID.asc(),SYS_MENU.ORDER_NUM.asc());
return queryWrapper;
}
/**
* 查询系统菜单列表
*
* @param menu 菜单信息
* @param menuBo 菜单信息
* @return 菜单列表
*/
@Override
public List<SysMenu> selectMenuList(SysMenu menu, Long userId) {
List<SysMenu> menuList = null;
public List<SysMenuVo> selectMenuList(SysMenuBo menuBo, Long userId) {
List<SysMenuVo> menuList;
// 管理员显示所有菜单信息
if (SysUser.isAdmin(userId)) {
menuList = menuMapper.selectMenuList(menu);
if (LoginHelper.isSuperAdmin(userId)) {
QueryWrapper queryWrapper = buildQueryWrapper(menuBo);
menuList = this.listAs(queryWrapper, SysMenuVo.class);
} else {
menu.getParams().put("userId", userId);
menuList = menuMapper.selectMenuListByUserId(menu);
menuBo.getParams().put("userId", userId);
List<SysMenu> list = menuMapper.selectMenuListByUserId(menuBo);
menuList = MapstructUtils.convert(list, SysMenuVo.class);
}
return menuList;
}
@ -110,6 +136,14 @@ public class SysMenuServiceImpl implements ISysMenuService {
return permsSet;
}
private QueryWrapper buildMenuTreeQueryWrapper(){
QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
queryWrapper.and(SYS_MENU.MENU_TYPE.in(UserConstants.TYPE_DIR, UserConstants.TYPE_MENU));
queryWrapper.and(SYS_MENU.STATUS.eq(UserConstants.MENU_NORMAL));
queryWrapper.orderBy(SYS_MENU.PARENT_ID.asc(),SYS_MENU.ORDER_NUM.asc());
return queryWrapper;
}
/**
* 根据用户ID查询菜单
*
@ -118,9 +152,10 @@ public class SysMenuServiceImpl implements ISysMenuService {
*/
@Override
public List<SysMenu> selectMenuTreeByUserId(Long userId) {
List<SysMenu> menus = null;
List<SysMenu> menus;
if (LoginHelper.isSuperAdmin(userId)) {
menus = menuMapper.selectMenuTreeAll();
QueryWrapper queryWrapper = buildMenuTreeQueryWrapper();
menus = this.list(queryWrapper);
} else {
menus = menuMapper.selectMenuTreeByUserId(userId);
}
@ -190,30 +225,6 @@ public class SysMenuServiceImpl implements ISysMenuService {
return routers;
}
/**
* 构建前端所需要树结构
*
* @param menus 菜单列表
* @return 树结构列表
*/
@Override
public List<SysMenu> buildMenuTree(List<SysMenu> menus) {
List<SysMenu> returnList = new ArrayList<>();
List<Long> tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext(); ) {
SysMenu menu = (SysMenu) iterator.next();
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(menu.getParentId())) {
recursionFn(menus, menu);
returnList.add(menu);
}
}
if (returnList.isEmpty()) {
returnList = menus;
}
return returnList;
}
/**
* 构建前端所需要下拉树结构
*
@ -221,9 +232,15 @@ public class SysMenuServiceImpl implements ISysMenuService {
* @return 下拉树结构列表
*/
@Override
public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) {
List<SysMenu> menuTrees = buildMenuTree(menus);
return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
public List<Tree<Long>> buildMenuTreeSelect(List<SysMenuVo> menus) {
if (CollUtil.isEmpty(menus)) {
return CollUtil.newArrayList();
}
return TreeBuildUtils.build(menus, (menu, tree) ->
tree.setId(menu.getMenuId())
.setParentId(menu.getParentId())
.setName(menu.getMenuName())
.setWeight(menu.getOrderNum()));
}
/**
@ -233,8 +250,8 @@ public class SysMenuServiceImpl implements ISysMenuService {
* @return 菜单信息
*/
@Override
public SysMenu selectMenuById(Long menuId) {
return menuMapper.selectMenuById(menuId);
public SysMenuVo selectMenuById(Long menuId) {
return this.getOneAs(query().where(SYS_MENU.MENU_ID.eq(menuId)), SysMenuVo.class);
}
/**
@ -245,8 +262,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
*/
@Override
public boolean hasChildByMenuId(Long menuId) {
int result = menuMapper.hasChildByMenuId(menuId);
return result > 0;
return this.exists(query().where(SYS_MENU.PARENT_ID.eq(menuId)));
}
/**
@ -257,41 +273,43 @@ public class SysMenuServiceImpl implements ISysMenuService {
*/
@Override
public boolean checkMenuExistRole(Long menuId) {
int result = roleMenuMapper.checkMenuExistRole(menuId);
int result = roleMenuMapper.checkMenuExistRole(menuId);//TODO:转化为mybatis-flex
return result > 0;
}
/**
* 新增保存菜单信息
*
* @param menu 菜单信息
* @return 结果
* @param menuBo 菜单信息
* @return 结果:受影响的行数
*/
@Override
public int insertMenu(SysMenu menu) {
return menuMapper.insertMenu(menu);
public int insertMenu(SysMenuBo menuBo) {
SysMenu menu = MapstructUtils.convert(menuBo, SysMenu.class);
return menuMapper.insert(menu, false);
}
/**
* 修改保存菜单信息
*
* @param menu 菜单信息
* @return 结果
* @param menuBo 菜单信息
* @return 结果:true 更新成功false 更新失败
*/
@Override
public int updateMenu(SysMenu menu) {
return menuMapper.updateMenu(menu);
public boolean updateMenu(SysMenuBo menuBo) {
SysMenu menu = MapstructUtils.convert(menuBo, SysMenu.class);
return this.updateById(menu);
}
/**
* 删除菜单管理信息
*
* @param menuId 菜单ID
* @return 结果
* @return 结果:true 删除成功false 删除失败
*/
@Override
public int deleteMenuById(Long menuId) {
return menuMapper.deleteMenuById(menuId);
public boolean deleteMenuById(Long menuId) {
return this.removeById(menuId);
}
/**
@ -301,9 +319,11 @@ public class SysMenuServiceImpl implements ISysMenuService {
* @return 结果
*/
@Override
public boolean checkMenuNameUnique(SysMenu menu) {
public boolean checkMenuNameUnique(SysMenuBo menu) {
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
QueryWrapper queryWrapper = query().where(SYS_MENU.MENU_NAME.eq(menu.getMenuName()))
.and(SYS_MENU.PARENT_ID.eq(menu.getParentId()));
SysMenu info = this.getOne(queryWrapper);
if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) {
return UserConstants.NOT_UNIQUE;
}
@ -405,10 +425,9 @@ public class SysMenuServiceImpl implements ISysMenuService {
* @param parentId 传入的父节点ID
* @return String
*/
public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
private List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
List<SysMenu> returnList = new ArrayList<>();
for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext(); ) {
SysMenu t = (SysMenu) iterator.next();
for (SysMenu t : list) {
// 根据传入的某个父节点ID,遍历该父节点的所有子节点
if (t.getParentId() == parentId) {
recursionFn(list, t);
@ -420,43 +439,19 @@ public class SysMenuServiceImpl implements ISysMenuService {
/**
* 递归列表
*
* @param list 分类表
* @param t 子节点
*/
private void recursionFn(List<SysMenu> list, SysMenu t) {
// 得到子节点列表
List<SysMenu> childList = getChildList(list, t);
List<SysMenu> childList = StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId()));
t.setChildren(childList);
for (SysMenu tChild : childList) {
if (hasChild(list, tChild)) {
// 判断是否有子节点
if (list.stream().anyMatch(n -> n.getParentId().equals(tChild.getMenuId()))) {
recursionFn(list, tChild);
}
}
}
/**
* 得到子节点列表
*/
private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
List<SysMenu> tlist = new ArrayList<>();
Iterator<SysMenu> it = list.iterator();
while (it.hasNext()) {
SysMenu n = (SysMenu) it.next();
if (n.getParentId().longValue() == t.getMenuId().longValue()) {
tlist.add(n);
}
}
return tlist;
}
/**
* 判断是否有子节点
*/
private boolean hasChild(List<SysMenu> list, SysMenu t) {
return getChildList(list, t).size() > 0;
}
/**
* 内链域名特殊字符替换
*

View File

@ -32,28 +32,6 @@
from sys_menu
</sql>
<select id="selectMenuList" parameterType="SysMenu" resultMap="SysMenuResult">
<include refid="selectMenuVo"/>
<where>
<if test="menuName != null and menuName != ''">
AND menu_name like concat('%', #{menuName}, '%')
</if>
<if test="visible != null and visible != ''">
AND visible = #{visible}
</if>
<if test="status != null and status != ''">
AND status = #{status}
</if>
</where>
order by parent_id, order_num
</select>
<select id="selectMenuTreeAll" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
order by m.parent_id, m.order_num
</select>
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m
@ -118,85 +96,4 @@
where m.status = '0' and rm.role_id = #{roleId}
</select>
<select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult">
<include refid="selectMenuVo"/>
where menu_id = #{menuId}
</select>
<select id="hasChildByMenuId" resultType="Integer">
select count(1) from sys_menu where parent_id = #{menuId}
</select>
<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
<include refid="selectMenuVo"/>
where menu_name=#{menuName} and parent_id = #{parentId} limit 1
</select>
<update id="updateMenu" parameterType="SysMenu">
update sys_menu
<set>
<if test="menuName != null and menuName != ''">menu_name = #{menuName},</if>
<if test="parentId != null">parent_id = #{parentId},</if>
<if test="orderNum != null">order_num = #{orderNum},</if>
<if test="path != null and path != ''">path = #{path},</if>
<if test="component != null">component = #{component},</if>
<if test="query != null">`query` = #{query},</if>
<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
<if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
<if test="visible != null">visible = #{visible},</if>
<if test="status != null">status = #{status},</if>
<if test="perms !=null">perms = #{perms},</if>
<if test="icon !=null and icon != ''">icon = #{icon},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
update_time = sysdate()
</set>
where menu_id = #{menuId}
</update>
<insert id="insertMenu" parameterType="SysMenu">
insert into sys_menu(
<if test="menuId != null and menuId != 0">menu_id,</if>
<if test="parentId != null and parentId != 0">parent_id,</if>
<if test="menuName != null and menuName != ''">menu_name,</if>
<if test="orderNum != null">order_num,</if>
<if test="path != null and path != ''">path,</if>
<if test="component != null and component != ''">component,</if>
<if test="query != null and query != ''">`query`,</if>
<if test="isFrame != null and isFrame != ''">is_frame,</if>
<if test="isCache != null and isCache != ''">is_cache,</if>
<if test="menuType != null and menuType != ''">menu_type,</if>
<if test="visible != null">visible,</if>
<if test="status != null">status,</if>
<if test="perms !=null and perms != ''">perms,</if>
<if test="icon != null and icon != ''">icon,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
create_time
)values(
<if test="menuId != null and menuId != 0">#{menuId},</if>
<if test="parentId != null and parentId != 0">#{parentId},</if>
<if test="menuName != null and menuName != ''">#{menuName},</if>
<if test="orderNum != null">#{orderNum},</if>
<if test="path != null and path != ''">#{path},</if>
<if test="component != null and component != ''">#{component},</if>
<if test="query != null and query != ''">#{query},</if>
<if test="isFrame != null and isFrame != ''">#{isFrame},</if>
<if test="isCache != null and isCache != ''">#{isCache},</if>
<if test="menuType != null and menuType != ''">#{menuType},</if>
<if test="visible != null">#{visible},</if>
<if test="status != null">#{status},</if>
<if test="perms !=null and perms != ''">#{perms},</if>
<if test="icon != null and icon != ''">#{icon},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
sysdate()
)
</insert>
<delete id="deleteMenuById" parameterType="Long">
delete from sys_menu where menu_id = #{menuId}
</delete>
</mapper>

View File

@ -290,7 +290,7 @@
</template>
<script setup name="Menu">
import { addMenu, delMenu, getMenu, listMenu, updateMenu } from "@/api/system/menu";
import { addMenu, delMenu, getMenu, listMenu, updateMenu } from "@/api/system/menu";
import SvgIcon from "@/components/SvgIcon";
import IconSelect from "@/components/IconSelect";