From a54a414b6b6d566aaa79d228313ea1bbede74f1f Mon Sep 17 00:00:00 2001
From: zhongrj <646384940@qq.com>
Date: Mon, 06 May 2024 18:26:57 +0800
Subject: [PATCH] 加入 controller

---
 blade-auth/src/main/java/org/springblade/system/controller/RoleController.java          |  151 +++
 blade-auth/src/main/java/org/springblade/system/controller/TopMenuController.java       |  138 +++
 blade-auth/src/main/java/org/springblade/system/controller/DeptController.java          |  160 ++++
 blade-auth/src/main/java/org/springblade/system/controller/DataScopeController.java     |  122 +++
 blade-auth/src/main/java/org/springblade/auth/config/SecurityConfiguration.java         |    6 
 blade-auth/src/main/java/org/springblade/system/controller/TenantController.java        |  233 +++++
 blade-auth/src/main/java/org/springblade/system/controller/MenuController.java          |  268 ++++++
 blade-auth/src/main/java/org/springblade/system/controller/RegionController.java        |  201 +++++
 blade-auth/src/main/java/org/springblade/system/controller/ApiScopeController.java      |  104 ++
 blade-auth/src/main/java/org/springblade/system/controller/AuthClientController.java    |  101 ++
 blade-auth/src/main/java/org/springblade/system/controller/DictBizController.java       |  161 ++++
 blade-auth/src/main/java/org/springblade/system/controller/ParamController.java         |   90 ++
 blade-auth/src/main/java/org/springblade/system/controller/SearchController.java        |   98 ++
 blade-auth/src/main/java/org/springblade/system/controller/DictController.java          |  179 ++++
 blade-auth/src/main/java/org/springblade/system/controller/PostController.java          |  148 +++
 blade-auth/src/main/java/org/springblade/system/controller/TenantPackageController.java |  133 +++
 16 files changed, 2,291 insertions(+), 2 deletions(-)

diff --git a/blade-auth/src/main/java/org/springblade/auth/config/SecurityConfiguration.java b/blade-auth/src/main/java/org/springblade/auth/config/SecurityConfiguration.java
index 44440ef..ec68cc2 100644
--- a/blade-auth/src/main/java/org/springblade/auth/config/SecurityConfiguration.java
+++ b/blade-auth/src/main/java/org/springblade/auth/config/SecurityConfiguration.java
@@ -21,6 +21,7 @@
 import org.springblade.auth.support.BladePasswordEncoderFactories;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.builders.WebSecurity;
@@ -34,6 +35,7 @@
  */
 @Configuration(proxyBeanMethods = false)
 @AllArgsConstructor
+@Order(1)
 public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 
 	@Bean
