# 后台手册

# 模块目录规范

后端modules结构图

# 1. api

controller类

只写swagger注解,log注解,valid参数校验注解,权限校验注解等。

总之不写业务逻辑,业务逻辑实现都调用biz。

# 2. biz

复杂业务类

可调用多个repository类

注意:该类里的方法无特殊情况,不要return <? extends BywinCloudBaseResponse>,controller层已统一自动套了一层响应格式。

{
  "code": 0,
  "data": null,
  "requestId": "请求id"
}

# 3. repository

简单业务类

不要涉及到业务逻辑实现,只写sql。

# 4. mapper

mapper类

# 5. tb

数据库实体类


# 6. request

请求参数类

# 7. response

返回参数类

# @BywinCloudRest

@BywinCloudRest 框架AOP实现需要,如实现自动保存Log等功能

使用方法:controller层用@BywinCloudRest替换@RestController+@RequestMapping

示例

@Tag(name = "用户管理模块示例")
@BywinCloudRest("/users")
public class ExampleUserManagerApi {}

# 包裹返回格式

引入@BywinCloudRest,controller层会默认包裹一层返回格式,如:

{
  "code": 0,
  "requestId": "Nn73Xx2yvlhx7W2svUvei"
}

报错默认返回 "code":"400"

  • 400 客户端错误
  • 500 服务器错误

错误码参照Http状态码大全


# 包裹自定义

@ResponseStatus注解可以改返回码


指定返回包裹

@Operation(summary = "指定code,msg")
@GetMapping("/test-code-msg")
public BywinCloudResponse<String> codeMsg() {

    final BywinCloudResponse<String> response = new BywinCloudResponse<>();

    response.setCode(120);
    response.setMsg("my msg");
    response.setData("hello world!");

    return response;
}

//return
{
  "msg": "my msg",
  "code": 120,
  "requestId": "GOsZBmIokBO1YlGemHAtz",
  "data": "hello world!"
}

自定义返回包裹

public static class MyResponseWrapper implements IBywinCloudRestReturnValueWrapper {

    @Override
    public Object wrap(Object returnValue) {
        final HashMap<String, Object> wrappered = new HashMap<>();
        wrappered.put("data", returnValue);
        wrappered.put("mywrapper", "this is my wrapper");
        return wrappered;
    }

}

/**
 * 使用 @BywinCloudResponseWrapper 包裹
 */
@Operation(summary = "测试自定义包裹响应类型")
@BywinCloudResponseWrapper(type = MyResponseWrapper.class)
@GetMapping("/test-custom-wrap")
public String testCustomWrapper() {
    //noinspection SpringMVCViewInspection
    return "testCustomWrapper";
}

不包裹返回

/**
 * 使用 @UnwrapBywinCloudResponse 注解取消包裹
 */
@UnwrapBywinCloudResponse
@Operation(summary = "测试不包裹响应类型,适用于响应文件")
@GetMapping("/test-unwrap")
public String testUnwrap() {
    //noinspection SpringMVCViewInspection
    return "test unwrap";
}

//return
test unwrap

# 分页实现

# 前端参数

pageNum:第几页默认1
pageSize:每页大小默认10
sortField:排序字段
sortOrder:asc 升序 desc 降序 

# 后台实现逻辑

//参数类
@EqualsAndHashCode(callSuper = true)
@Data
public class QueryUserRequest extends BywinCloudPageQuery {
    //private String username;
}

//Controller
@PostMapping("/search")
@Operation(summary = "分页查询用户")
public IPageData<ExampleUser> pageQueryUsers(@Valid @RequestBody QueryUserRequest query) {
    return exampleUserManager.pageQueryUsers(query);
}

//ServiceImpl
public IPageData<ExampleUser> pageQuery(QueryUserRequest request) {
    LambdaQueryChainWrapper<ExampleUser> wrapper = new LambdaQueryChainWrapper<ExampleUser>();
    return BywinCloudPageHelper.query(request, wrapper::list);
}

# 权限注解

  • @RequiredBywinCloudPermissions("example:example:query")

权限认证:必须具有指定权限才能进入该方法。


  • @RequiredBywinCloudRoles("example:admin")

角色认证:必须具有指定角色标识才能进入该方法。


@RequiredBywinCloudPermissions

参数 类型 描述
value String[] 权限列表
mode RequiredMode 权限之间的判断关系,默认为RequiredMode.ANY

示例1:以下代码表示必须拥有 example:example:query 权限才可以访问

@GetMapping("/user/{id}")
@RequiredBywinCloudPermissions("example:example:query")
public String queryById(@PathVariable("id") Long id) {
    return "Successfully accessed, user id: " + id;
}

@RequiredBywinCloudRoles

参数 类型 描述
value String[] 权限列表
mode RequiredMode 权限之间的判断关系,默认为RequiredMode.ANY

示例1:以下代码表示必须拥有 example:admin 角色才可以访问

@GetMapping("/admin")
@RequiredBywinCloudRoles("_example:admin")
public String admin() {
    return "welcome! admin";
}

# 异常处理

统一返回实体类

@Data
@Schema(title = "通用单条目响应数据")
public class BywinCloudResponse<T> extends BywinCloudBaseResponse {
    @Schema(name = "业务数据")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T data;
}

未知异常

@Operation(summary = "未知异常测试")
@GetMapping("/unknown")
public void unknown() throws Exception {
    throw new Exception("unknown");
}

//return
{
  "msg": "Internal Server Error",
  "code": 500,
  "requestId": "9LFxBLB2tEIGaTjaIlp66"
}

通用业务异常

@Operation(summary = "通用业务异常")
@GetMapping("/bywin-cloud-runtime-exception")
public void bywinCloudRuntimeException() {
    throw new BywinCloudRuntimeException("BywinCloudRuntimeException异常测试");
}

//return
{
  "msg": "BywinCloudRuntimeException异常测试",
  "code": 400,
  "requestId": "8PJRYAJWNoisB6wV54fz5"
}

自定义异常

@Operation(summary = "自定义异常")
@GetMapping("/my-exception")
public void myException() {
    throw new MyException();
}

@BywinCloudError(code = 403, errCode = "Forbidden", httpStatus = 403, message = "Forbidden")
public class MyException extends BywinCloudRuntimeException {
}

//return
{
  "msg": "Forbidden",
  "code": 403,
  "requestId": "_2RBksIrTHcWRxjkvVbkT"
}

# 参数验证

使用jakarta.validation包 @Valid

不符合固定返回10000错误码

//controller
@PostMapping
public void example(@Valid @RequestBody ExampleRequest query) {
}

//实体类
@Data
@Schema(title = "参数校验请求")
public class ValidRequest {

    @NotBlank(message = "名称不能为空")
    @Schema(title = "名称")
    private String name;
}

