@RequestMapping(
      value = {"", "main"},
      method = RequestMethod.GET)
  public String main() {

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

    return viewName("main");
  }
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public String view(@PathVariable("id") M m, Model model) {
    if (permissionList != null) {
      permissionList.assertHasViewPermission();
    }

    setCommonData(model);
    model.addAttribute("m", m);
    model.addAttribute(Constants.OP_NAME, "查看");
    return viewName("editForm");
  }
  @RequestMapping(value = "{parent}/children", method = RequestMethod.GET)
  @PageableDefaults(sort = {"parentIds=asc", "weight=asc"})
  public String list(
      HttpServletRequest request,
      @PathVariable("parent") M parent,
      Searchable searchable,
      Model model)
      throws UnsupportedEncodingException {

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

    if (parent != null) {
      searchable.addSearchFilter("parentId", SearchOperator.eq, parent.getId());
    }

    model.addAttribute("page", baseService.findAll(searchable));

    return viewName("listChildren");
  }
  @RequestMapping(value = "tree", method = RequestMethod.GET)
  @PageableDefaults(sort = {"parentIds=asc", "weight=asc"})
  public String tree(
      HttpServletRequest request,
      @RequestParam(value = "searchName", required = false) String searchName,
      @RequestParam(value = "async", required = false, defaultValue = "false") boolean async,
      Searchable searchable,
      Model model) {

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

    List<M> models = null;

    if (!StringUtils.isEmpty(searchName)) {
      searchable.addSearchParam("name_like", searchName);
      models = baseService.findAllByName(searchable, null);
      if (!async) { // 非异步 查自己和子子孙孙
        searchable.removeSearchFilter("name_like");
        List<M> children = baseService.findChildren(models, searchable);
        models.removeAll(children);
        models.addAll(children);
      } else { // 异步模式只查自己

      }
    } else {
      if (!async) { // 非异步 查自己和子子孙孙
        models = baseService.findAllWithSort(searchable);
      } else { // 异步模式只查根 和 根一级节点
        models = baseService.findRootAndChild(searchable);
      }
    }

    model.addAttribute("trees", convertToZtreeList(request.getContextPath(), models, async, true));

    return viewName("tree");
  }