zhongrj
2024-05-06 a54a414b6b6d566aaa79d228313ea1bbede74f1f
加入 controller
1 files modified
15 files added
2293 ■■■■■ changed files
blade-auth/src/main/java/org/springblade/auth/config/SecurityConfiguration.java 6 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/ApiScopeController.java 104 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/AuthClientController.java 101 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/DataScopeController.java 122 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/DeptController.java 160 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/DictBizController.java 161 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/DictController.java 179 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/MenuController.java 268 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/ParamController.java 90 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/PostController.java 148 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/RegionController.java 201 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/RoleController.java 151 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/SearchController.java 98 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/TenantController.java 233 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/TenantPackageController.java 133 ●●●●● patch | view | raw | blame | history
blade-auth/src/main/java/org/springblade/system/controller/TopMenuController.java 138 ●●●●● patch | view | raw | blame | history
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");
    }
blade-auth/src/main/java/org/springblade/system/controller/ApiScopeController.java
New file
@@ -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)));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/AuthClientController.java
New file
@@ -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)));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/DataScopeController.java
New file
@@ -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)));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/DeptController.java
New file
@@ -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);
    }
}
blade-auth/src/main/java/org/springblade/system/controller/DictBizController.java
New file
@@ -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));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/DictController.java
New file
@@ -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);
    }
}
blade-auth/src/main/java/org/springblade/system/controller/MenuController.java
New file
@@ -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));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/ParamController.java
New file
@@ -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)));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/PostController.java
New file
@@ -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);
    }
}
blade-auth/src/main/java/org/springblade/system/controller/RegionController.java
New file
@@ -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);
    }
}
blade-auth/src/main/java/org/springblade/system/controller/RoleController.java
New file
@@ -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);
    }
}
blade-auth/src/main/java/org/springblade/system/controller/SearchController.java
New file
@@ -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));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/TenantController.java
New file
@@ -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)));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/TenantPackageController.java
New file
@@ -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)));
    }
}
blade-auth/src/main/java/org/springblade/system/controller/TopMenuController.java
New file
@@ -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);
    }
}