//不符合规则return
{
  "code": 10000,
  "requestId": "6B3Ih7trOiUqKIZjgFQSi",
  "data": [
    {
      "field": "name",
      "msg": "名称不能为空"
    }
  ]
}

# 注解参数说明

注解名称 功能
@Null 检查该字段为空
@NotNull 不能为null
@NotBlank 不能为空,常用于检查空字符串
@NotEmpty 不能为空,多用于检测list是否size是0
@Max 该字段的值只能小于或等于该值
@Min 该字段的值只能大于或等于该值
@Past 检查该字段的日期是在过去
@Future 检查该字段的日期是否是属于将来的日期
@Email 检查是否是一个有效的email地址
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@Size(min=, max=) 检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等
@Length(min=,max=) 检查所属的字段的长度是否在min和max之间,只能用于字符串
@AssertTrue 用于boolean字段,该字段只能为true
@AssertFalse 该字段的值只能为false

# 数据权限

# SQL字段

数据库字段,需要有:数据创建者,部门字段

通用情况sql如下:

  `dept_id` bigint(20) DEFAULT NULL COMMENT '部门id',
  `create_by` varchar(50) DEFAULT NULL COMMENT '创建人',

# 实体类

后端实体类,需要继承:AutoIncrIdTable(自增id+通用字段类),IBywinCloudData(数据权限类)

public class ExampleUser extends AutoIncrIdTable implements IBywinCloudData {}

IBywinCloudData说明:默认数据创建者为`create_by`,部门字段为`dept_id`

如需自定义,可重写方法:

public class ExampleUser extends AutoIncrIdTable implements IBywinCloudData {
    @Override
    public String getOwner() {
        return getCreateBy();
    }
    @Override
    public Long getDeptId(){
        return getDeptId();
    }
}

# 业务代码通用接入

  1. 引入2个注解:

@PrepareBywinCloudDataPermit 准备数据权限

@InjectBywinCloudDataPermit 注入数据权限

//controller控制层
@PrepareBywinCloudDataPermit(UserManagerPermissions.QUERY_USER)
public IPageData<ExampleUser> pageQuery(@Valid @RequestBody QueryUserRequest query) {
    return exampleUserManager.pageQueryUsers(query);
}

//实现层
/**
 * 使用 InjectBywinCloudDataPermit 注解注入权限
 *
 * @param request QueryUserRequest
 * @return inject(wrapper, BywinCloudDataPermitContextHolder.permit ());
 */
@InjectBywinCloudDataPermit
default LambdaQueryChainWrapper<ExampleUser> lambdaQuery(QueryUserRequest request) {
    final String username = Optional.ofNullable(request.getUsername()).map(String::trim).orElse(null);
    return lambdaQuery().like(StringUtils.isNotBlank(username), ExampleUser::getUsername, username);
}

default IPageData<ExampleUser> pageQuery(QueryUserRequest request) {
    // aop不支持 内部调用代理方法,所以这里用self(this)转成代理类
    final LambdaQueryChainWrapper<ExampleUser> wrapper = self(this).lambdaQuery(request);
    return BywinCloudPageHelper.query(request, wrapper::list);
}

2. 实现层需继承 IBywinCloudDataPermitRepository<>,来使@InjectBywinCloudDataPermit注解生效。
public interface ExampleUserRepository extends IBywinCloudDataPermitRepository<ExampleUser> {

}

注意:@InjectBywinCloudDataPermit包裹的方法,需要return Wrapper。 目前支持的类型有:

  • LambdaQueryChainWrapper
  • LambdaQueryWrapper
  • QueryWrapper
  • QueryChainWrapper

示例

@InjectBywinCloudDataPermit
default LambdaQueryChainWrapper<ExampleUser> lambdaQuery(QueryUserRequest request) {
    final String username = Optional.ofNullable(request.getUsername()).map(String::trim).orElse(null);
    return lambdaQuery().like(StringUtils.isNotBlank(username), ExampleUser::getUsername, username);
}

# 特殊情况

当create_by和dept_id在联表查询的情况下,可使用注解@BywinCloudDataPermitColumn自定义联表字段名

@InjectBywinCloudDataPermit
@BywinCloudDataPermitColumn(dept = "a.dept_id",owner = "a.create_by")


# FAQ

  1. 为什么数据权限要拆分成两个注解?

控制层@PrepareBywinCloudDataPermit引入后,实现层可以选择添加或者不添加@InjectBywinCloudDataPermit来切换是否让数据权限生效,更为灵活。


# 业务代码自定义接入

当然了,如果觉得不方便,或是有额外的自定义需求上述暂无法实现的情况,可选择手动引入数据权限。

# 方式一

需要控制层先添加@PrepareBywinCloudDataPermit注解,然后业务实现类中使用

BywinCloudDataPermitContextHolder.permit()


获取IBywinCloudDataPermit类:

String getUsername(); //当前用户名

Set<Long> getDeptIds(); //当前拥有的部门数据权限

public interface IBywinCloudDataPermit {
    Set<Long> NOT_ALLOW_ACCESS_DEPT_IDS = Set.of(-1L);

    String getUsername();

    Set<Long> getDeptIds();

    default boolean hasDeptIds() {
        final Set<Long> deptIds = getDeptIds();
        return deptIds != null && NOT_ALLOW_ACCESS_DEPT_IDS != deptIds && !deptIds.isEmpty();
    }

    default boolean accessable(IBywinCloudData data) {
        final Set<Long> deptIds = getDeptIds();
        return Objects.equals(getUsername(), data.getOwner()) ||
                (deptIds != null && deptIds.contains(data.getDeptId()));
    }


    static IBywinCloudDataPermit ofPermission(BywinCloudUser user, String permission) {
        return user.getPermitByPermission(permission);
    }

    static IBywinCloudDataPermit ofRole(BywinCloudUser user, String role) {
        return user.getPermitByRole(role);
    }

    static IBywinCloudDataPermit ofPermission(String permission) {
        return ofPermission(BywinCloudUserContextHolder.getUser(), permission);
    }

    static IBywinCloudDataPermit ofRole(String role) {
        return ofRole(BywinCloudUserContextHolder.getUser(), role);
    }
}

# 方式二

//部门数据权限常用于sql, eg: where dept_id in (1, 2, 3)
Set<Long> deptIds = BywinCloudUserContextHolder.getUser().getAccessibleDepartmentsByPermission(permission);
Set<Long> deptIds = BywinCloudUserContextHolder.getUser().getAccessibleDepartmentsByRole(role);

BywinCloudUserContextHolder.getUser() 说明

public interface BywinCloudUser {

    /**
     * 当前用户名
     */
    String getUsername();

    /**
     * 是否有角色
     *
     * @param role 角色唯一key
     */
    boolean hasRole(String role);

    /**
     * 判断用户是否有权限
     *
     * @param permission 权限唯一key
     */
    boolean hasPermission(String permission);

