package com.moral.api.service.impl; 
 | 
  
 | 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 
 | 
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; 
 | 
import com.moral.api.config.mybatis.wrapper.NullFilterWrapper; 
 | 
import com.moral.api.entity.Group; 
 | 
import com.moral.api.entity.Menu; 
 | 
import com.moral.api.mapper.GroupMenuMapper; 
 | 
import com.moral.api.mapper.MenuMapper; 
 | 
import com.moral.api.pojo.dto.menu.MenuDTO; 
 | 
import com.moral.api.pojo.dto.menu.MenuQueryDTO; 
 | 
import com.moral.api.pojo.dto.menu.MenuQueryNamesDTO; 
 | 
import com.moral.api.pojo.form.menu.MenuDeleteForm; 
 | 
import com.moral.api.pojo.form.menu.MenuInsertForm; 
 | 
import com.moral.api.pojo.form.menu.MenuQueryNamesForm; 
 | 
import com.moral.api.pojo.form.menu.MenuUpdateForm; 
 | 
import com.moral.api.service.GroupService; 
 | 
import com.moral.api.service.MenuService; 
 | 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 
 | 
import com.moral.api.util.CompareFieldUtils; 
 | 
import com.moral.api.util.LogUtils; 
 | 
import com.moral.constant.Constants; 
 | 
import com.moral.constant.ResponseCodeEnum; 
 | 
import com.moral.pojo.CompareFieldResult; 
 | 
import org.springframework.beans.factory.annotation.Autowired; 
 | 
import org.springframework.stereotype.Service; 
 | 
import org.springframework.transaction.annotation.Transactional; 
 | 
import org.springframework.util.ObjectUtils; 
 | 
  
 | 
import java.util.ArrayList; 
 | 
import java.util.HashMap; 
 | 
import java.util.List; 
 | 
import java.util.Map; 
 | 
import java.util.function.Predicate; 
 | 
  
 | 
/** 
 | 
 * <p> 
 | 
 * 前台菜单 服务实现类 
 | 
 * </p> 
 | 
 * 
 | 
 * @author moral 
 | 
 * @since 2021-03-09 
 | 
 */ 
 | 
