|
|
@@ -0,0 +1,347 @@
|
|
|
+package shop.alien.store.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+import shop.alien.entity.result.R;
|
|
|
+import shop.alien.entity.store.LifeSysMenu;
|
|
|
+import shop.alien.mapper.LifeSysMenuMapper;
|
|
|
+import shop.alien.store.service.LifeSysMenuService;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 菜单权限表 服务实现类
|
|
|
+ *
|
|
|
+ * @author system
|
|
|
+ * @since 2025-01-XX
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Transactional
|
|
|
+public class LifeSysMenuServiceImpl implements LifeSysMenuService {
|
|
|
+
|
|
|
+ private final LifeSysMenuMapper lifeSysMenuMapper;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<LifeSysMenu> addMenu(LifeSysMenu menu) {
|
|
|
+ log.info("LifeSysMenuServiceImpl.addMenu?menu={}", menu);
|
|
|
+
|
|
|
+ // 参数校验
|
|
|
+ if (menu == null) {
|
|
|
+ log.warn("新增菜单失败:参数为空");
|
|
|
+ return R.fail("参数不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验必填字段:菜单名称
|
|
|
+ if (!StringUtils.hasText(menu.getMenuName())) {
|
|
|
+ return R.fail("菜单名称不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验必填字段:菜单类型
|
|
|
+ if (!StringUtils.hasText(menu.getMenuType())) {
|
|
|
+ return R.fail("菜单类型不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验菜单名称是否已存在(同一父菜单下不能有重名)
|
|
|
+ QueryWrapper<LifeSysMenu> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("menu_name", menu.getMenuName());
|
|
|
+ queryWrapper.eq("del_flag", "0"); // 未删除的菜单
|
|
|
+ Long parentId = menu.getParentId() != null ? menu.getParentId() : 0L;
|
|
|
+ queryWrapper.eq("parent_id", parentId);
|
|
|
+ LifeSysMenu existingMenu = lifeSysMenuMapper.selectOne(queryWrapper);
|
|
|
+ if (existingMenu != null) {
|
|
|
+ return R.fail("该菜单名称已存在,请更换其他名称");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果指定了父菜单,校验父菜单是否存在
|
|
|
+ if (menu.getParentId() != null && menu.getParentId() != 0) {
|
|
|
+ LifeSysMenu parentMenu = lifeSysMenuMapper.selectById(menu.getParentId());
|
|
|
+ if (parentMenu == null || !"0".equals(parentMenu.getDelFlag())) {
|
|
|
+ return R.fail("父菜单不存在或已被删除");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置默认值
|
|
|
+ if (menu.getParentId() == null) {
|
|
|
+ menu.setParentId(0L);
|
|
|
+ }
|
|
|
+ if (menu.getMenuSort() == null) {
|
|
|
+ menu.setMenuSort(0);
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(menu.getStatus())) {
|
|
|
+ menu.setStatus("0");
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(menu.getVisible())) {
|
|
|
+ menu.setVisible("0");
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(menu.getIsFrame())) {
|
|
|
+ menu.setIsFrame("1");
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(menu.getIsCache())) {
|
|
|
+ menu.setIsCache("0");
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(menu.getIcon())) {
|
|
|
+ menu.setIcon("#");
|
|
|
+ }
|
|
|
+ menu.setDelFlag("0"); // 未删除
|
|
|
+
|
|
|
+ // 保存菜单
|
|
|
+ int result = lifeSysMenuMapper.insert(menu);
|
|
|
+ if (result > 0) {
|
|
|
+ log.info("新增菜单成功,菜单ID={}", menu.getMenuId());
|
|
|
+ return R.data(menu, "新增菜单成功");
|
|
|
+ }
|
|
|
+ return R.fail("新增菜单失败,请稍后重试");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<LifeSysMenu> updateMenu(LifeSysMenu menu) {
|
|
|
+ log.info("LifeSysMenuServiceImpl.updateMenu?menu={}", menu);
|
|
|
+
|
|
|
+ // 参数校验
|
|
|
+ if (menu == null) {
|
|
|
+ log.warn("编辑菜单失败:参数为空");
|
|
|
+ return R.fail("参数不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验必填字段:菜单ID
|
|
|
+ if (menu.getMenuId() == null) {
|
|
|
+ return R.fail("菜单ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验必填字段:菜单名称
|
|
|
+ if (!StringUtils.hasText(menu.getMenuName())) {
|
|
|
+ return R.fail("菜单名称不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询菜单是否存在
|
|
|
+ LifeSysMenu existingMenu = lifeSysMenuMapper.selectById(menu.getMenuId());
|
|
|
+ if (existingMenu == null) {
|
|
|
+ return R.fail("菜单不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已被删除
|
|
|
+ if (!"0".equals(existingMenu.getDelFlag())) {
|
|
|
+ return R.fail("该菜单已被删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果菜单名称有变化,校验新名称是否与其他菜单重复(同一父菜单下不能有重名)
|
|
|
+ if (!menu.getMenuName().equals(existingMenu.getMenuName())) {
|
|
|
+ QueryWrapper<LifeSysMenu> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("menu_name", menu.getMenuName());
|
|
|
+ queryWrapper.eq("del_flag", "0"); // 未删除的菜单
|
|
|
+ queryWrapper.ne("menu_id", menu.getMenuId()); // 排除当前菜单
|
|
|
+ Long parentId = existingMenu.getParentId() != null ? existingMenu.getParentId() : 0L;
|
|
|
+ queryWrapper.eq("parent_id", parentId);
|
|
|
+ LifeSysMenu duplicateMenu = lifeSysMenuMapper.selectOne(queryWrapper);
|
|
|
+ if (duplicateMenu != null) {
|
|
|
+ return R.fail("该菜单名称已存在,请更换其他名称");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新菜单信息
|
|
|
+ existingMenu.setMenuName(menu.getMenuName());
|
|
|
+ existingMenu.setMenuType(menu.getMenuType());
|
|
|
+ existingMenu.setMenuSort(menu.getMenuSort() != null ? menu.getMenuSort() : existingMenu.getMenuSort());
|
|
|
+ existingMenu.setPath(menu.getPath());
|
|
|
+ existingMenu.setComponent(menu.getComponent());
|
|
|
+ existingMenu.setPerms(menu.getPerms());
|
|
|
+ existingMenu.setIcon(menu.getIcon() != null ? menu.getIcon() : existingMenu.getIcon());
|
|
|
+ existingMenu.setStatus(menu.getStatus() != null ? menu.getStatus() : existingMenu.getStatus());
|
|
|
+ existingMenu.setVisible(menu.getVisible() != null ? menu.getVisible() : existingMenu.getVisible());
|
|
|
+ existingMenu.setIsFrame(menu.getIsFrame() != null ? menu.getIsFrame() : existingMenu.getIsFrame());
|
|
|
+ existingMenu.setIsCache(menu.getIsCache() != null ? menu.getIsCache() : existingMenu.getIsCache());
|
|
|
+ existingMenu.setRemark(menu.getRemark());
|
|
|
+
|
|
|
+ // 保存更新
|
|
|
+ int result = lifeSysMenuMapper.updateById(existingMenu);
|
|
|
+ if (result > 0) {
|
|
|
+ log.info("编辑菜单成功,菜单ID={}, 菜单名称={}", existingMenu.getMenuId(), existingMenu.getMenuName());
|
|
|
+ return R.data(existingMenu, "编辑菜单成功");
|
|
|
+ }
|
|
|
+ return R.fail("编辑菜单失败,请稍后重试");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<Boolean> deleteMenu(Long menuId) {
|
|
|
+ log.info("LifeSysMenuServiceImpl.deleteMenu?menuId={}", menuId);
|
|
|
+
|
|
|
+ // 参数校验
|
|
|
+ if (menuId == null) {
|
|
|
+ log.warn("删除菜单失败:菜单ID为空");
|
|
|
+ return R.fail("菜单ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询菜单信息
|
|
|
+ LifeSysMenu menu = lifeSysMenuMapper.selectById(menuId);
|
|
|
+ if (menu == null) {
|
|
|
+ return R.fail("菜单不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已被删除
|
|
|
+ if (!"0".equals(menu.getDelFlag())) {
|
|
|
+ return R.fail("该菜单已被删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有子菜单(未删除的子菜单)
|
|
|
+ QueryWrapper<LifeSysMenu> childQueryWrapper = new QueryWrapper<>();
|
|
|
+ childQueryWrapper.eq("parent_id", menuId);
|
|
|
+ childQueryWrapper.eq("del_flag", "0"); // 未删除的子菜单
|
|
|
+ Integer childCount = lifeSysMenuMapper.selectCount(childQueryWrapper);
|
|
|
+
|
|
|
+ if (childCount != null && childCount > 0) {
|
|
|
+ log.warn("删除菜单失败:该菜单下存在{}个子菜单,不允许删除", childCount);
|
|
|
+ return R.fail("该菜单下存在子菜单,请先删除子菜单后再删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 执行逻辑删除(设置 del_flag = "2")
|
|
|
+ LambdaUpdateWrapper<LifeSysMenu> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ updateWrapper.eq(LifeSysMenu::getMenuId, menuId)
|
|
|
+ .set(LifeSysMenu::getDelFlag, "2");
|
|
|
+
|
|
|
+ int result = lifeSysMenuMapper.update(null, updateWrapper);
|
|
|
+
|
|
|
+ if (result > 0) {
|
|
|
+ log.info("删除菜单成功,菜单ID={}, 菜单名称={}", menuId, menu.getMenuName());
|
|
|
+ return R.success("删除菜单成功");
|
|
|
+ } else {
|
|
|
+ return R.fail("删除菜单失败");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("删除菜单失败,菜单ID={}", menuId, e);
|
|
|
+ return R.fail("删除菜单失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<LifeSysMenu> getMenuById(Long menuId) {
|
|
|
+ log.info("LifeSysMenuServiceImpl.getMenuById?menuId={}", menuId);
|
|
|
+
|
|
|
+ // 参数校验
|
|
|
+ if (menuId == null) {
|
|
|
+ log.warn("查询菜单失败:菜单ID为空");
|
|
|
+ return R.fail("菜单ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询菜单
|
|
|
+ LifeSysMenu menu = lifeSysMenuMapper.selectById(menuId);
|
|
|
+ if (menu == null) {
|
|
|
+ return R.fail("菜单不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已被删除
|
|
|
+ if (!"0".equals(menu.getDelFlag())) {
|
|
|
+ return R.fail("该菜单已被删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ return R.data(menu, "查询成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<List<LifeSysMenu>> getMenuTree() {
|
|
|
+ log.info("LifeSysMenuServiceImpl.getMenuTree");
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 查询所有未删除的菜单
|
|
|
+ QueryWrapper<LifeSysMenu> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("del_flag", "0"); // 只查询未删除的菜单
|
|
|
+ queryWrapper.orderByAsc("menu_sort"); // 按排序值升序排列
|
|
|
+ List<LifeSysMenu> allMenus = lifeSysMenuMapper.selectList(queryWrapper);
|
|
|
+
|
|
|
+ if (allMenus == null || allMenus.isEmpty()) {
|
|
|
+ return R.data(new ArrayList<>(), "查询成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建树形结构
|
|
|
+ List<LifeSysMenu> treeList = buildMenuTree(allMenus);
|
|
|
+
|
|
|
+ log.info("查询菜单树成功,菜单数量={}", allMenus.size());
|
|
|
+ return R.data(treeList, "查询成功");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("查询菜单树失败", e);
|
|
|
+ return R.fail("查询菜单树失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<List<LifeSysMenu>> getMenuListByParentId(Long parentId) {
|
|
|
+ log.info("LifeSysMenuServiceImpl.getMenuListByParentId?parentId={}", parentId);
|
|
|
+
|
|
|
+ try {
|
|
|
+ QueryWrapper<LifeSysMenu> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("del_flag", "0"); // 只查询未删除的菜单
|
|
|
+ if (parentId != null) {
|
|
|
+ queryWrapper.eq("parent_id", parentId);
|
|
|
+ } else {
|
|
|
+ queryWrapper.eq("parent_id", 0);
|
|
|
+ }
|
|
|
+ queryWrapper.orderByAsc("menu_sort"); // 按排序值升序排列
|
|
|
+ List<LifeSysMenu> menuList = lifeSysMenuMapper.selectList(queryWrapper);
|
|
|
+
|
|
|
+ log.info("查询菜单列表成功,父菜单ID={}, 菜单数量={}", parentId, menuList != null ? menuList.size() : 0);
|
|
|
+ return R.data(menuList, "查询成功");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("查询菜单列表失败,父菜单ID={}", parentId, e);
|
|
|
+ return R.fail("查询菜单列表失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建菜单树形结构
|
|
|
+ *
|
|
|
+ * @param flatList 扁平列表
|
|
|
+ * @return 树形结构列表
|
|
|
+ */
|
|
|
+ private List<LifeSysMenu> buildMenuTree(List<LifeSysMenu> flatList) {
|
|
|
+ if (flatList == null || flatList.isEmpty()) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建映射:ID到节点的映射,父ID到子节点列表的映射
|
|
|
+ Map<Long, LifeSysMenu> nodeMap = new HashMap<>();
|
|
|
+ Map<Long, List<LifeSysMenu>> parentChildMap = new HashMap<>();
|
|
|
+ List<LifeSysMenu> result = new ArrayList<>();
|
|
|
+
|
|
|
+ // 第一步:建立映射关系
|
|
|
+ for (LifeSysMenu menu : flatList) {
|
|
|
+ Long menuId = menu.getMenuId();
|
|
|
+ Long parentId = menu.getParentId() != null ? menu.getParentId() : 0L;
|
|
|
+
|
|
|
+ // 存入节点映射
|
|
|
+ nodeMap.put(menuId, menu);
|
|
|
+
|
|
|
+ // 如果是根节点(parentId为0或null),直接添加到结果
|
|
|
+ if (parentId == null || parentId == 0) {
|
|
|
+ result.add(menu);
|
|
|
+ } else {
|
|
|
+ // 否则,记录父子关系
|
|
|
+ parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(menu);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 第二步:建立父子关系
|
|
|
+ for (LifeSysMenu menu : nodeMap.values()) {
|
|
|
+ Long menuId = menu.getMenuId();
|
|
|
+ if (parentChildMap.containsKey(menuId)) {
|
|
|
+ // 对子节点按排序值排序
|
|
|
+ List<LifeSysMenu> children = parentChildMap.get(menuId);
|
|
|
+ children.sort(Comparator.comparing(LifeSysMenu::getMenuSort, Comparator.nullsLast(Integer::compareTo)));
|
|
|
+ menu.setChildren(children);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对根节点按排序值排序
|
|
|
+ result.sort(Comparator.comparing(LifeSysMenu::getMenuSort, Comparator.nullsLast(Integer::compareTo)));
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|