    /**
     * 获取用户的部门权限
     *
     * @param role 角色唯一key
     * @return 返回用户在该角色绑定下的可访问的部门数据列表
     */
    Set<Long> getAccessibleDepartmentsByRole(String role);

    /**
     * 获取该用户绑定这个角色的部门id
     *
     * @param role 角色
     * @return 部门id
     */
    Long getDepartmentIdByRole(String role);

    /**
     * 获取该用户绑定这个权限的部门id
     *
     * @param permission 角色
     * @return 部门id
     */
    Long getDepartmentIdByPermission(String permission);

    /**
     * 获取用户的部门权限
     *
     * @param permission 权限
     * @return 返回用户在该权限绑定下的可访问的部门数据列表
     */
    Set<Long> getAccessibleDepartmentsByPermission(String permission);


    String SUPER_ADMIN = "super_admin";

    /**
     * 是否为超级管理员
     *
     * @return super_admin 角色
     */
    default boolean isAdmin() {
        return hasRole(SUPER_ADMIN);
    }


    default IBywinCloudDataPermit getPermitByRole(String role) {
        return BywinCloudDataPermit.builder()
                .username(getUsername())
                .deptIds(getAccessibleDepartmentsByRole(role))
                .build();
    }

    default IBywinCloudDataPermit getPermitByPermission(String permission) {
        return BywinCloudDataPermit.builder()
                .username(getUsername())
                .deptIds(getAccessibleDepartmentsByPermission(permission))
                .build();
    }

}


部门数据权限

  1. 获取用户绑定这个角色的部门id
Long getDepartmentIdByRole(String role);
  1. 获取用户的部门权限 返回用户在该角色绑定下的可访问的部门数据列表
Set<Long> getAccessibleDepartmentsByRole(String role);
  1. 获取用户绑定这个权限的部门id
Long getDepartmentIdByPermission(String permission)
  1. 获取用户的部门权限 返回用户在该权限绑定下的可访问的部门数据列表
Set<Long> getAccessibleDepartmentsByPermission(String permission)

使用示例

查询某用户名,且在 super:admin 角色的部门数据权限

public LambdaQueryChainWrapper<ExampleUser> lambdaQuery(QueryUserRequest request) {
    String username = Optional.ofNullable(request.getUsername()).map(String::trim).orElse(null);

    Set<Long> deptIds = BywinCloudUserContextHolder.getUser().getAccessibleDepartmentsByRole("super:admin");
    deptIds.add(-1L);

    LambdaQueryChainWrapper<ExampleUser> wrapper = lambdaQuery()
            .eq(ExampleUser::getUsername, username)
            .in(ExampleUser::getDeptId, deptIds);

    return wrapper;
}

# 多数据源

# 配置

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx) # 内置加密,使用请查看详细文档
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver
        #......省略
        #以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2

# 使用**@DS** 切换数据源

注解 结果
没有@DS 默认数据源
@DS("dsName") dsName可以为组名也可以为具体某个库的名称

# 代码示例

@Mapper
@DS("db1")
public interface TbExampleMapper extends BaseMapper<TbExample> {
}

# 系统接口

# 注解

注意:强制使用 openApi,也就是swagger v3。

openApi,便于apifox、postman导入json直接调试。


在现在的开发过程中还有很大一部分公司都是以口口相传的方式来进行前后端的联调,而接口文档很大一部分都只停留在了说说而已的地步,或者写了代码再写文档。 还有一点就是文档的修改,定义好的接口并不是一成不变的,可能在开发过程中文档修改不止一次的变化,这个时候就会很难受了。 只要不是强制性要求,没人会愿意写这东西,而且在写的过程中,一个字母的错误就会导致联调时候的很大麻烦,但是通过Swagger v3,我们可以省略了这一步,而且文档出错率近乎于零, 只要你在写代码的时候,稍加几个注解,文档自动生成。

注解 注解位置 说明
@Tag(name = “接口类名”,description = “接口类描述”) Controller 类上
@Operation(summary =“接口方法描述”) Controller 方法上
@Parameters Controller 方法上
@Parameter(description=“参数描述”) Controller 方法上 @Parameters 里
@Parameter(description=“参数描述”) Controller 方法的参数上
@Schema 实体类上
@Schema 实体类属性上
@Parameter(hidden = true) 或 @Operation(hidden = true) 或 @Hidden 隐藏

示例:

//Controller 类上
@Tag(name = "exampleController")
public class exampleController {}

//Controller 方法上
Operation(summary = "exampleApi")
@GetMapping("/exampleApi")
public BywinCloudResponse<?> exampleApi() {}

//controller参数上
public String example(
    @Parameter(in = ParameterIn.PATH, name = "key", description = "缓存key")
    @PathVariable("key") String key,
    @Parameter(in = ParameterIn.PATH, name = "defaultValue", description = "缓存默认value,下次访问还是这个值")
    @PathVariable("defaultValue") String defaultValue) {
    return defaultValue;
}

//实体类
@Schema(title = "example user")
public class ExampleUser{
    @Schema(title = "用户名")
    private String username;
}

# apiDoc

注意:后端项目默认打开api doc,生产环境建议关闭!

//关闭配置
springdoc:
  apiDocs:
    enabled: false

api doc链接:http://localhost:10001/doc.html#/home

为了方便测试,可调用一站式auth example接口拿到example用户token: http://localhost:9200/test/user/token/example

获取exampleUserToken图

api doc设置token

apiDoc设置token图

参数名称:Authorization

参数值:Bearer <token>

参数类型:header


即可使用

使用swagger图

# 系统日志

@BywinCloudRequestLog

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface BywinCloudRequestLog {

    /**
     * 模块
     */
    String title() default "";

    /**
     * 功能
     */
    BusinessType businessType() default BusinessType.OTHER;

    /**
     * 操作人类别
     */
    OperatorType operatorType() default OperatorType.MANAGE;

    /**
     * 是否保存请求的参数
     */
    boolean saveParameters() default true;

    /**
     * 保存参数时,忽略序列化以下类型,默认,ServletResponse.class, ServletRequest.class,
     */
    Class<?>[] ignoredParameterTypes() default {};

    boolean disable() default false;
}

使用示例

@BywinCloudRequestLog(title = "日志测试")
@Operation(summary = "日志测试")
@GetMapping("/example/{arg1}/{arg2}")
public String[] example1(@PathVariable("arg1") String arg1, @PathVariable("arg2") String arg2) {
    return new String[]{arg1, arg2};
}

控制台DEBUG日志说明

引入配置

logging:
  level:
    com:
      bywin: DEBUG
      example: DEBUG

请求api会在控制台打印相关返回,并带出请求id,执行用时等,如

...

bywin cloud destroy request id : 8PJRYAJWNoisB6wV54fz5, duration: 56 ms <====

# 缓存

# spring缓存

# 方式1.注解方式