@Service 
 | 
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService { 
 | 
  
 | 
    @Autowired 
 | 
    MenuMapper menuMapper; 
 | 
    @Autowired 
 | 
    GroupService groupService; 
 | 
    @Autowired 
 | 
    GroupMenuMapper groupMenuMapper; 
 | 
  
 | 
    @Override 
 | 
    public MenuQueryDTO queryAllMenus() { 
 | 
        //创建返回对象 
 | 
        MenuQueryDTO dto = new MenuQueryDTO(); 
 | 
        //获取所有菜单 
 | 
        QueryWrapper wrapper = new QueryWrapper(); 
 | 
        wrapper.eq("is_delete", Constants.NOT_DELETE); 
 | 
        List<Menu> menus = menuMapper.selectList(wrapper); 
 | 
        //组装成父子结构 
 | 
        combinationParentChildrenMenus(menus); 
 | 
        //转换菜单为DTO 
 | 
        List<MenuDTO> dtos = new ArrayList<>(); 
 | 
        for (Menu menu : menus) { 
 | 
            MenuDTO menuDTO = new MenuDTO(); 
 | 
            menuDTO.setMenu(menu); 
 | 
            dtos.add(menuDTO); 
 | 
        } 
 | 
        dto.setDtos(dtos); 
 | 
        dto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 
 | 
        dto.setMsg(ResponseCodeEnum.SUCCESS.getMsg()); 
 | 
        return dto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public MenuQueryDTO queryAdminGroupMenusByOrganizationId(Integer organizationId) { 
 | 
        //创建返回对象 
 | 
        MenuQueryDTO dto = new MenuQueryDTO(); 
 | 
        //查询组织admin角色 
 | 
        Group group = groupService.queryAdminGroupByOrganizationId(organizationId); 
 | 
        if (ObjectUtils.isEmpty(group)) {//如果没有角色则证明组织还没有账号 
 | 
            dto.setCode(ResponseCodeEnum.ORGANIZATION_USER_NOT_EXIST.getCode()); 
 | 
            dto.setMsg(ResponseCodeEnum.ORGANIZATION_USER_NOT_EXIST.getMsg()); 
 | 
            return dto; 
 | 
        } 
 | 
        //根据角色查询拥有的所有菜单 
 | 
        List<Menu> ownMenus = menuMapper.getMenusByGroupId(group.getId()); 
 | 
  
 | 
        /*判断每个菜单是否有子菜单,如果有则不传递 
 | 
         * 前端无法解决父菜单选中,子菜单没有全部选中回显问题。由后端处理的代码。*/ 
 | 
        removeMenuWithChildren(ownMenus); 
 | 
  
 | 
        //封装返回结果 
 | 
        List<MenuDTO> dtos = new ArrayList<>(); 
 | 
        for (Menu menu : ownMenus) { 
 | 
            MenuDTO menuDTO = new MenuDTO(); 
 | 
            menuDTO.setMenu(menu); 
 | 
            dtos.add(menuDTO); 
 | 
        } 
 | 
        dto.setDtos(dtos); 
 | 
        dto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 
 | 
        dto.setMsg(ResponseCodeEnum.SUCCESS.getMsg()); 
 | 
        return dto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    @Transactional 
 | 
    public MenuDTO insertMenu(MenuInsertForm form) { 
 | 
        //创建返回对象 
 | 
        MenuDTO dto = new MenuDTO(); 
 | 
        //取参 
 | 
        Menu menu = form.formConvertEntity(); 
 | 
        //检查名字是否重复 
 | 
        Menu existMenu = new Menu(); 
 | 
        existMenu.setName(menu.getName()); 
 | 
        existMenu.setIsDelete(Constants.NOT_DELETE); 
 | 
        QueryWrapper existWrapper = new QueryWrapper(); 
 | 
        existWrapper.setEntity(existMenu); 
 | 
        Menu existMenuResult = menuMapper.selectOne(existWrapper); 
 | 
        if (!ObjectUtils.isEmpty(existMenuResult)) { 
 | 
            dto.setCode(ResponseCodeEnum.MENU_IS_EXIST.getCode()); 
 | 
            dto.setMsg(ResponseCodeEnum.MENU_IS_EXIST.getMsg()); 
 | 
            return dto; 
 | 
        } 
 | 
        //执行插入逻辑 
 | 
        menuMapper.insert(menu); 
 | 
        //插入日志 
 | 
        insertLog(menu); 
 | 
        //封装返回对象 
 | 
        dto.setMenu(menu); 
 | 
        dto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 
 | 
        dto.setMsg(ResponseCodeEnum.SUCCESS.getMsg()); 
 | 
        return dto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    @Transactional 
 | 
    public MenuDTO deleteMenu(MenuDeleteForm form) { 
 | 
        //创建返回对象 
 | 
        MenuDTO dto = new MenuDTO(); 
 | 
        //取参 
 | 
        Integer id = form.getId(); 
 | 
        //查询要删除的菜单 
 | 
        Menu existMenu = menuMapper.selectById(id); 
 | 
        if (ObjectUtils.isEmpty(existMenu)) { 
 | 
            dto.setCode(ResponseCodeEnum.MENU_IS_NULL.getCode()); 
 | 
            dto.setMsg(ResponseCodeEnum.MENU_IS_NULL.getMsg()); 
 | 
            return dto; 
 | 
        } 
 | 
        //删除所有子菜单 
 | 
        List<Integer> childrenIds = getChildrenIdsByParentId(id); 
 | 
        if (!ObjectUtils.isEmpty(childrenIds)) { 
 | 
            UpdateWrapper wrapper = new UpdateWrapper(); 
 | 
            wrapper.in("id", childrenIds); 
 | 
            wrapper.set("is_delete", Constants.DELETE); 
 | 
            menuMapper.update(null, wrapper); 
 | 
        } 
 | 
        //删除菜单 
 | 
        existMenu.setIsDelete(Constants.DELETE); 
 | 
        menuMapper.updateById(existMenu); 
 | 
        //删除角色菜单关系表中对应的菜单 
 | 
        UpdateWrapper deleteGroupMenuWrapper = new UpdateWrapper(); 
 | 
        List<Integer> allMenuIds = new ArrayList<>(); 
 | 
        allMenuIds.add(id); 
 | 
        if (!ObjectUtils.isEmpty(childrenIds)) { 
 | 
            allMenuIds.addAll(childrenIds); 
 | 
        } 
 | 
        deleteGroupMenuWrapper.in("menu_id", allMenuIds); 
 | 
        deleteGroupMenuWrapper.set("is_delete", Constants.DELETE); 
 | 
        groupMenuMapper.update(null, deleteGroupMenuWrapper); 
 | 
        //插入日志 
 | 
        StringBuilder content = new StringBuilder(); 
 | 
        if (existMenu.getParentId().equals(0)) 
 | 
            content.append("删除了父菜单:" + existMenu.getName() + ";"); 
 | 
        else 
 | 
            content.append("删除了子菜单:" + existMenu.getName() + ";"); 
 | 
        if (!ObjectUtils.isEmpty(childrenIds)) { 
 | 
            for (Integer childrenId : childrenIds) { 
 | 
                content.append("及其子菜单:" + menuMapper.selectById(childrenId).getName() + ";"); 
 | 
            } 
 | 
        } 
 | 
        LogUtils.saveOperationForManage(content.toString(), Constants.DELETE_OPERATE_TYPE); 
 | 
        //封装返回对象 
 | 
        dto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 
 | 
        dto.setMsg(ResponseCodeEnum.SUCCESS.getMsg()); 
 | 
        dto.setMenu(existMenu); 
 | 
        return dto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public MenuDTO updateMenu(MenuUpdateForm form) { 
 | 
        //创建返回对象 
 | 
        MenuDTO dto = new MenuDTO(); 
 | 
        //取参 
 | 
        Menu menu = form.formConvertEntity(); 
 | 
        //查找更新前的菜单用于插入日志 
 | 
        QueryWrapper<Menu> oldMenuWrapper = new QueryWrapper<>(); 
 | 
        Menu oldMenu = new Menu(); 
 | 
        oldMenu.setId(menu.getId()); 
 | 
        oldMenu.setIsDelete(Constants.NOT_DELETE); 
 | 
        oldMenuWrapper.setEntity(oldMenu); 
 | 
        oldMenu = menuMapper.selectOne(oldMenuWrapper); 
 | 
        if (ObjectUtils.isEmpty(oldMenu)) { 
 | 
            dto.setCode(ResponseCodeEnum.MENU_IS_NULL.getCode()); 
 | 
            dto.setMsg(ResponseCodeEnum.MENU_IS_NULL.getMsg()); 
 | 
            return dto; 
 | 
        } 
 | 
        //更新 
 | 
        menuMapper.updateById(menu); 
 | 
        //获取更新后的对象 
 | 
        menu = menuMapper.selectById(menu.getId()); 
 | 
        //插入日志 
 | 
        updateLog(oldMenu, menu); 
 | 
        //封装返回对象 
 | 
        dto.setMenu(menu); 
 | 
        dto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 
 | 
        dto.setMsg(ResponseCodeEnum.SUCCESS.getMsg()); 
 | 
        return dto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public MenuQueryNamesDTO queryNames(MenuQueryNamesForm form) { 
 | 
        //创建返回对象 
 | 
        MenuQueryNamesDTO dto = new MenuQueryNamesDTO(); 
 | 
        //取参 
 | 
        Integer id = form.getId(); 
 | 
        String name = form.getName(); 
 | 
        //查询结果 
 | 
        NullFilterWrapper<Menu> wrapper = new NullFilterWrapper<>(); 
 | 
        wrapper.eq("is_delete", Constants.NOT_DELETE); 
 | 
        wrapper.like("name", name); 
 | 
        List<Menu> menus = menuMapper.selectList(wrapper); 
 | 
        //过滤该id对应的所有子菜单 
 | 
        List<Integer> childrenIds = getChildrenIdsByParentId(id);//获取所有子菜单id结合 
 | 
        if (ObjectUtils.isEmpty(childrenIds)) { 
 | 
            menus.removeIf(new Predicate<Menu>() { 
 | 
                @Override 
 | 
                public boolean test(Menu m) { 
 | 
                    if (m.getId().equals(id)) 
 | 
                        return true; 
 | 
                    return false; 
 | 
                } 
 | 
            }); 
 | 
        } else { 
 | 
            menus.removeIf(new Predicate<Menu>() { 
 | 
                @Override 
 | 
                public boolean test(Menu m) { 
 | 
                    if (childrenIds.contains(m.getId()) || m.getId().equals(id)) 
 | 
                        return true; 
 | 
                    return false; 
 | 
                } 
 | 
            }); 
 | 
        } 
 | 
  
 | 
        //封装返回对象 
 | 
        dto.setMenus(menus); 
 | 
        dto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 
 | 
        dto.setMsg(ResponseCodeEnum.SUCCESS.getMsg()); 
 | 
        return dto; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * @Description: 将传来的菜单集合封装成父子结构的集合 
 | 
     * @Param: [menus] 
 | 
     * @return: java.util.List<com.moral.api.entity.Menu> 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/5/13 
 | 
     */ 
 | 
    private void combinationParentChildrenMenus(List<Menu> menus) { 
 | 
        //组合menu父子结构 
 | 
        Map<Integer, Menu> menuMap = new HashMap<>(); 
 | 
        for (Menu menu : menus) { 
 | 
            menuMap.put(menu.getId(), menu); 
 | 
            menu.setChildren(new ArrayList<>());//初始化集合 
 | 
        } 
 | 
        for (Menu menu : menus) { 
 | 
            putMenuToParentMenu(menuMap, menu); 
 | 
        } 
 | 
        //删除非根菜单 
 | 
        menus.removeIf(new Predicate<Menu>() { 
 | 
            @Override 
 | 
            public boolean test(Menu menu) { 
 | 
                if (menu.getParentId().equals(0)) 
 | 
                    return false; 
 | 
                return true; 
 | 
            } 
 | 
        }); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 把传来的menu放到menuMap对应的父菜单中 
 | 
     * @Param: [menuMap, menu] 
 | 
     * @return: void 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/5/6 
 | 
     */ 
 | 
    private void putMenuToParentMenu(Map<Integer, Menu> menuMap, Menu menu) { 
 | 
        Integer parentId = menu.getParentId(); 
 | 
        Menu parentMenu = menuMap.get(parentId); 
 | 
        if (!ObjectUtils.isEmpty(parentMenu)) { 
 | 
            parentMenu.getChildren().add(menu); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 根据菜单的id获取封装好children的menu对象 
 | 
     * @Param: [id] 
 | 
     * @return: com.moral.api.entity.Menu 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/4/26 
 | 
     */ 
 | 
    private Menu getMenuAndChildrenById(Integer id) { 
 | 
        //获取所有菜单 
 | 
        QueryWrapper wrapper = new QueryWrapper(); 
 | 
        wrapper.eq("is_delete", Constants.NOT_DELETE); 
 | 
        List<Menu> menus = menuMapper.selectList(wrapper); 
 | 
        //组合menu父子结构 
 | 
        Map<Integer, Menu> menuMap = new HashMap<>(); 
 | 
        for (Menu menu : menus) { 
 | 
            menuMap.put(menu.getId(), menu); 
 | 
            menu.setChildren(new ArrayList<>());//初始化集合 
 | 
        } 
 | 
        for (Menu menu : menus) { 
 | 
            putMenuToParentMenu(menuMap, menu); 
 | 
        } 
 | 
        Menu menu = menuMap.get(id); 
 | 
        return menu; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 获取该菜单下的所有子菜单id集合 
 | 
     * @Param: [id] 
 | 
     * @return: java.util.List<java.lang.Integer> 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/4/26 
 | 
     */ 
 | 
    private List<Integer> getChildrenIdsByParentId(Integer id) { 
 | 
        Menu parentMenu = getMenuAndChildrenById(id); 
 | 
        List<Integer> childrenIds = null; 
 | 
        if (!ObjectUtils.isEmpty(parentMenu.getChildren())) { 
 | 
            List<Menu> children = parentMenu.getChildren(); 
 | 
            childrenIds = new ArrayList<>(); 
 | 
            for (Menu child : children) { 
 | 
                recursiveAccess(child, childrenIds); 
 | 
            } 
 | 
        } 
 | 
        return childrenIds; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * @Description: 递归获取菜单以及children的id放入集合中 
 | 
     * @Param: [menu, ids] 
 | 
     * @return: void 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/4/26 
 | 
     */ 
 | 
    private void recursiveAccess(Menu menu, List<Integer> ids) { 
 | 
        ids.add(menu.getId()); 
 | 
        List<Menu> children = menu.getChildren(); 
 | 
        if (!ObjectUtils.isEmpty(children)) { 
 | 
            for (Menu child : children) { 
 | 
                recursiveAccess(child, ids); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 移除含有子菜单的菜单 
 | 
     * @Param: [menus] 
 | 
     * @return: java.util.List<com.moral.api.entity.Menu> 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/5/28 
 | 
     */ 
 | 
    private void removeMenuWithChildren(List<Menu> menus) { 
 | 
        //查询所有菜单 
 | 
        QueryWrapper wrapper = new QueryWrapper(); 
 | 
        wrapper.eq("is_delete", Constants.NOT_DELETE); 
 | 
        List<Menu> allMenus = menuMapper.selectList(wrapper); 
 | 
        //组合menu父子结构 
 | 
        Map<Integer, Menu> menuMap = new HashMap<>(); 
 | 
        for (Menu menu : allMenus) { 
 | 
            menuMap.put(menu.getId(), menu); 
 | 
            menu.setChildren(new ArrayList<>());//初始化集合 
 | 
        } 
 | 
        for (Menu menu : allMenus) { 
 | 
            putMenuToParentMenu(menuMap, menu); 
 | 
        } 
 | 
        //移除含有子菜单的菜单 
 | 
        menus.removeIf(new Predicate<Menu>() { 
 | 
            @Override 
 | 
            public boolean test(Menu menu) { 
 | 
                if (ObjectUtils.isEmpty(menuMap.get(menu.getId()).getChildren())) 
 | 
                    return false; 
 | 
                return true; 
 | 
            } 
 | 
        }); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 更新操作插入日志 
 | 
     * @Param: [oldMenu, newMenu] 
 | 
     * @return: void 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/8/24 
 | 
     */ 
 | 
    private void updateLog(Menu oldMenu, Menu newMenu) { 
 | 
        List<CompareFieldResult> compareResult = CompareFieldUtils.compare(Menu.class, oldMenu, newMenu); 
 | 
        for (CompareFieldResult result : compareResult) { 
 | 
            //parentId做特殊处理 
 | 
            if (result.getFieldName().equals("parentId")) { 
 | 
                //父菜单id转为菜单名称 
 | 
                String oldData = result.getOldData(); 
 | 
                String newData = result.getNewData(); 
 | 
  
 | 
                if (!oldData.equals("0")) 
 | 
                    oldData = menuMapper.selectById(Integer.parseInt(oldData)).getName(); 
 | 
                else 
 | 
                    oldData = "null"; 
 | 
  
 | 
                if (!newData.equals("0")) 
 | 
                    newData = menuMapper.selectById(Integer.parseInt(newData)).getName(); 
 | 
                else 
 | 
                    newData = "null"; 
 | 
  
 | 
                result.setNewData(newData); 
 | 
                result.setOldData(oldData); 
 | 
                result.setFieldAnnoName("父菜单"); 
 | 
            } 
 | 
        } 
 | 
        String content = CompareFieldUtils.resultsConvertContent(compareResult, "修改了前台菜单"); 
 | 
        LogUtils.saveOperationForManage(content, Constants.UPDATE_OPERATE_TYPE); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 插入操作插入日志 
 | 
     * @Param: [menu] 
 | 
     * @return: void 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/8/24 
 | 
     */ 
 | 
    private void insertLog(Menu menu) { 
 | 
        StringBuilder content = new StringBuilder(); 
 | 
        //判断插入的是子菜单还是父菜单 
 | 
        if (menu.getParentId().equals(0)) { 
 | 
            content.append("添加了前台父菜单;"); 
 | 
        } else { 
 | 
            content.append("添加了前台子菜单;"); 
 | 
            //根据父菜单id查询菜单名称 
 | 
            Menu parentMenu = menuMapper.selectById(menu.getParentId()); 
 | 
            content.append("父菜单:" + parentMenu.getName() + ";"); 
 | 
        } 
 | 
        content.append("名称:" + menu.getName() + ";"); 
 | 
        if (menu.getUrl() != null) 
 | 
            content.append("url:" + menu.getUrl() + ";"); 
 | 
        content.append("顺序:" + menu.getOrder() + ";"); 
 | 
        LogUtils.saveOperationForManage(content.toString(), Constants.INSERT_OPERATE_TYPE); 
 | 
    } 
 | 
  
 | 
} 
 |