@@ -51,8 +53,8 @@
 	@Override
 	@SneakyThrows
 	protected void configure(HttpSecurity http) {
-		http.headers().frameOptions().disable();
-		http.httpBasic().and().csrf().disable();
+//		http.headers().frameOptions().disable();
+//		http.httpBasic().and().csrf().disable();
 		http.formLogin().loginPage("/oauth/login").loginProcessingUrl("/oauth/form");
 	}
 
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/ApiScopeController.java b/blade-auth/src/main/java/org/springblade/system/controller/ApiScopeController.java
new file mode 100644
index 0000000..4e3f8fe
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/ApiScopeController.java
@@ -0,0 +1,104 @@
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.ApiScope;
+import org.springblade.system.service.IApiScopeService;
+import org.springblade.system.vo.ApiScopeVO;
+import org.springblade.system.wrapper.ApiScopeWrapper;
+import org.springframework.web.bind.annotation.*;
+import javax.validation.Valid;
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+
+/**
+ * 接口权限控制器
+ *
+ * @author BladeX
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("api-scope")
+@Api(value = "接口权限", tags = "接口权限")
+public class ApiScopeController {
+
+	private final IApiScopeService apiScopeService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入dataScope")
+	public R<ApiScope> detail(ApiScope dataScope) {
+		ApiScope detail = apiScopeService.getOne(Condition.getQueryWrapper(dataScope));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入dataScope")
+	public R<IPage<ApiScopeVO>> list(ApiScope dataScope, Query query) {
+		IPage<ApiScope> pages = apiScopeService.page(Condition.getPage(query), Condition.getQueryWrapper(dataScope));
+		return R.data(ApiScopeWrapper.build().pageVO(pages));
+	}
+
+	/**
+	 * 新增
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "新增", notes = "传入dataScope")
+	public R save(@Valid @RequestBody ApiScope dataScope) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(apiScopeService.save(dataScope));
+	}
+
+	/**
+	 * 修改
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "修改", notes = "传入dataScope")
+	public R update(@Valid @RequestBody ApiScope dataScope) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(apiScopeService.updateById(dataScope));
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "新增或修改", notes = "传入dataScope")
+	public R submit(@Valid @RequestBody ApiScope dataScope) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(apiScopeService.saveOrUpdate(dataScope));
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(apiScopeService.deleteLogic(Func.toLongList(ids)));
+	}
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/AuthClientController.java b/blade-auth/src/main/java/org/springblade/system/controller/AuthClientController.java
new file mode 100644
index 0000000..80dfc1f
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/AuthClientController.java
@@ -0,0 +1,101 @@
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.AuthClient;
+import org.springblade.system.service.IAuthClientService;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+import javax.validation.Valid;
+
+/**
+ *  应用管理控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/client")
+@ApiIgnore
+@Api(value = "应用管理", tags = "接口")
+//@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+public class AuthClientController{
+
+	private final IAuthClientService clientService;
+
+	/**
+	* 详情
+	*/
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入client")
+	public R<AuthClient> detail(AuthClient authClient) {
+		AuthClient detail = clientService.getOne(Condition.getQueryWrapper(authClient));
+		return R.data(detail);
+	}
+
+	/**
+	* 分页
+	*/
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入client")
+	public R<IPage<AuthClient>> list(AuthClient authClient, Query query) {
+		IPage<AuthClient> pages = clientService.page(Condition.getPage(query), Condition.getQueryWrapper(authClient));
+		return R.data(pages);
+	}
+
+	/**
+	* 新增
+	*/
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "新增", notes = "传入client")
+	public R save(@Valid @RequestBody AuthClient authClient) {
+		return R.status(clientService.save(authClient));
+	}
+
+	/**
+	* 修改
+	*/
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "修改", notes = "传入client")
+	public R update(@Valid @RequestBody AuthClient authClient) {
+		return R.status(clientService.updateById(authClient));
+	}
+
+	/**
+	* 新增或修改
+	*/
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "新增或修改", notes = "传入client")
+	public R submit(@Valid @RequestBody AuthClient authClient) {
+		return R.status(clientService.saveOrUpdate(authClient));
+	}
+
+
+	/**
+	* 删除
+	*/
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(clientService.deleteLogic(Func.toLongList(ids)));
+	}
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/DataScopeController.java b/blade-auth/src/main/java/org/springblade/system/controller/DataScopeController.java
new file mode 100644
index 0000000..030b684
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/DataScopeController.java
@@ -0,0 +1,122 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.DataScope;
+import org.springblade.system.service.IDataScopeService;
+import org.springblade.system.vo.DataScopeVO;
+import org.springblade.system.wrapper.DataScopeWrapper;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+
+/**
+ * 数据权限控制器
+ *
+ * @author BladeX
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("data-scope")
+@Api(value = "数据权限", tags = "数据权限")
+public class DataScopeController {
+
+	private final IDataScopeService dataScopeService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入dataScope")
+	public R<DataScope> detail(DataScope dataScope) {
+		DataScope detail = dataScopeService.getOne(Condition.getQueryWrapper(dataScope));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入dataScope")
+	public R<IPage<DataScopeVO>> list(DataScope dataScope, Query query) {
+		IPage<DataScope> pages = dataScopeService.page(Condition.getPage(query), Condition.getQueryWrapper(dataScope));
+		return R.data(DataScopeWrapper.build().pageVO(pages));
+	}
+
+	/**
+	 * 新增
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "新增", notes = "传入dataScope")
+	public R save(@Valid @RequestBody DataScope dataScope) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(dataScopeService.save(dataScope));
+	}
+
+	/**
+	 * 修改
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "修改", notes = "传入dataScope")
+	public R update(@Valid @RequestBody DataScope dataScope) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(dataScopeService.updateById(dataScope));
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "新增或修改", notes = "传入dataScope")
+	public R submit(@Valid @RequestBody DataScope dataScope) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(dataScopeService.saveOrUpdate(dataScope));
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(dataScopeService.deleteLogic(Func.toLongList(ids)));
+	}
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/DeptController.java b/blade-auth/src/main/java/org/springblade/system/controller/DeptController.java
new file mode 100644
index 0000000..9daecd8
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/DeptController.java
@@ -0,0 +1,160 @@
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.BladeConstant;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springblade.core.tool.support.Kv;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.cache.DictCache;
+import org.springblade.system.entity.Dept;
+import org.springblade.system.enums.DictEnum;
+import org.springblade.system.service.IDeptService;
+import org.springblade.system.user.cache.UserCache;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.vo.DeptVO;
+import org.springblade.system.wrapper.DeptWrapper;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/dept")
+@Api(value = "部门", tags = "部门")
+//@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+public class DeptController{
+
+	private final IDeptService deptService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入dept")
+	public R<DeptVO> detail(Dept dept) {
+		Dept detail = deptService.getOne(Condition.getQueryWrapper(dept));
+		return R.data(DeptWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 列表
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "deptName", value = "部门名称", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "fullName", value = "部门全称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "列表", notes = "传入dept")
+	public R<List<DeptVO>> list(@ApiIgnore @RequestParam Map<String, Object> dept, BladeUser bladeUser) {
+		QueryWrapper<Dept> queryWrapper = Condition.getQueryWrapper(dept, Dept.class);
+		List<Dept> list = deptService.list((!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(Dept::getTenantId, bladeUser.getTenantId()) : queryWrapper);
+		return R.data(DeptWrapper.build().listNodeVO(list));
+	}
+
+	/**
+	 * 懒加载列表
+	 */
+	@GetMapping("/lazy-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "deptName", value = "部门名称", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "fullName", value = "部门全称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "懒加载列表", notes = "传入dept")
+	public R<List<DeptVO>> lazyList(@ApiIgnore @RequestParam Map<String, Object> dept, Long parentId, BladeUser bladeUser) {
+		List<DeptVO> list = deptService.lazyList(bladeUser.getTenantId(), parentId, dept);
+		return R.data(DeptWrapper.build().listNodeLazyVO(list));
+	}
+
+	/**
+	 * 获取部门树形结构
+	 *
+	 * @return
+	 */
+	@GetMapping("/tree")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<DeptVO>> tree(String tenantId, BladeUser bladeUser) {
+		List<DeptVO> tree = deptService.tree(Func.toStrWithEmpty(tenantId, bladeUser.getTenantId()));
+		return R.data(tree);
+	}
+
+	/**
+	 * 懒加载获取部门树形结构
+	 */
+	@GetMapping("/lazy-tree")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "懒加载树形结构", notes = "树形结构")
+	public R<List<DeptVO>> lazyTree(String tenantId, Long parentId, BladeUser bladeUser) {
+		List<DeptVO> tree = deptService.lazyTree(Func.toStrWithEmpty(tenantId, bladeUser.getTenantId()), parentId);
+		return R.data(tree);
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入dept")
+	public R submit(@Valid @RequestBody Dept dept) {
+		if (deptService.submit(dept)) {
+			CacheUtil.clear(SYS_CACHE);
+			// 返回懒加载树更新节点所需字段
+			Kv kv = Kv.create().set("id", String.valueOf(dept.getId())).set("tenantId", dept.getTenantId())
+				.set("deptCategoryName", DictCache.getValue(DictEnum.ORG_CATEGORY, dept.getDeptCategory()));
+			return R.data(kv);
+		}
+		return R.fail("操作失败");
+	}
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(SYS_CACHE);
+		return R.status(deptService.removeDept(ids));
+	}
+
+	/**
+	 * 下拉数据源
+	 */
+//	@PreAuth(AuthConstant.PERMIT_ALL)
+	@GetMapping("/select")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "下拉数据源", notes = "传入id集合")
+	public R<List<Dept>> select(Long userId, String deptId) {
+		if (Func.isNotEmpty(userId)) {
+			User user = UserCache.getUser(userId);
+			deptId = user.getDeptId();
+		}
+		List<Dept> list = deptService.list(Wrappers.<Dept>lambdaQuery().in(Dept::getId, Func.toLongList(deptId)));
+		return R.data(list);
+	}
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/DictBizController.java b/blade-auth/src/main/java/org/springblade/system/controller/DictBizController.java
new file mode 100644
index 0000000..7c64724
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/DictBizController.java
@@ -0,0 +1,161 @@
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.system.entity.DictBiz;
+import org.springblade.system.service.IDictBizService;
+import org.springblade.system.vo.DictBizVO;
+import org.springblade.system.wrapper.DictBizWrapper;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+
+import static org.springblade.core.cache.constant.CacheConstant.DICT_CACHE;
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/dict-biz")
+@Api(value = "业务字典", tags = "业务字典")
+public class DictBizController {
+
+	private final IDictBizService dictService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入dict")
+	public R<DictBizVO> detail(DictBiz dict) {
+		DictBiz detail = dictService.getOne(Condition.getQueryWrapper(dict));
+		return R.data(DictBizWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 列表
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "字典编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "dictValue", value = "字典名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "列表", notes = "传入dict")
+	public R<List<DictBizVO>> list(@ApiIgnore @RequestParam Map<String, Object> dict) {
+		List<DictBiz> list = dictService.list(Condition.getQueryWrapper(dict, DictBiz.class).lambda().orderByAsc(DictBiz::getSort));
+		return R.data(DictBizWrapper.build().listNodeVO(list));
+	}
+
+	/**
+	 * 顶级列表
+	 */
+	@GetMapping("/parent-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "字典编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "dictValue", value = "字典名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "列表", notes = "传入dict")
+	public R<IPage<DictBizVO>> parentList(@ApiIgnore @RequestParam Map<String, Object> dict, Query query) {
+		return R.data(dictService.parentList(dict, query));
+	}
+
+	/**
+	 * 子列表
+	 */
+	@GetMapping("/child-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "字典编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "dictValue", value = "字典名称", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "parentId", value = "字典名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "列表", notes = "传入dict")
+	public R<List<DictBizVO>> childList(@ApiIgnore @RequestParam Map<String, Object> dict, @RequestParam(required = false, defaultValue = "-1") Long parentId) {
+		return R.data(dictService.childList(dict, parentId));
+	}
+
+	/**
+	 * 获取字典树形结构
+	 */
+	@GetMapping("/tree")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<DictBizVO>> tree() {
+		List<DictBizVO> tree = dictService.tree();
+		return R.data(tree);
+	}
+
+	/**
+	 * 获取字典树形结构
+	 */
+	@GetMapping("/parent-tree")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<DictBizVO>> parentTree() {
+		List<DictBizVO> tree = dictService.parentTree();
+		return R.data(tree);
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入dict")
+	public R submit(@Valid @RequestBody DictBiz dict) {
+		CacheUtil.clear(DICT_CACHE);
+		return R.status(dictService.submit(dict));
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(DICT_CACHE);
+		return R.status(dictService.removeDict(ids));
+	}
+
+	/**
+	 * 获取字典
+	 */
+	@GetMapping("/dictionary")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "获取字典", notes = "获取字典")
+	public R<List<DictBiz>> dictionary(String code) {
+		List<DictBiz> tree = dictService.getList(code);
+		return R.data(tree);
+	}
+
+	/**
+	 * 获取字典树
+	 */
+	@GetMapping("/dictionary-tree")
+	@ApiOperationSupport(order = 9)
+	@ApiOperation(value = "获取字典树", notes = "获取字典树")
+	public R<List<DictBizVO>> dictionaryTree(String code) {
+		List<DictBiz> tree = dictService.getList(code);
+		return R.data(DictBizWrapper.build().listNodeVO(tree));
+	}
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/DictController.java b/blade-auth/src/main/java/org/springblade/system/controller/DictController.java
new file mode 100644
index 0000000..710d03e
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/DictController.java
@@ -0,0 +1,179 @@
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.StringPool;
+import org.springblade.system.entity.Dict;
+import org.springblade.system.service.IDictService;
+import org.springblade.system.vo.DictVO;
+import org.springblade.system.wrapper.DictWrapper;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+
+import static org.springblade.core.cache.constant.CacheConstant.DICT_CACHE;
+
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/dict")
+@Api(value = "字典", tags = "字典")
+public class DictController{
+
+	private final IDictService dictService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入dict")
+	public R<DictVO> detail(Dict dict) {
+		Dict detail = dictService.getOne(Condition.getQueryWrapper(dict));
+		return R.data(DictWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 列表
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "字典编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "dictValue", value = "字典名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "列表", notes = "传入dict")
+	public R<List<DictVO>> list(@ApiIgnore @RequestParam Map<String, Object> dict) {
+		List<Dict> list = dictService.list(Condition.getQueryWrapper(dict, Dict.class).lambda().orderByAsc(Dict::getSort));
+		DictWrapper dictWrapper = new DictWrapper();
+		return R.data(dictWrapper.listNodeVO(list));
+	}
+
+	/**
+	 * 顶级列表
+	 */
+	@GetMapping("/parent-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "字典编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "dictValue", value = "字典名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "列表", notes = "传入dict")
+	public R<IPage<DictVO>> parentList(@ApiIgnore @RequestParam Map<String, Object> dict, Query query) {
+		return R.data(dictService.parentList(dict, query));
+	}
+
+	/**
+	 * 子列表
+	 */
+	@GetMapping("/child-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "字典编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "dictValue", value = "字典名称", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "parentId", value = "字典名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "列表", notes = "传入dict")
+	public R<List<DictVO>> childList(@ApiIgnore @RequestParam Map<String, Object> dict, @RequestParam(required = false, defaultValue = "-1") Long parentId) {
+		return R.data(dictService.childList(dict, parentId));
+	}
+
+	/**
+	 * 获取字典树形结构
+	 */
+	@GetMapping("/tree")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<DictVO>> tree() {
+		List<DictVO> tree = dictService.tree();
+		return R.data(tree);
+	}
+
+	/**
+	 * 获取字典树形结构
+	 */
+	@GetMapping("/parent-tree")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<DictVO>> parentTree() {
+		List<DictVO> tree = dictService.parentTree();
+		return R.data(tree);
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入dict")
+	public R submit(@Valid @RequestBody Dict dict) {
+		CacheUtil.clear(DICT_CACHE, Boolean.FALSE);
+		return R.status(dictService.submit(dict));
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(DICT_CACHE, Boolean.FALSE);
+		return R.status(dictService.removeDict(ids));
+	}
+
+	/**
+	 * 获取字典
+	 */
+	@GetMapping("/dictionary")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "获取字典", notes = "获取字典")
+	public R<List<Dict>> dictionary(String code) {
+		List<Dict> tree = dictService.getList(code);
+		return R.data(tree);
+	}
+
+	/**
+	 * 获取字典树
+	 */
+	@GetMapping("/dictionary-tree")
+	@ApiOperationSupport(order = 9)
+	@ApiOperation(value = "获取字典树", notes = "获取字典树")
+	public R<List<DictVO>> dictionaryTree(String code) {
+		List<Dict> tree = dictService.getList(code);
+		return R.data(DictWrapper.build().listNodeVO(tree));
+	}
+
+	/**
+	 * 字典键值列表
+	 */
+	@GetMapping("/select")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "字典键值列表", notes = "字典键值列表")
+	public R<List<Dict>> select() {
+		List<Dict> list = dictService.list(Wrappers.<Dict>query().lambda().eq(Dict::getParentId, CommonConstant.TOP_PARENT_ID));
+		list.forEach(dict -> dict.setDictValue(dict.getCode() + StringPool.COLON + StringPool.SPACE + dict.getDictValue()));
+		return R.data(list);
+	}
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/MenuController.java b/blade-auth/src/main/java/org/springblade/system/controller/MenuController.java
new file mode 100644
index 0000000..6b70b9c
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/MenuController.java
@@ -0,0 +1,268 @@
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springblade.core.tool.node.TreeNode;
+import org.springblade.core.tool.support.Kv;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.Menu;
+import org.springblade.system.entity.TopMenu;
+import org.springblade.system.service.IMenuService;
+import org.springblade.system.service.ITopMenuService;
+import org.springblade.system.vo.CheckedTreeVO;
+import org.springblade.system.vo.GrantTreeVO;
+import org.springblade.system.vo.MenuVO;
+import org.springblade.system.wrapper.MenuWrapper;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+
+import static org.springblade.core.cache.constant.CacheConstant.MENU_CACHE;
+
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/menu")
+@Api(value = "菜单", tags = "菜单")
+public class MenuController {
+
+	private final IMenuService menuService;
+	private final ITopMenuService topMenuService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入menu")
+	public R<MenuVO> detail(Menu menu) {
+		Menu detail = menuService.getOne(Condition.getQueryWrapper(menu));
+		return R.data(MenuWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 列表
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "菜单编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "name", value = "菜单名称", paramType = "query", dataType = "string")
+	})
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "列表", notes = "传入menu")
+	public R<List<MenuVO>> list(@ApiIgnore @RequestParam Map<String, Object> menu) {
+		List<Menu> list = menuService.list(Condition.getQueryWrapper(menu, Menu.class).lambda().orderByAsc(Menu::getSort));
+		return R.data(MenuWrapper.build().listNodeVO(list));
+	}
+
+	/**
+	 * 懒加载列表
+	 */
+	@GetMapping("/lazy-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "菜单编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "name", value = "菜单名称", paramType = "query", dataType = "string")
+	})
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "懒加载列表", notes = "传入menu")
+	public R<List<MenuVO>> lazyList(Long parentId, @ApiIgnore @RequestParam Map<String, Object> menu) {
+		List<MenuVO> list = menuService.lazyList(parentId, menu);
+		return R.data(MenuWrapper.build().listNodeLazyVO(list));
+	}
+
+	/**
+	 * 菜单列表
+	 */
+	@GetMapping("/menu-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "菜单编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "name", value = "菜单名称", paramType = "query", dataType = "string")
+	})
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "菜单列表", notes = "传入menu")
+	public R<List<MenuVO>> menuList(@ApiIgnore @RequestParam Map<String, Object> menu) {
+		List<Menu> list = menuService.list(Condition.getQueryWrapper(menu, Menu.class).lambda().eq(Menu::getCategory, 1).orderByAsc(Menu::getSort));
+		return R.data(MenuWrapper.build().listNodeVO(list));
+	}
+
+	/**
+	 * 懒加载菜单列表
+	 */
+	@GetMapping("/lazy-menu-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "菜单编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "name", value = "菜单名称", paramType = "query", dataType = "string")
+	})
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "懒加载菜单列表", notes = "传入menu")
+	public R<List<MenuVO>> lazyMenuList(Long parentId, @ApiIgnore @RequestParam Map<String, Object> menu) {
+		List<MenuVO> list = menuService.lazyMenuList(parentId, menu);
+		return R.data(MenuWrapper.build().listNodeLazyVO(list));
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入menu")
+	public R submit(@Valid @RequestBody Menu menu) {
+		if (menuService.submit(menu)) {
+			CacheUtil.clear(MENU_CACHE);
+			CacheUtil.clear(MENU_CACHE, Boolean.FALSE);
+			// 返回懒加载树更新节点所需字段
+			Kv kv = Kv.create().set("id", String.valueOf(menu.getId()));
+			return R.data(kv);
+		}
+		return R.fail("操作失败");
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(MENU_CACHE);
+		CacheUtil.clear(MENU_CACHE, Boolean.FALSE);
+		return R.status(menuService.removeMenu(ids));
+	}
+
+	/**
+	 * 前端菜单数据
+	 */
+	@GetMapping("/routes")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "前端菜单数据", notes = "前端菜单数据")
+	public R<List<MenuVO>> routes(BladeUser user, Long topMenuId) {
+		List<MenuVO> list = menuService.routes((user == null) ? null : user.getRoleId(), topMenuId);
+		return R.data(list);
+	}
+
+	/**
+	 * 前端按钮数据
+	 */
+	@GetMapping("/buttons")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "前端按钮数据", notes = "前端按钮数据")
+	public R<List<MenuVO>> buttons(BladeUser user) {
+		List<MenuVO> list = menuService.buttons(user.getRoleId());
+		return R.data(list);
+	}
+
+	/**
+	 * 获取菜单树形结构
+	 */
+	@GetMapping("/tree")
+	@ApiOperationSupport(order = 11)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<TreeNode>> tree() {
+		List<TreeNode> tree = menuService.tree();
+		return R.data(tree);
+	}
+
+	/**
+	 * 获取权限分配树形结构
+	 */
+	@GetMapping("/grant-tree")
+	@ApiOperationSupport(order = 12)
+	@ApiOperation(value = "权限分配树形结构", notes = "权限分配树形结构")
+	public R<GrantTreeVO> grantTree(BladeUser user) {
+		GrantTreeVO vo = new GrantTreeVO();
+		vo.setMenu(menuService.grantTree(user));
+		vo.setDataScope(menuService.grantDataScopeTree(user));
+		vo.setApiScope(menuService.grantApiScopeTree(user));
+		return R.data(vo);
+	}
+
+	/**
+	 * 获取权限分配树形结构
+	 */
+	@GetMapping("/role-tree-keys")
+	@ApiOperationSupport(order = 13)
+	@ApiOperation(value = "角色所分配的树", notes = "角色所分配的树")
+	public R<CheckedTreeVO> roleTreeKeys(String roleIds) {
+		CheckedTreeVO vo = new CheckedTreeVO();
+		vo.setMenu(menuService.roleTreeKeys(roleIds));
+		vo.setDataScope(menuService.dataScopeTreeKeys(roleIds));
+		vo.setApiScope(menuService.apiScopeTreeKeys(roleIds));
+		return R.data(vo);
+	}
+
+	/**
+	 * 获取顶部菜单树形结构
+	 */
+	@GetMapping("/grant-top-tree")
+	@ApiOperationSupport(order = 14)
+	@ApiOperation(value = "顶部菜单树形结构", notes = "顶部菜单树形结构")
+	public R<GrantTreeVO> grantTopTree(BladeUser user) {
+		GrantTreeVO vo = new GrantTreeVO();
+		vo.setMenu(menuService.grantTopTree(user));
+		return R.data(vo);
+	}
+
+	/**
+	 * 获取顶部菜单树形结构
+	 */
+	@GetMapping("/top-tree-keys")
+	@ApiOperationSupport(order = 15)
+	@ApiOperation(value = "顶部菜单所分配的树", notes = "顶部菜单所分配的树")
+	public R<CheckedTreeVO> topTreeKeys(String topMenuIds) {
+		CheckedTreeVO vo = new CheckedTreeVO();
+		vo.setMenu(menuService.topTreeKeys(topMenuIds));
+		return R.data(vo);
+	}
+
+	/**
+	 * 顶部菜单数据
+	 */
+	@GetMapping("/top-menu")
+	@ApiOperationSupport(order = 16)
+	@ApiOperation(value = "顶部菜单数据", notes = "顶部菜单数据")
+	public R<List<TopMenu>> topMenu(BladeUser user) {
+		if (Func.isEmpty(user)) {
+			return null;
+		}
+		List<TopMenu> list = topMenuService.list(Wrappers.<TopMenu>query().lambda().orderByAsc(TopMenu::getSort));
+		return R.data(list);
+	}
+
+	/**
+	 * 获取配置的角色权限
+	 */
+	@GetMapping("auth-routes")
+	@ApiOperationSupport(order = 17)
+	@ApiOperation(value = "菜单的角色权限")
+	public R<List<Kv>> authRoutes(BladeUser user) {
+		if (Func.isEmpty(user)) {
+			return null;
+		}
+		return R.data(menuService.authRoutes(user));
+	}
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/ParamController.java b/blade-auth/src/main/java/org/springblade/system/controller/ParamController.java
new file mode 100644
index 0000000..0968014
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/ParamController.java
@@ -0,0 +1,90 @@
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.Param;
+import org.springblade.system.service.IParamService;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.validation.Valid;
+import java.util.Map;
+
+import static org.springblade.core.cache.constant.CacheConstant.PARAM_CACHE;
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/param")
+@Api(value = "参数管理", tags = "接口")
+public class ParamController {
+
+	private final IParamService paramService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入param")
+	public R<Param> detail(Param param) {
+		Param detail = paramService.getOne(Condition.getQueryWrapper(param));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "paramName", value = "参数名称", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "paramKey", value = "参数键名", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "paramValue", value = "参数键值", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入param")
+	public R<IPage<Param>> list(@ApiIgnore @RequestParam Map<String, Object> param, Query query) {
+		IPage<Param> pages = paramService.page(Condition.getPage(query), Condition.getQueryWrapper(param, Param.class));
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "新增或修改", notes = "传入param")
+	public R submit(@Valid @RequestBody Param param) {
+		CacheUtil.clear(PARAM_CACHE);
+		CacheUtil.clear(PARAM_CACHE, Boolean.FALSE);
+		return R.status(paramService.saveOrUpdate(param));
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(PARAM_CACHE);
+		CacheUtil.clear(PARAM_CACHE, Boolean.FALSE);
+		return R.status(paramService.deleteLogic(Func.toLongList(ids)));
+	}
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/PostController.java b/blade-auth/src/main/java/org/springblade/system/controller/PostController.java
new file mode 100644
index 0000000..da3a989
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/PostController.java
@@ -0,0 +1,148 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.Post;
+import org.springblade.system.service.IPostService;
+import org.springblade.system.vo.PostVO;
+import org.springblade.system.wrapper.PostWrapper;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+
+/**
+ * 岗位表 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/post")
+@Api(value = "岗位", tags = "岗位")
+public class PostController {
+
+	private final IPostService postService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入post")
+	public R<PostVO> detail(Post post) {
+		Post detail = postService.getOne(Condition.getQueryWrapper(post));
+		return R.data(PostWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 分页 岗位表
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入post")
+	public R<IPage<PostVO>> list(Post post, Query query) {
+		IPage<Post> pages = postService.page(Condition.getPage(query), Condition.getQueryWrapper(post));
+		return R.data(PostWrapper.build().pageVO(pages));
+	}
+
+
+	/**
+	 * 自定义分页 岗位表
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "分页", notes = "传入post")
+	public R<IPage<PostVO>> page(PostVO post, Query query) {
+		IPage<PostVO> pages = postService.selectPostPage(Condition.getPage(query), post);
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 岗位表
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "新增", notes = "传入post")
+	public R save(@Valid @RequestBody Post post) {
+		CacheUtil.clear(SYS_CACHE);
+		return R.status(postService.save(post));
+	}
+
+	/**
+	 * 修改 岗位表
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "修改", notes = "传入post")
+	public R update(@Valid @RequestBody Post post) {
+		CacheUtil.clear(SYS_CACHE);
+		return R.status(postService.updateById(post));
+	}
+
+	/**
+	 * 新增或修改 岗位表
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入post")
+	public R submit(@Valid @RequestBody Post post) {
+		CacheUtil.clear(SYS_CACHE);
+		return R.status(postService.saveOrUpdate(post));
+	}
+
+
+	/**
+	 * 删除 岗位表
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(SYS_CACHE);
+		return R.status(postService.deleteLogic(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 下拉数据源
+	 */
+	@GetMapping("/select")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "下拉数据源", notes = "传入post")
+	public R<List<Post>> select(String tenantId, BladeUser bladeUser) {
+		List<Post> list = postService.list(Wrappers.<Post>query().lambda().eq(Post::getTenantId, Func.toStrWithEmpty(tenantId, bladeUser.getTenantId())));
+		return R.data(list);
+	}
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/RegionController.java b/blade-auth/src/main/java/org/springblade/system/controller/RegionController.java
new file mode 100644
index 0000000..2a136b0
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/RegionController.java
@@ -0,0 +1,201 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.excel.util.ExcelUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.system.entity.Region;
+import org.springblade.system.excel.RegionExcel;
+import org.springblade.system.excel.RegionImporter;
+import org.springblade.system.service.IRegionService;
+import org.springblade.system.vo.RegionVO;
+import org.springblade.system.wrapper.RegionWrapper;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 行政区划表 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/region")
+@Api(value = "行政区划", tags = "行政区划")
+public class RegionController {
+
+	private final IRegionService regionService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入region")
+	public R<RegionVO> detail(Region region) {
+		Region detail = regionService.getOne(Condition.getQueryWrapper(region));
+		return R.data(RegionWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 分页 行政区划表
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入region")
+	public R<IPage<Region>> list(Region region, Query query) {
+		IPage<Region> pages = regionService.page(Condition.getPage(query), Condition.getQueryWrapper(region));
+		return R.data(pages);
+	}
+
+	/**
+	 * 懒加载列表
+	 */
+	@GetMapping("/lazy-list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "区划编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "name", value = "区划名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "懒加载列表", notes = "传入menu")
+	public R<List<RegionVO>> lazyList(String parentCode, @ApiIgnore @RequestParam Map<String, Object> menu) {
+		List<RegionVO> list = regionService.lazyList(parentCode, menu);
+		return R.data(RegionWrapper.build().listNodeLazyVO(list));
+	}
+
+	/**
+	 * 懒加载列表
+	 */
+	@GetMapping("/lazy-tree")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "code", value = "区划编号", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "name", value = "区划名称", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "懒加载列表", notes = "传入menu")
+	public R<List<RegionVO>> lazyTree(String parentCode, @ApiIgnore @RequestParam Map<String, Object> menu) {
+		List<RegionVO> list = regionService.lazyTree(parentCode, menu);
+		return R.data(RegionWrapper.build().listNodeLazyVO(list));
+	}
+
+	/**
+	 * 新增 行政区划表
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "新增", notes = "传入region")
+	public R save(@Valid @RequestBody Region region) {
+		return R.status(regionService.save(region));
+	}
+
+	/**
+	 * 修改 行政区划表
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "修改", notes = "传入region")
+	public R update(@Valid @RequestBody Region region) {
+		return R.status(regionService.updateById(region));
+	}
+
+	/**
+	 * 新增或修改 行政区划表
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "新增或修改", notes = "传入region")
+	public R submit(@Valid @RequestBody Region region) {
+		return R.status(regionService.submit(region));
+	}
+
+
+	/**
+	 * 删除 行政区划表
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "删除", notes = "传入主键")
+	public R remove(@ApiParam(value = "主键", required = true) @RequestParam String id) {
+		return R.status(regionService.removeRegion(id));
+	}
+
+	/**
+	 * 行政区划下拉数据源
+	 */
+	@GetMapping("/select")
+	@ApiOperationSupport(order = 9)
+	@ApiOperation(value = "下拉数据源", notes = "传入tenant")
+	public R<List<Region>> select(@RequestParam(required = false, defaultValue = "00") String code) {
+		List<Region> list = regionService.list(Wrappers.<Region>query().lambda().eq(Region::getParentCode, code));
+		return R.data(list);
+	}
+
+	/**
+	 * 导入行政区划数据
+	 */
+	@PostMapping("import-region")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "导入行政区划", notes = "传入excel")
+	public R importRegion(MultipartFile file, Integer isCovered) {
+		RegionImporter regionImporter = new RegionImporter(regionService, isCovered == 1);
+		ExcelUtil.save(file, regionImporter, RegionExcel.class);
+		return R.success("操作成功");
+	}
+
+	/**
+	 * 导出行政区划数据
+	 */
+	@GetMapping("export-region")
+	@ApiOperationSupport(order = 11)
+	@ApiOperation(value = "导出行政区划", notes = "传入user")
+	public void exportRegion(@ApiIgnore @RequestParam Map<String, Object> region, HttpServletResponse response) {
+		QueryWrapper<Region> queryWrapper = Condition.getQueryWrapper(region, Region.class);
+		List<RegionExcel> list = regionService.exportRegion(queryWrapper);
+		ExcelUtil.export(response, "行政区划数据" + DateUtil.time(), "行政区划数据表", list, RegionExcel.class);
+	}
+
+	/**
+	 * 导出模板
+	 */
+	@GetMapping("export-template")
+	@ApiOperationSupport(order = 12)
+	@ApiOperation(value = "导出模板")
+	public void exportUser(HttpServletResponse response) {
+		List<RegionExcel> list = new ArrayList<>();
+		ExcelUtil.export(response, "行政区划模板", "行政区划表", list, RegionExcel.class);
+	}
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/RoleController.java b/blade-auth/src/main/java/org/springblade/system/controller/RoleController.java
new file mode 100644
index 0000000..eee03f6
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/RoleController.java
@@ -0,0 +1,151 @@
+package org.springblade.system.controller;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.BladeConstant;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.cache.SysCache;
+import org.springblade.system.entity.Role;
+import org.springblade.system.service.IRoleService;
+import org.springblade.system.user.cache.UserCache;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.vo.GrantVO;
+import org.springblade.system.vo.RoleVO;
+import org.springblade.system.wrapper.RoleWrapper;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/role")
+@Api(value = "角色", tags = "角色")
+//@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+public class RoleController {
+
+	private final IRoleService roleService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入role")
+	public R<RoleVO> detail(Role role) {
+		Role detail = roleService.getOne(Condition.getQueryWrapper(role));
+		return R.data(RoleWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 列表
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "roleName", value = "参数名称", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "roleAlias", value = "角色别名", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "列表", notes = "传入role")
+	public R<List<RoleVO>> list(@ApiIgnore @RequestParam Map<String, Object> role, BladeUser bladeUser) {
+		QueryWrapper<Role> queryWrapper = Condition.getQueryWrapper(role, Role.class);
+		List<Role> list = roleService.list((!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(Role::getTenantId, bladeUser.getTenantId()) : queryWrapper);
+		return R.data(RoleWrapper.build().listNodeVO(list));
+	}
+
+	/**
+	 * 获取角色树形结构
+	 */
+	@GetMapping("/tree")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<RoleVO>> tree(String tenantId, BladeUser bladeUser) {
+		List<RoleVO> tree = roleService.tree(Func.toStrWithEmpty(tenantId, bladeUser.getTenantId()));
+		return R.data(tree);
+	}
+
+	/**
+	 * 获取指定角色树形结构
+	 */
+	@GetMapping("/tree-by-id")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "树形结构", notes = "树形结构")
+	public R<List<RoleVO>> treeById(Long roleId, BladeUser bladeUser) {
+		Role role = SysCache.getRole(roleId);
+		List<RoleVO> tree = roleService.tree(Func.notNull(role) ? role.getTenantId() : bladeUser.getTenantId());
+		return R.data(tree);
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "新增或修改", notes = "传入role")
+	public R submit(@Valid @RequestBody Role role) {
+		CacheUtil.clear(SYS_CACHE);
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(roleService.submit(role));
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(SYS_CACHE);
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(roleService.removeRole(ids));
+	}
+
+	/**
+	 * 设置角色权限
+	 */
+	@PostMapping("/grant")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "权限设置", notes = "传入roleId集合以及menuId集合")
+	public R grant(@RequestBody GrantVO grantVO) {
+		CacheUtil.clear(SYS_CACHE);
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		boolean temp = roleService.grant(grantVO.getRoleIds(), grantVO.getMenuIds(), grantVO.getDataScopeIds(), grantVO.getApiScopeIds());
+		return R.status(temp);
+	}
+
+	/**
+	 * 下拉数据源
+	 */
+//	@PreAuth(AuthConstant.PERMIT_ALL)
+	@GetMapping("/select")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "下拉数据源", notes = "传入id集合")
+	public R<List<Role>> select(Long userId, String roleId) {
+		if (Func.isNotEmpty(userId)) {
+			User user = UserCache.getUser(userId);
+			roleId = user.getRoleId();
+		}
+		List<Role> list = roleService.list(Wrappers.<Role>lambdaQuery().in(Role::getId, Func.toLongList(roleId)));
+		return R.data(list);
+	}
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/SearchController.java b/blade-auth/src/main/java/org/springblade/system/controller/SearchController.java
new file mode 100644
index 0000000..f4d10e9
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/SearchController.java
@@ -0,0 +1,98 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.Post;
+import org.springblade.system.service.IDeptService;
+import org.springblade.system.service.IPostService;
+import org.springblade.system.service.IRoleService;
+import org.springblade.system.vo.DeptVO;
+import org.springblade.system.vo.PostVO;
+import org.springblade.system.vo.RoleVO;
+import org.springblade.system.wrapper.PostWrapper;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 查询控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/search")
+@Api(value = "查询", tags = "查询")
+public class SearchController {
+
+	private final IRoleService roleService;
+
+	private final IDeptService deptService;
+
+	private final IPostService postService;
+
+	/**
+	 * 角色信息查询
+	 */
+	@GetMapping("/role")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "角色信息查询", notes = "传入roleName或者parentId")
+	public R<List<RoleVO>> roleSearch(String roleName, Long parentId) {
+		return R.data(roleService.search(roleName, parentId));
+	}
+
+	/**
+	 * 部门信息查询
+	 */
+	@GetMapping("/dept")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "部门信息查询", notes = "传入deptName或者parentId")
+	public R<List<DeptVO>> deptSearch(String deptName, Long parentId) {
+		return R.data(deptService.search(deptName, parentId));
+	}
+
+	/**
+	 * 岗位信息查询
+	 */
+	@GetMapping("/post")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "岗位信息查询", notes = "传入postName")
+	public R<IPage<PostVO>> postSearch(String postName, Query query) {
+		LambdaQueryWrapper<Post> queryWrapper = Wrappers.<Post>query().lambda();
+		if (Func.isNotBlank(postName)) {
+			queryWrapper.like(Post::getPostName, postName);
+		}
+		IPage<Post> pages = postService.page(Condition.getPage(query), queryWrapper);
+		return R.data(PostWrapper.build().pageVO(pages));
+	}
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/TenantController.java b/blade-auth/src/main/java/org/springblade/system/controller/TenantController.java
new file mode 100644
index 0000000..f94cca2
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/TenantController.java
@@ -0,0 +1,233 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.BladeConstant;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springblade.core.tool.support.Kv;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.Tenant;
+import org.springblade.system.entity.TenantPackage;
+import org.springblade.system.service.ITenantPackageService;
+import org.springblade.system.service.ITenantService;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.validation.Valid;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+import static org.springblade.core.tenant.constant.TenantBaseConstant.TENANT_DATASOURCE_CACHE;
+import static org.springblade.core.tenant.constant.TenantBaseConstant.TENANT_DATASOURCE_EXIST_KEY;
+import static org.springblade.system.cache.SysCache.TENANT_PACKAGE_ID;
+import static org.springblade.system.cache.SysCache.TENANT_TENANT_ID;
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@NonDS
+@ApiIgnore
+@RestController
+@AllArgsConstructor
+@RequestMapping("/tenant")
+@Api(value = "租户管理", tags = "接口")
+public class TenantController {
+
+	private final ITenantService tenantService;
+
+	private final ITenantPackageService tenantPackageService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入tenant")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+	public R<Tenant> detail(Tenant tenant) {
+		Tenant detail = tenantService.getOne(Condition.getQueryWrapper(tenant));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "tenantId", value = "参数名称", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "tenantName", value = "角色别名", paramType = "query", dataType = "string"),
+		@ApiImplicitParam(name = "contactNumber", value = "联系电话", paramType = "query", dataType = "string")
+	})
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入tenant")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+	public R<IPage<Tenant>> list(@ApiIgnore @RequestParam Map<String, Object> tenant, Query query, BladeUser bladeUser) {
+		QueryWrapper<Tenant> queryWrapper = Condition.getQueryWrapper(tenant, Tenant.class);
+		IPage<Tenant> pages = tenantService.page(Condition.getPage(query), (!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(Tenant::getTenantId, bladeUser.getTenantId()) : queryWrapper);
+		return R.data(pages);
+	}
+
+	/**
+	 * 下拉数据源
+	 */
+	@GetMapping("/select")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "下拉数据源", notes = "传入tenant")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+	public R<List<Tenant>> select(Tenant tenant, BladeUser bladeUser) {
+		QueryWrapper<Tenant> queryWrapper = Condition.getQueryWrapper(tenant);
+		List<Tenant> list = tenantService.list((!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(Tenant::getTenantId, bladeUser.getTenantId()) : queryWrapper);
+		return R.data(list);
+	}
+
+	/**
+	 * 自定义分页
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "分页", notes = "传入tenant")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+	public R<IPage<Tenant>> page(Tenant tenant, Query query) {
+		IPage<Tenant> pages = tenantService.selectTenantPage(Condition.getPage(query), tenant);
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "新增或修改", notes = "传入tenant")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	public R submit(@Valid @RequestBody Tenant tenant) {
+		return R.status(tenantService.submitTenant(tenant));
+	}
+
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(tenantService.removeTenant(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 授权配置
+	 */
+	@PostMapping("/setting")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "授权配置", notes = "传入ids,accountNumber,expireTime")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	public R setting(@ApiParam(value = "主键集合", required = true) @RequestParam String ids, @ApiParam(value = "账号额度") Integer accountNumber, @ApiParam(value = "过期时间") Date expireTime) {
+		return R.status(tenantService.setting(accountNumber, expireTime, ids));
+	}
+
+	/**
+	 * 数据源配置
+	 */
+	@PostMapping("datasource")
+	@ApiOperationSupport(order = 8)
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperation(value = "数据源配置", notes = "传入datasource_id")
+	public R datasource(@ApiParam(value = "租户ID", required = true) @RequestParam String tenantId, @ApiParam(value = "数据源ID", required = true) @RequestParam Long datasourceId){
+		CacheUtil.evict(TENANT_DATASOURCE_CACHE, TENANT_DATASOURCE_EXIST_KEY, tenantId, Boolean.FALSE);
+		return R.status(tenantService.update(Wrappers.<Tenant>update().lambda().set(Tenant::getDatasourceId, datasourceId).eq(Tenant::getTenantId, tenantId)));
+	}
+
+	/**
+	 * 根据名称查询列表
+	 *
+	 * @param name 租户名称
+	 */
+	@GetMapping("/find-by-name")
+	@ApiOperationSupport(order = 9)
+	@ApiOperation(value = "详情", notes = "传入tenant")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+	public R<List<Tenant>> findByName(String name) {
+		List<Tenant> list = tenantService.list(Wrappers.<Tenant>query().lambda().like(Tenant::getTenantName, name));
+		return R.data(list);
+	}
+
+	/**
+	 * 根据域名查询信息
+	 *
+	 * @param domain 域名
+	 */
+	@GetMapping("/info")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "配置信息", notes = "传入domain")
+	public R<Kv> info(String domain) {
+		Tenant tenant = tenantService.getOne(Wrappers.<Tenant>query().lambda().eq(Tenant::getDomainUrl, domain));
+		Kv kv = Kv.create();
+		if (tenant != null) {
+			kv.set("tenantId", tenant.getTenantId())
+				.set("domain", tenant.getDomainUrl())
+				.set("backgroundUrl", tenant.getBackgroundUrl());
+		}
+		return R.data(kv);
+	}
+
+	/**
+	 * 根据租户ID查询产品包详情
+	 *
+	 * @param tenantId 租户ID
+	 */
+	@GetMapping("/package-detail")
+	@ApiOperationSupport(order = 11)
+	@ApiOperation(value = "产品包详情", notes = "传入tenantId")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	public R<TenantPackage> packageDetail(Long tenantId) {
+		Tenant tenant = tenantService.getById(tenantId);
+		return R.data(tenantPackageService.getById(tenant.getPackageId()));
+	}
+
+	/**
+	 * 产品包配置
+	 */
+	@PostMapping("/package-setting")
+	@ApiOperationSupport(order = 12)
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
+	@ApiOperation(value = "产品包配置", notes = "传入packageId")
+	public R packageSetting(@ApiParam(value = "租户ID", required = true) @RequestParam String tenantId, @ApiParam(value = "产品包ID") Long packageId) {
+		CacheUtil.evict(SYS_CACHE, TENANT_TENANT_ID, tenantId, Boolean.FALSE);
+		CacheUtil.evict(SYS_CACHE, TENANT_PACKAGE_ID, tenantId, Boolean.FALSE);
+		return R.status(tenantService.update(Wrappers.<Tenant>update().lambda().set(Tenant::getPackageId, packageId).eq(Tenant::getTenantId, tenantId)));
+	}
+
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/TenantPackageController.java b/blade-auth/src/main/java/org/springblade/system/controller/TenantPackageController.java
new file mode 100644
index 0000000..d7946a8
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/TenantPackageController.java
@@ -0,0 +1,133 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+//import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+//import org.springblade.core.secure.annotation.PreAuth;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.TenantPackage;
+import org.springblade.system.service.ITenantPackageService;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+
+/**
+ * 租户产品表 控制器
+ *
+ * @author BladeX
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/tenant-package")
+@Api(value = "租户产品表", tags = "租户产品表接口")
+public class TenantPackageController {
+
+	private final ITenantPackageService tenantPackageService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入tenantPackage")
+	public R<TenantPackage> detail(TenantPackage tenantPackage) {
+		TenantPackage detail = tenantPackageService.getOne(Condition.getQueryWrapper(tenantPackage));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页 租户产品表
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入tenantPackage")
+	public R<IPage<TenantPackage>> list(TenantPackage tenantPackage, Query query) {
+		IPage<TenantPackage> pages = tenantPackageService.page(Condition.getPage(query), Condition.getQueryWrapper(tenantPackage));
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 租户产品表
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "新增", notes = "传入tenantPackage")
+	public R save(@Valid @RequestBody TenantPackage tenantPackage) {
+		return R.status(tenantPackageService.save(tenantPackage));
+	}
+
+	/**
+	 * 修改 租户产品表
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "修改", notes = "传入tenantPackage")
+	public R update(@Valid @RequestBody TenantPackage tenantPackage) {
+		return R.status(tenantPackageService.updateById(tenantPackage));
+	}
+
+	/**
+	 * 新增或修改 租户产品表
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "新增或修改", notes = "传入tenantPackage")
+	public R submit(@Valid @RequestBody TenantPackage tenantPackage) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(tenantPackageService.saveOrUpdate(tenantPackage));
+	}
+
+
+	/**
+	 * 删除 租户产品表
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
+		return R.status(tenantPackageService.deleteLogic(Func.toLongList(ids)));
+	}
+
+
+	/**
+	 * 下拉数据源
+	 */
+	@GetMapping("/select")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "下拉数据源", notes = "传入tenant")
+//	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+	public R<List<TenantPackage>> select(TenantPackage tenantPackage) {
+		return R.data(tenantPackageService.list(Condition.getQueryWrapper(tenantPackage)));
+	}
+
+
+}
diff --git a/blade-auth/src/main/java/org/springblade/system/controller/TopMenuController.java b/blade-auth/src/main/java/org/springblade/system/controller/TopMenuController.java
new file mode 100644
index 0000000..3b0a8f6
--- /dev/null
+++ b/blade-auth/src/main/java/org/springblade/system/controller/TopMenuController.java
@@ -0,0 +1,138 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.system.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+//import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+//import org.springblade.core.secure.annotation.PreAuth;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.TopMenu;
+import org.springblade.system.service.ITopMenuService;
+import org.springblade.system.vo.GrantVO;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+import static org.springblade.core.cache.constant.CacheConstant.MENU_CACHE;
+import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
+
+/**
+ * 顶部菜单表 控制器
+ *
+ * @author BladeX
+ */
+@NonDS
+@RestController
+@AllArgsConstructor
+@RequestMapping("/topmenu")
+@Api(value = "顶部菜单表", tags = "顶部菜单")
+//@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+public class TopMenuController {
+
+	private final ITopMenuService topMenuService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入topMenu")
+	public R<TopMenu> detail(TopMenu topMenu) {
+		TopMenu detail = topMenuService.getOne(Condition.getQueryWrapper(topMenu));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页 顶部菜单表
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入topMenu")
+	public R<IPage<TopMenu>> list(TopMenu topMenu, Query query) {
+		IPage<TopMenu> pages = topMenuService.page(Condition.getPage(query), Condition.getQueryWrapper(topMenu).lambda().orderByAsc(TopMenu::getSort));
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 顶部菜单表
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "新增", notes = "传入topMenu")
+	public R save(@Valid @RequestBody TopMenu topMenu) {
+		return R.status(topMenuService.save(topMenu));
+	}
+
+	/**
+	 * 修改 顶部菜单表
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "修改", notes = "传入topMenu")
+	public R update(@Valid @RequestBody TopMenu topMenu) {
+		return R.status(topMenuService.updateById(topMenu));
+	}
+
+	/**
+	 * 新增或修改 顶部菜单表
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入topMenu")
+	public R submit(@Valid @RequestBody TopMenu topMenu) {
+		return R.status(topMenuService.saveOrUpdate(topMenu));
+	}
+
+
+	/**
+	 * 删除 顶部菜单表
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(topMenuService.deleteLogic(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 设置顶部菜单
+	 */
+	@PostMapping("/grant")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "顶部菜单配置", notes = "传入topMenuId集合以及menuId集合")
+	public R grant(@RequestBody GrantVO grantVO) {
+		CacheUtil.clear(SYS_CACHE);
+		CacheUtil.clear(MENU_CACHE);
+		CacheUtil.clear(MENU_CACHE, Boolean.FALSE);
+		boolean temp = topMenuService.grant(grantVO.getTopMenuIds(), grantVO.getMenuIds());
+		return R.status(temp);
+	}
+
+
+
+}

--
Gitblit v1.9.3