@Cacheable(value = "bywin.cloud.cache-keys", key = "#key")

这里使用 @Cacheable 注解就可以将运行结果缓存,以后查询相同的数据,直接从缓存中取,不需要调用方法。key = '#key' 表示将参数key作为缓存的key

@Operation(summary = "缓存注解@Cacheable测试")
@Cacheable(value = "bywin.cloud.cache-keys", key = "#key")
@GetMapping("/cache/{key}/{defaultValue}")
public String cacheValue(
        @Parameter(in = ParameterIn.PATH, name = "key", description = "缓存key")
        @PathVariable("key") String key,
        @Parameter(in = ParameterIn.PATH, name = "defaultValue", description = "缓存默认value,下次访问还是这个值")
        @PathVariable("defaultValue") String defaultValue) {
    return defaultValue;
}

# 方式2.编码方式

存在则用旧值,不存在则用新值,并进行缓存。

@Operation(summary = "简单缓存测试")
@GetMapping("/simple-cache/{key}/{value}")
public String getSimpleCache(
        @Parameter(in = ParameterIn.PATH, name = "key", description = "缓存key")
        @PathVariable("key") String key,
        @Parameter(in = ParameterIn.PATH, name = "value", description = "缓存值")
        @PathVariable("value") String value) {

    return bywinCloudCache.computeIfChanged(key, oldValue -> {
        if (oldValue == null) {
            return value;
        }
        return oldValue;
    });

}


# spring缓存增强,引入过期时间

private final Cache cache;
private final BywinCloudCache bywinCloudCache;
private static final String BYWIN_CLOUD_CACHE_TEST = "bywin-cloud-cache-test";

public BywinCloudCacheExample(CacheManager cacheManager, BywinCloudCache bywinCloudCache) {
    this.cache = cacheManager.getCache(BYWIN_CLOUD_CACHE_TEST);
    this.bywinCloudCache = bywinCloudCache;
}

//10s过期样例
@Operation(summary = "缓存编程测试 设定10s过期")
@GetMapping("/get/{key}/{value}")
public BywinCloudResponse<CacheWrapper> get(
        @Parameter(in = ParameterIn.PATH, name = "key", description = "缓存key")
        @PathVariable("key") String key,
        @Parameter(in = ParameterIn.PATH, name = "value", description = "缓存值 (不过期则返回之前的缓存值,过期则用新传入的这个值,进行重新缓存)")
        @PathVariable("value") String value) {
    final BywinCloudResponse<CacheWrapper> bywinCloudResponse = new BywinCloudResponse<>();

    final String cacheType = cache.getClass().getName();

    bywinCloudResponse.setCode(BywinCloudResponseCode.OK.getCode());

    bywinCloudResponse.setData(CacheUtils.get(cache, key, cacheWrapper -> {

        final long now = new Date().getTime();

        if (cacheWrapper == null || cacheWrapper.getExpiredDate().getTime() < now) {

            if (cacheWrapper == null) {

                bywinCloudResponse.setMessage("{0}, key: {1}, not exist , now create it", cacheType, key);

            } else {

                bywinCloudResponse.setMessage("{0}, key: {1} was expired, now renew it", cacheType, key);
            }

            cacheWrapper = CacheWrapper.builder()
                    .expiredDate(new Date(now + 10 * 1000))
                    .key(key)
                    .value(value)
                    .build();


        } else {
            bywinCloudResponse.setMessage("{0}, key {1} already exists, use cache", cacheType, key);
        }

        return cacheWrapper;

    }));


    return bywinCloudResponse;

}

# redis缓存

private final BywinCloudSimpleRedisCache redisCache;

@Operation(summary = "redis缓存测试: get(key)")
@GetMapping("/redis/get/{key}")
public Object getCache(@Parameter(in = ParameterIn.PATH, name = "key", description = "缓存key")
                        @PathVariable("key") String key) {
    return redisCache.get(key);
}

@Operation(summary = "redis缓存测试: put(key, value)")
@GetMapping("/redis/put/{key}/{value}")
public void getCache(@Parameter(in = ParameterIn.PATH, name = "key", description = "缓存key")
                        @PathVariable("key") String key,
                        @Parameter(in = ParameterIn.PATH, name = "value", description = "缓存值")
                        @PathVariable("value") String value) {
    redisCache.put(key, value);
}

# 新增子模块

复制svc-template-server项目,更名成svc-xxxx-server(xxxx为新服务名) copyPorj.jpg

修改pom.xml,更正artifactId,加载为maven项目 updatePom.jpg

更改包名和启动类名,如xxxx updatePackName.jpg

项目根pom文件中,modules加入这个新的module,组成父子项目 根pom加新module

# 文件能力

# 上传文件

bywinCloudFileClient.upload

/**
 * 上传文件
 *
 * @return BywinCloudResponse<String> 文件id
 */
@Operation(summary = "上传文件")
@PostMapping(value = "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public BywinCloudResponse<String> upload(@RequestPart(value = "file") MultipartFile file) {
    return bywinCloudFileClient.upload(file);
}

# 删除文件

bywinCloudFileClient.remove

/**
 * 删除文件
 *
 * @return BywinCloudResponse<?>
 */
@Operation(summary = "删除文件")
@PostMapping("/file/remove")
public BywinCloudResponse<?> remove() {
    List<String> ids = new ArrayList<>();
    ids.add("1");
    paramMap.put("ids", ids);
    return bywinCloudFileClient.remove(paramMap);
}

# 获取文件

bywinCloudFileClient.getInfo

/**
 * 获取文件
 *
 * @return BywinCloudResponse<FileInfo>
 */
@Operation(summary = "获取文件")
@GetMapping("/file/getInfo")
public BywinCloudResponse<FileInfo> getInfo(@RequestParam("id") String id) {
    return bywinCloudFileClient.getInfo(id);
}

# 批量获取文件

bywinCloudFileClient.getInfos

/**
 * 批量获取文件
 *
 * @return BywinCloudResponse<List < FileInfo>>
 */
@Operation(summary = "批量获取文件")
@GetMapping("/file/getInfos")
public BywinCloudResponse<List<FileInfo>> getInfos(@RequestParam("ids") String ids) {
    return bywinCloudFileClient.getInfos(ids);
}

# 获取文件预览URL

bywinCloudFileClient.getViewUrl

/**
 * 获取文件预览url
 *
 * @return BywinCloudResponse<?>
 */
@Operation(summary = "获取文件预览url")
@GetMapping("/file/viewUrl")
public BywinCloudResponse<?> getViewUrl(@RequestParam("id") String id) {
    return bywinCloudFileClient.getViewUrl(id);
}

# 消息能力

# 发送短信

发送短信,通常用于验证码发送。

bywinCloudMsgClient.sendSMSSingle

/**
 * 发送短信
 *
 * @return BywinCloudResponse<?>
 */
