@RequestMapping(value = "batch/delete")
  public String deleteInBatch(
      @RequestParam(value = "ids", required = false) ID[] ids,
      @RequestParam(value = Constants.BACK_URL, required = false) String backURL,
      RedirectAttributes redirectAttributes) {

    if (permissionList != null) {
      permissionList.assertHasDeletePermission();
    }

    // 如果要求不严格 此处可以删除判断 前台已经判断过了
    Searchable searchable =
        Searchable.newSearchable().addSearchFilter("id", SearchOperator.in, ids);
    List<M> mList = baseService.findAllWithNoPageNoSort(searchable);
    for (M m : mList) {
      if (m.isRoot()) {
        redirectAttributes.addFlashAttribute(Constants.ERROR, "您删除的数据中包含根节点,根节点不能删除");
        return redirectToUrl(backURL);
      }
    }

    baseService.deleteSelfAndChild(mList);
    redirectAttributes.addFlashAttribute(Constants.MESSAGE, "删除成功");
    return redirectToUrl(backURL);
  }
  @RequestMapping(value = "{source}/move", method = RequestMethod.POST)
  @PageableDefaults(sort = {"parentIds=asc", "weight=asc"})
  public String move(
      HttpServletRequest request,
      @RequestParam(value = "async", required = false, defaultValue = "false") boolean async,
      @PathVariable("source") M source,
      @RequestParam("target") M target,
      @RequestParam("moveType") String moveType,
      Searchable searchable,
      Model model,
      RedirectAttributes redirectAttributes) {

    if (this.permissionList != null) {
      this.permissionList.assertHasEditPermission();
    }

    if (target.isRoot() && !moveType.equals("inner")) {
      model.addAttribute(Constants.ERROR, "不能移动到根节点之前或之后");
      return showMoveForm(request, async, source, searchable, model);
    }

    baseService.move(source, target, moveType);

    redirectAttributes.addFlashAttribute(Constants.MESSAGE, "移动节点成功");
    return redirectToUrl(viewName("success"));
  }
  private ZTree convertToZtree(M m, boolean open, boolean onlyCheckLeaf) {
    ZTree<ID> zTree = new ZTree<ID>();
    zTree.setId(m.getId());
    zTree.setpId(m.getParentId());
    zTree.setName(m.getName());
    zTree.setIconSkin(m.getIcon());
    zTree.setOpen(open);
    zTree.setRoot(m.isRoot());
    zTree.setIsParent(m.isHasChildren());

    if (onlyCheckLeaf && zTree.isIsParent()) {
      zTree.setNocheck(true);
    } else {
      zTree.setNocheck(false);
    }

    return zTree;
  }
  @RequestMapping(value = "{id}/delete", method = RequestMethod.POST)
  public String deleteSelfAndChildren(
      Model model,
      @ModelAttribute("m") M m,
      BindingResult result,
      RedirectAttributes redirectAttributes) {

    if (permissionList != null) {
      permissionList.assertHasDeletePermission();
    }

    if (m.isRoot()) {
      result.reject("您删除的数据中包含根节点,根节点不能删除");
      return deleteForm(m, model);
    }

    baseService.deleteSelfAndChild(m);
    redirectAttributes.addFlashAttribute(Constants.MESSAGE, "删除成功");
    return redirectToUrl(viewName("success"));
  }