class StoreMenuServiceImpl extends ServiceImpl<StoreMenuMapper, StoreMenu> implements StoreMenuService {
    /**
     * 菜单角色
     */
    @Autowired
    private StoreMenuRoleService storeMenuRoleService;

    @Autowired
    private Cache cache;

    /**
     * 店员
     */
    @Autowired
    private ClerkService clerkService;



    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteIds(List<String> ids) {
        QueryWrapper<StoreMenuRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("menu_id", ids);
        //如果已有角色绑定菜单，则不能直接删除
        if (storeMenuRoleService.count(queryWrapper) > 0) {
            throw new ServiceException(ResultCode.PERMISSION_MENU_ROLE_ERROR);
        }
        cache.vagueDel(CachePrefix.PERMISSION_LIST.getPrefix(UserEnums.STORE));
        cache.vagueDel(CachePrefix.STORE_USER_MENU.getPrefix());
        this.removeByIds(ids);
    }


    @Override
    public List<StoreMenuVO> findUserTree() {
        AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
        if (Boolean.TRUE.equals(authUser.getIsSuper())) {
            return this.tree();
        }
        //获取当前登录用户的店员信息
        Clerk clerk = clerkService.getOne(new LambdaQueryWrapper<Clerk>().eq(Clerk::getMemberId, authUser.getId()));
        //获取当前店员角色的菜单列表
        List<StoreMenu> userMenus = this.findUserList(authUser.getId(), clerk.getId());
        return this.tree(userMenus);
    }

    @Override
    public List<StoreMenu> findUserList(String userId, String clerkId) {<FILL_FUNCTION_BODY>}

    /**
     * 添加更新菜单
     *
     * @param storeMenu 菜单数据
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdateMenu(StoreMenu storeMenu) {
        if (CharSequenceUtil.isNotEmpty(storeMenu.getId())) {
            cache.vagueDel(CachePrefix.PERMISSION_LIST.getPrefix(UserEnums.STORE));
            cache.vagueDel(CachePrefix.STORE_USER_MENU.getPrefix());
        }
        return this.saveOrUpdate(storeMenu);
    }

    @Override
    public List<StoreUserMenuVO> getUserRoleMenu(String clerkId) {
        return this.baseMapper.getUserRoleMenu(clerkId);
    }

    @Override
    public List<StoreMenu> findByRoleIds(String roleId) {
        QueryWrapper<StoreMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId);
        return this.list(queryWrapper);
    }

    @Override
    public List<StoreMenu> searchList(MenuSearchParams menuSearchParams) {
        //title 需要特殊处理
        String title = null;
        if (CharSequenceUtil.isNotEmpty(menuSearchParams.getTitle())) {
            title = menuSearchParams.getTitle();
            menuSearchParams.setTitle(null);
        }
        QueryWrapper<StoreMenu> queryWrapper = PageUtil.initWrapper(menuSearchParams, new SearchVO());
        if (CharSequenceUtil.isNotEmpty(title)) {
            queryWrapper.like("title", title);
        }
        queryWrapper.orderByDesc("sort_order");
        return this.baseMapper.selectList(queryWrapper);
    }


    @Override
    public List<StoreMenuVO> tree() {
        try {
            List<StoreMenu> menus = this.list();
            return tree(menus);
        } catch (Exception e) {
            log.error("菜单树错误", e);
        }
        return Collections.emptyList();
    }

    /**
     * 传入自定义菜单集合
     *
     * @param menus 自定义菜单集合
     * @return 修改后的自定义菜单集合
     */
    private List<StoreMenuVO> tree(List<StoreMenu> menus) {
        List<StoreMenuVO> tree = new ArrayList<>();
        menus.forEach(item -> {
            if (item.getLevel() == 0) {
                StoreMenuVO treeItem = new StoreMenuVO(item);
                initChild(treeItem, menus);
                tree.add(treeItem);
            }
        });
        //对一级菜单排序
        tree.sort(Comparator.comparing(StoreMenu::getSortOrder));
        return tree;
    }

    /**
     * 递归初始化子树
     *
     * @param tree  树结构
     * @param menus 数据库对象集合
     */
    private void initChild(StoreMenuVO tree, List<StoreMenu> menus) {
        if (menus == null) {
            return;
        }
        menus.stream()
                .filter(item -> (item.getParentId().equals(tree.getId())))
                .forEach(child -> {
                    StoreMenuVO childTree = new StoreMenuVO(child);
                    initChild(childTree, menus);
                    tree.getChildren().add(childTree);
                });
    }

}

        String cacheKey = CachePrefix.STORE_USER_MENU.getPrefix() + userId;
        List<StoreMenu> menuList = (List<StoreMenu>) cache.get(cacheKey);
        if (menuList == null || menuList.isEmpty()) {
            menuList = this.baseMapper.findByUserId(clerkId);
            cache.put(cacheKey, menuList);
        }
        return menuList;
    
<no_super_class>