@Operation(summary = "发送短信")
@PostMapping("/mail/sendSMSSingle")
public BywinCloudResponse<?> sendSMSSingle() {
    String sendTo = "15555555555";
    String content = "1234";
    String preKey = "sms prefix redis key-"; //检测频繁调用的缓存前缀key
    long timeout = 2000; //检测频繁调用间隔
    return bywinCloudMsgClient.sendSMSSingle(sendTo, content, preKey, timeout);
}

群发短信

bywinCloudMsgClient.sendSMS

/**
 * 群发短信
 *
 * @return BywinCloudResponse<?>
 */
@Operation(summary = "发送短信")
@PostMapping("/mail/sendSMS")
public BywinCloudResponse<?> sendSMS(@RequestParam("sendTo") String[] sendTo, @RequestParam("content") String content) throws Exception {
    return bywinCloudMsgClient.sendSMS(sendTo, content);
}

# 发送邮箱

发送邮箱

bywinCloudMsgClient.sendEmailSingle

/**
 * 发送邮箱
 *
 * @return BywinCloudResponse<?>
 */
@Operation(summary = "发送邮箱")
@PostMapping("/mail/sendEmailSingle")
public BywinCloudResponse<?> sendEmailSingle() {
    String sendTo = "999999999@qq.com";
    String content = "example content";

    String preKey = "email prefix redis key-"; //检测频繁调用的缓存前缀key
    long timeout = 2000; //检测频繁调用间隔
    return bywinCloudMsgClient.sendEmailSingle(sendTo, content, preKey, timeout);
}

群发邮箱

bywinCloudMsgClient.sendEmail

/**
 * 群发邮箱
 *
 * @return BywinCloudResponse<?>
 */
@Operation(summary = "发送邮箱")
@PostMapping("/mail/sendMail")
public BywinCloudResponse<?> sendEmail(@RequestParam("sendTo") String[] sendTo, @RequestParam("subject") String subject, @RequestParam("content") String content, @RequestParam(value = "files", required = false) MultipartFile[] files) throws Exception {
    //sendTo = new String[]{"username1", "username2"};
    //subject = "subject";
    //content = "example content";
    //files = null;

    return bywinCloudMsgClient.sendEmail(sendTo, subject, content, files);
}

# 通知公告能力

# 列表

bywinCloudNoticeClient.userNoticeList2

参数类

@Data
public class NoticeListParams extends BywinCloudPageQuery {
    /**
     * 接收人id 必填
     */
    private Long jsrId;

    /**
     * 已读状态 true/false
     */
    private String ydzt;

    /**
     * 限制条数
     */
    private Integer limit;

    /**
     * 类型 通知/公告
     */
    private String lx;

    /**
     * 标题
     */
    private String bt;

    /**
     * eq 标题 搜索
     */
    private String eqBt;
}
/**
 * 通知列表
 *
 * @return BywinCloudPageResponse<?>
 */
@Operation(summary = "通知列表")
@GetMapping("/ggRead/userNoticeList2")
public BywinCloudPageResponse<?> userNoticeList2(NoticeListParams params) {
    return bywinCloudNoticeClient.userNoticeList2(params);
}

# 发送

bywinCloudNoticeClient.save

参数说明

@Data
@Schema(title = "通知实体类")
public class GgInfo implements Serializable {
    private static final long serialVersionUID = 1L;

    private Long id;

    @Schema(title = "外部消息推送id")
    private Long messageCenterSendId;

    @Schema(title = "应用id")
    private Long appId;

    @Schema(title = "0认证 1低代码")
    private Integer appType;

    @Schema(title = "公告标题")
    private String bt;

    @Schema(title = "公告类型 (通知/公告)")
    private String lx;

    /**
     * 公告内容
     */
    @Schema(title = "公告内容")
    private String nr;

    /**
     * 公告有效期时间
     */
    @Schema(title = "公告有效期时间")
    private String yxsj;

    /**
     * 公告发布时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Schema(title = "公告发布时间")
    private Date fbsj;

    /**
     * 公告发布部门id
     */
    @Schema(title = "公告发布部门id")
    private Long fbbmid;

    /**
     * 公告发布部门名称
     */
    @Schema(title = "公告发布部门名称")
    private String fbbmmc;

    /**
     * 公告接收学院
     */
    @Schema(title = "公告接收学院 deptId,多个逗号隔开")
    private String jsxy;

    /**
     * 公告接收角色
     */
    @Schema(title = "公告接收角色 roleId,多个逗号隔开")
    private String jsjs;

    /**
     * 公告接收用户
     */
    @Schema(title = "公告接收用户 userId,多个逗号隔开")
    private String jsyh;

    /**
     * 类别 1 教务 2 学工 3 科研
     */
    @Schema(title = "类别")
    private String lb;

    /**
     * 公告置顶 0不置顶1置顶
     */
    @Schema(title = "公告置顶")
    private boolean zd;


    private String createBy;

    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;

    /**
     * 更新者
     */
    private String updateBy;

    /**
     * 更新时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;

    /**
     * 公告状态(0草稿 1发布)
     */
    @Schema(title = "公告状态 (0草稿 1发布)")
    private boolean status;
    
    //@TableField(exist = false)
    @Schema(title = "已读")
    private String yd;

    //@TableField(exist = false)
    @Schema(title = "未读")
    private String wd;

    @Schema(title = "是否跟进")
    private Boolean follow;

    @Schema(title = "是否必读")
    private Boolean readRequired;

    @Schema(title = "提醒是否启用")
    private Boolean noticeEnable;

    @Schema(title = "提醒规则模板id")
    private Long noticeRuleId;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Schema(title = "提醒结束时间")
    private Date noticeEndTime;

    @Schema(title = "单用户提醒次数上线")
    private Integer noticeUserMax;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Schema(title = "通知发送时间")
    private Date sendTime;

    @Schema(title = "发送方式 1.立即发送 2.定时发送")
    private Integer sendType;

    @Schema(title = "推送通道编号列表 逗号(,)分割")
    private String channelCodes;

    @Schema(title = "推送通道名称列表 逗号(,)分割")
    private String channelNames;
}
/**
 * 保存通知
 *
 * @return BywinCloudResponse<GgInfo>
 */
@Operation(summary = "保存通知")
@PostMapping("/ggInfo/save")
public BywinCloudResponse<GgInfo> save(@RequestBody GgInfo ggInfo) {
    return bywinCloudNoticeClient.save(ggInfo);
}

# 删除

bywinCloudNoticeClient.delete

/**
 * 删除通知
 *
 * @return BywinCloudResponse<?>
 */
@Operation(summary = "删除通知")
@GetMapping("/ggInfo/delete/{id}")
public BywinCloudResponse<?> delete(@PathVariable("id") Long id, @RequestParam(value = "appId", required = false) Long appId) {
    return bywinCloudNoticeClient.delete(id, appId);
}

# 置为已读

bywinCloudNoticeClient.viewNoticeApi

/**
 * 通知置为已读
 *
 * @return BywinCloudResponse<GgInfo>
 */
@Operation(summary = "通知置为已读")
@GetMapping("/ggRead/viewNoticeApi")
public BywinCloudResponse<GgInfo> viewNoticeApi(@RequestParam("id") Long id) {
    //id是公告阅读记录的id
    return bywinCloudNoticeClient.viewNoticeApi(id);
}

# 模板能力

# 参数说明

@ApiModelProperty("通道id")
private Long noticeInfoId;

@ApiModelProperty("模板类型")
private String type;

@ApiModelProperty("内容")
private String content;

@ApiModelProperty("模板")
private String templateId;

@ApiModelProperty("标题")
private String title;

# 获取通道列表

@GetMapping("/message/channel/list")
public TableDataInfo<?> list(MessageCenterChannelQueryParams params)

# 获取通道详情和模板列表

@Log(title = "消息通道", businessType = BusinessType.GETDATA)
@ApiOperation("根据id获取详情")
@GetMapping("/message/channel/getInfo")
public R<?> getInfo(@RequestParam(CommonTable.Field.ID) Long id)

# 通道能力实现发送

传入的参数可以是用户id,也可以是指定类型的数据,比如邮箱地址,微信个人id

其中noticeDataMap模板对应内容 为模板中的内容对应的键值对,如模板中的内容试:"我的验证码试${code}"。 其中这个noticeDataMap传入的键值对"code":"1111"

@ApiModelProperty("用户id")
private List<String> userNames;

@ApiModelProperty("通道名称")
private String channlName;

@ApiModelProperty("通道代码")
private String channlCode;

@ApiModelProperty("模板Id")
private String templateId;

@ApiModelProperty("模板对应内容map")
private Map<String, Object> noticeDataMap;
@Log(title = "消息通道-能力集成", businessType = BusinessType.OTHER)
@ApiOperation("钉钉、恒峰通知、消息发送-邮件、企业微信、微信公众号、系统通知")
@PostMapping("/message/chanel/Capability")
public R<?> sendingCapabilityIntegration(@RequestBody SendCapabilityVO sendCapabilityVO)

# 工作流能力

详细集成说明 (opens new window)

# 流程发起

BywinCloudWorkflowClient.taskAction()

/**
 * 流程审批操作
 *
 * @param request 流程审批操作实体类
 * @return 节点信息
 */
@PostMapping("/workFlow/taskAction")
BywinCloudResponse<TaskMeta> taskAction(@RequestBody TaskActionRequest request);

需要传递的流程的参数: procDefKey: 流程唯一标识 action: 审批动作(1. 通过 2.拒绝 3.撤回 4.退回 5.转发 9.提交 0.保存) assigneeList 下一节点审批人 ccList 抄送人员工号 variables 流程分支变量 businessKey 必填 命名格式为 模块缩写:业务id

# 流程审批

BywinCloudWorkflowClient.taskAction()

/**
 * 流程审批操作
 *
 * @param request 流程审批操作实体类
 * @return 节点信息
 */
@PostMapping("/workFlow/taskAction")
BywinCloudResponse<TaskMeta> taskAction(@RequestBody TaskActionRequest request);

需要传递的流程字段: 发起: assigneeList action procDefKey ccList variables businessKey startUsername 同意/拒绝 id taskId comment assigneeList action 撤回 id taskId action 退回 id taskId action assigneeList

# 流程列表

BywinCloudWorkflowClient.taskProcessList()

/**
    * 查询用户相关流程实例id列表
    *
    * @param request 请求体
    * @return 流程实例id列表
    */
@GetMapping("/workFlow/listYw")
BywinCloudResponse<List<String>> taskProcessList(@SpringQueryMap TaskProcessRequest request);

参数

public class TaskProcessRequest {
    /**
     * 分类名称
     */
    private String typeName;

    /**
     * 查询用户工号,默认为当前登陆用户
     */
    private String userName;

    /**
     * 流程所属的应用id
     */
    private Long appId;

    /**
     * listType:  1.待办 2.已办 3.关于我的 4.我的发起
     */
    private String listType;
}

# 查询流程实例权限

查询当前登陆用户在当前流程实例的权限

BywinCloudWorkflowClient.authority

@PostMapping("/workFlow/authority")
BywinCloudResponse<TaskAuthority> authority(@RequestParam(FlowConstants.PROCESS_INSTANCE_ID_FIELD) String processInstanceId,@RequestParam(FlowConstants.KEY_LIST_TYPE) Object listType);

参数: processInstanceId 流程实例id listType 列表类型 0.发起 1.待办 2.已办 3抄送


返回类:

public class TaskAuthority implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 是否可以审批(null值为否,有值为真)
     */
    private Boolean canApproval;

    /**
     * 是否可以撤回(null值为否,有值为真)
     */
    private String canChe;

    /**
     * 是否可以退回(null值为否,有值为真)
     */
    private String canTui;

    /**
     * 是否可以加签(null值为否,有值为真)
     */
    private String canAddSign;

    /**
     * 是否可以编辑(null值为否,有值为真)
     */
    private String canEdit;

    /**
     * 是否可以转发(null值为否,有值为真)
     */
    private String canForward;

    /**
     * 是否可以抄送(null值为否,有值为真)
     */
    private String canCc;

    /**
     * 是否可以同意(null值为否,有值为真)
     */
    private String canPass;

    /**
     * 是否可以拒绝(null值为否,有值为真)
     */
    private String canRefuse;

}

# 删除流程

BywinCloudWorkflowClient.delTask

/**
 * 删除流程示例
 *
 * @param processInstanceId 流程实例id
 * @return 操作结果
 */
@PostMapping("/workFlow/delTask")
BywinCloudResponse<Void> delTask(@RequestParam(FlowConstants.PROCESS_INSTANCE_ID_FIELD) String processInstanceId);

# 查询节点候选人

BywinCloudWorkflowClient.chooseAssignee

/**
 * 查询节点候选人
 *
 * @param request 请求体
 * @return 候选人信息
 */
@PostMapping("/workFlow/chooseAssignee")
BywinCloudResponse<Assignees> chooseAssignee(@RequestBody ChooseAssigneeRequest request);

参数:

public class ChooseAssigneeRequest implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 流程实例id
     */
    private String processInstanceId;

    /**
     * 流程定义key
     */
    private String procDefKey;

    /**
     * 跳过节点数 (0. 查询当前节点 1.查询下一节点),默认为0
     */
    private Integer skip;

    /**
     * 分支变量
     */
    private Map<String, Object> formData;
}

# 事务中心能力

BywinCloudApprovalClient

# 新增

@PostMapping("/approval/todo/add")
BywinCloudResponse<String> todoAdd(@RequestBody ActApprovalTodoRequest request);

请求体

参数名 描述 类型 为空 备注
taskName 审批节点名称 String 必填
approvalUrl 审批模块详情页地址 String 第三方应用需要与认证应用填写的回调地址对应
procDefName 流程名称 String 必填
assignee 待办人工号 String 必填
createTime 发起时间 Date 必填 yyyy-MM-dd HH:mm:ss
processInstanceId 流程实例唯一id String 必填 保证全系统唯一,建议使用UUID
endTime 结束时间 Date yyyy-MM-dd HH:mm:ss
startUserName 流程发起人工号 String 必填
approvalTerminal 审批终端 String 填pc或者mobile,多个逗号用隔开,默认值:pc,mobile
approvalListUrl 审批模块列表地址 String

请求示例

{
    "taskName": "管理员审批",
    "approvalUrl": "http://192.168.0.135:8101/pcldata-auth/auth/casCallback?menuPath=/DataDevelop/DataSourceManage",
    "procDefName": "测试流程",
    "assignee": "admin",
    "createTime": "2023-05-03 12:32:12",
    "processInstanceId": "f6e6fa4d-21e5-466b-9d9f-3ebd3228378e",
    "endTime": "2023-05-04 12:32:12",
    "startUserName": "admin",
    "approvalTerminal": "pc,mobile",
    "approvalListUrl": "http://192.168.0.135:8101/pcldata-auth/auth/casCallback?menuPath=/DataDevelop/DataSourceManage"
}

返回参数

参数名 描述
code 返回标识(0.正常 500.错误)
msg 操作信息
data messageId (后续更新或删除时使用)

返回示例

{
    "code": 0,
    "msg": "操作成功",
    "data": 101
}

# 更新

@PostMapping("/approval/todo/update")
BywinCloudResponse<Void> todoUpdate(@RequestBody ActApprovalTodoRequest request);

请求体

参数名 描述 类型 为空 备注
messageId 消息id Long 必填
taskName 审批节点名称 String
approvalUrl 审批模块详情页地址 String 第三方应用需要与认证应用填写的回调地址对应
procDefName 流程名称 String
assignee 待办人工号 String
createTime 发起时间 Date yyyy-MM-dd HH:mm:ss
processInstanceId 流程实例唯一id String 保证全系统唯一,建议使用UUID
endTime 结束时间 Date yyyy-MM-dd HH:mm:ss
startUserName 流程发起人工号 String 必填
approvalTerminal 审批终端 String 填pc或者mobile,多个逗号用隔开,默认值:pc,mobile
approvalListUrl 审批模块列表地址 String

请求示例

{
    "messageId": 101,
    "taskName": "管理员审批",
    "approvalUrl": "http://192.168.0.135:8101/pcldata-auth/auth/casCallback?menuPath=/DataDevelop/DataSourceManage",
    "procDefName": "测试流程",
    "assignee": "admin",
    "createTime": "2023-05-03 12:32:12",
    "processInstanceId": "f6e6fa4d-21e5-466b-9d9f-3ebd3228378e",
    "endTime": "2023-05-04 12:32:12",
    "startUserName": "admin",
    "approvalTerminal": "pc,mobile",
    "approvalListUrl": "http://192.168.0.135:8101/pcldata-auth/auth/casCallback?menuPath=/DataDevelop/DataSourceManage"
}

返回参数

参数名 描述
code 返回标识(0.正常 500.错误)
msg 操作信息
data 返回数据

返回示例

{
    "code": 0,
    "msg": "操作成功",
    "data": null
}

# 删除

@PostMapping("/approval/todo/remove")
BywinCloudResponse<Void> todoRemove(@RequestBody ActApprovalTodoRequest request);

请求体

参数名 描述 类型 为空 备注
messageId 消息id Long 必填

请求示例

messageId=101

返回参数

参数名 描述
code 返回标识(0.正常 500.错误)
msg 操作信息
data 返回数据

返回示例

{
    "code": 0,
    "msg": "操作成功",
    "data": null
}

# 新增或更新流程实例

@PostMapping("/approval/process/update")
BywinCloudResponse<Void> processUpdate(@RequestBody ActApprovalTodoRequest request);

请求体

参数名 描述 类型 为空 备注
processInstanceId 流程实例id String 必填
status 状态 Integer
endTime 结束时间 Date yyyy-MM-dd HH:mm:ss
startUserName 发起人工号 String
delFlag 删除标识 Integer -1. 删除 0. 正常(删除后无法再进行修改)

请求示例

{
    "processInstanceId": "f6e6fa4d-21e5-466b-9d9f-3ebd3228378e",
    "status": 2,
    "endTime": "2023-05-04 12:32:12",
    "startUserName": "admin",
    "delFlag": 0
}

返回参数

参数名 描述
code 返回标识(0.正常 500.错误)
msg 操作信息
data 返回数据

返回示例

{
    "code": 0,
    "msg": "操作成功",
    "data": null
}

# RBAC能力

# 部门

BywinCloudSystemDeptClient

# 示例

private final BywinCloudSystemDeptClient deptClient;

/**
 * 部门列表
 *
 * @param dept
 * @return
 */
@GetMapping("/dept/listR")
public List<SysDept> listR(@SpringQueryMap SysDept dept) {
    dept.setApplicationId(0L);

    return deptClient.listR(dept);
}

# 列表


参数列表(都非必填)

参数名 备注
parentId 父部门id
deptName 部门名称
eqDeptName 精准匹配部门名称
deptType 部门类型
deptNo 部门号
status 状态
deptIds in部门id列表
orgId 组织id
pageNum 页码
pageSize 页数据量

@GetMapping("/dept/listR")
List<SysDept> listR(@SpringQueryMap SysDept dept);

# 详情

@GetMapping(value = "/dept/getById")
BywinCloudResponse<SysDept> getById(@RequestParam("deptId") Long deptId);

# 添加

@PostMapping("/dept")
BywinCloudResponse<Long> add(@RequestBody SysDept dept);

# 更新

@PutMapping("/dept")
BywinCloudResponse<?> edit(@RequestBody SysDept dept);

# 删除

@DeleteMapping("/dept/{deptId}")
BywinCloudResponse<?> remove(@PathVariable("deptId") Long deptId, @RequestParam(value = "applicationId", required = false) Long applicationId);

# 菜单

BywinCloudSystemMenuClient

# 示例

private final BywinCloudSystemMenuClient menuClient;

/**
 * 菜单列表
 * @param menu
 * @return
 */
@GetMapping("/menu/list")
BywinCloudResponse<?> list(@SpringQueryMap SysMenu menu) {
    menu.setApplicationId(0L);
    return menuClient.list(menu);
}

# 列表


参数列表(都非必填)

参数名 备注
menuKey 菜单key
menuName 菜单名
visible 是否可见
status 状态
orgId 组织id
pageNum 页码
pageSize 页数据量

@GetMapping("/menu/list")
BywinCloudResponse<?> list(@SpringQueryMap SysMenu menu);

# 添加

@PostMapping("/menu")
BywinCloudResponse<Long> add(@RequestBody SysMenu menu);

# 更新

@PutMapping("/menu")
BywinCloudResponse<?> edit(@RequestBody SysMenu menu);

# 删除

@DeleteMapping("/menu/{menuId}")
BywinCloudResponse<?> remove(@PathVariable("menuId") Long menuId, @RequestParam(value = "applicationId", required = false) Long applicationId);

# 角色

BywinCloudSystemRoleClient

# 示例

private final BywinCloudSystemRoleClient roleClient;

/**
 * 角色列表
 * @param sysRole
 * @return
 */
@GetMapping("/role/listR")
BywinCloudPageResponse<?> list(@SpringQueryMap SysRole sysRole) {
    sysRole.setApplicationId(0L);

    return roleClient.list(sysRole);
}

# 列表


参数列表(都非必填)

参数名 备注
roleType 角色类型
parentId 父角色id
roleName 角色名
status 状态
roleKey 角色key
roleIds in角色id集合
orgId 组织id
pageNum 页码
pageSize 页数据量

@GetMapping("/role/listR")
BywinCloudPageResponse<?> list(@SpringQueryMap SysRole sysRole);

# 详情

@GetMapping("/role/getRoleInfo/{roleKey}")
SysRole getRoleInfo(@PathVariable("roleKey") String roleKey);

@GetMapping("/role/getRoleInfoByRoleId/{roleId}")
SysRole getRoleInfoByRoleId(@PathVariable("roleId") Long roleId);

# 添加

@PostMapping("/role")
BywinCloudResponse<Long> add(@RequestBody SysRole role);

# 更新

@PutMapping("/role")
BywinCloudResponse<?> edit(@RequestBody SysRole role);

# 删除

@DeleteMapping("/role/{roleIds}")
BywinCloudResponse<?> remove(@PathVariable("roleIds") Long[] roleIds, @RequestParam(value = "applicationId", required = false) Long applicationId);

# 获取某个username的所有授权角色

@GetMapping("/role/selectRolesByUserName/{userName}")
BywinCloudResponse<List<SysRole>> selectRolesByUserName(@PathVariable("userName") String userName);

# 用户

BywinCloudSystemUserClient

# 示例

private final BywinCloudSystemUserClient userClient;

/**
 * 用户列表
 *
 * @param params
 * @return
 */
@PostMapping("/user/listUserBySearchR")
BywinCloudResponse<List<SysUser>> listUserBySearchR(@RequestBody SysUserSearchRequest params) {
    params.setUserName("admin");

    return userClient.listUserBySearchR(params);
}

# 列表


参数列表(都非必填)

参数名 备注
roleKey 角色key
status 状态
noRoleKey 非角色key
userName 用户名
nickName 昵称
phonenumber 手机号
deptIds in部门id集合
roleIds in角色id集合
userIds in用户id集合
roleId 角色id
deptId 部门id
orgId 组织id
pageNum 页码
pageSize 页数据量

//不分页
@PostMapping("/user/listUserBySearchR")
BywinCloudResponse<List<SysUser>> listUserBySearchR(@RequestBody SysUserSearchRequest params);

//分页
@PostMapping("/user/listUserBySearchPage")
BywinCloudPageResponse<SysUser> listUserBySearchPage(@RequestBody SysUserSearchRequest params);

//所有用户
@GetMapping("/user/listAllUser")
BywinCloudResponse<List<SysUser>> listAllUser();

# 详情

@PostMapping("/user/getUserById")
BywinCloudResponse<SysUser> getUserById(@RequestParam("userId") String userId);

@PostMapping("/user/getUserByPhonenumber")
BywinCloudResponse<SysUser> getUserByPhonenumber(@RequestParam("phonenumber") String phonenumber);

@PostMapping("/user/getUserByName")
BywinCloudResponse<SysUser> getUserByName(@RequestParam("userName") String userName);

# 添加

@PostMapping("/user")
BywinCloudResponse<?> add(@RequestBody SysUser user);

# 更新

@PutMapping("/user")
BywinCloudResponse<?> edit(@RequestBody SysUser user);

# 删除

@DeleteMapping("/user/{userIds}")
BywinCloudResponse<?> remove(@PathVariable("userIds") Long[] userIds);

# 根据角色key 获取有该授权用户列表

@GetMapping("/user/listByRoleKey/{roleKey}")
BywinCloudResponse<List<SysUser>> userListByRoleKey(@PathVariable("roleKey") String roleKey);

# 根据角色id或部门id 获取有该授权用户列表

@PostMapping("/user/getUserIdByRoleIdOrDeptId/post")
BywinCloudResponse<List<SysUser>> getUserIdByRoleIdOrDeptIdPost(@RequestBody SysUserRole sysUserRole);

# 用户授权

BywinCloudSystemUserClient

# 示例

private final BywinCloudSystemUserClient userClient;

/**
 * 用户列表
 *
 * @param params
 * @return
 */
@PostMapping("/user/listUserBySearchR")
BywinCloudResponse<List<SysUser>> listUserBySearchR(@RequestBody SysUserSearchRequest params) {
    params.setUserName("admin");

    return userClient.listUserBySearchR(params);
}

# 获取用户与角色和部门的关系 根据userId

@PostMapping("/user/listUserRoleByUserId")
BywinCloudResponse<List<SysUserRole>> listUserRoleByUserId(@RequestParam("userId") String userId) {
    return userClient.listUserRoleByUserId(userId);
}

# 获取用户与角色和部门的关系 根据应用id,角色id

@PostMapping("/user/listUserRoleByRoleIdAndAppId")
BywinCloudResponse<List<SysUserRole>> listUserRoleByRoleIdAndAppId(@RequestBody SysUserRole userRole) {
    return userClient.listUserRoleByRoleIdAndAppId(userRole);
}

# 批量新增用户授权

@PostMapping("/user/batchAppListUserRoleR")
BywinCloudResponse<List<SysUserRole>> batchAppListUserRoleR(@RequestBody List<SysUserRole> list) {
    return userClient.batchAppListUserRoleR(list);
}

# 批量更新用户授权

@PostMapping("/user/editUserRoleDeptApp")
BywinCloudResponse<Map<String, List<SysUserRole>>> editUserRoleDeptApp(@RequestBody SysUserRoleAppDeptRequest userRoleAppDeptVO) {
    return userClient.editUserRoleDeptApp(userRoleAppDeptVO);
}

# 批量删除用户授权

@PostMapping("/user/deleteAppUserRole")
BywinCloudResponse<?> deleteAppUserRole(@RequestBody List<SysUserRole> sysUserRole) {
    return userClient.deleteAppUserRole(sysUserRole);
}