后端:增加 Banner 增删改查接口

This commit is contained in:
YunaiV 2019-03-30 21:57:01 +08:00
parent 0256a4da17
commit 4595db1d4c
41 changed files with 1543 additions and 19 deletions

View File

@ -87,7 +87,7 @@ public class AdminController {
@ApiOperation(value = "管理员分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "nickname", value = "昵称,模糊匹配", example = "小王"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 0 开始", example = "0"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<AdminPageVO> page(@RequestParam(value = "nickname", required = false) String nickname,

View File

@ -38,7 +38,7 @@ public class RoleController {
@ApiOperation(value = "角色分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "角色名,模糊匹配", required = true, example = "系统管理员"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 0 开始", example = "0"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<RolePageVO> page(@RequestParam(value = "name", required = false) String name,

View File

@ -4,6 +4,9 @@ import javax.validation.constraints.NotNull;
public class AdminPageDTO {
/**
* 昵称模糊匹配
*/
private String nickname;
@NotNull(message = "页码不能为空")

View File

@ -28,7 +28,7 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service("test")
@Service
@com.alibaba.dubbo.config.annotation.Service(validation = "true")
public class AdminServiceImpl implements AdminService {

View File

@ -40,4 +40,12 @@ public enum CommonStatusEnum {
return this;
}
public static boolean isValid(Integer status) {
if (status == null) {
return false;
}
return ENABLE.value.equals(status)
|| DISABLE.value.equals(status);
}
}

View File

@ -21,6 +21,7 @@
<module>admin</module>
<module>ops</module>
<module>pay</module>
<module>promotion</module>
</modules>
<packaging>pom</packaging>

View File

@ -107,7 +107,7 @@ public class AdminsProductSpuController {
@ApiOperation("商品 SPU 分页列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "商品名称,模糊匹配", example = "小王"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 0 开始", example = "0"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<AdminsProductSpuPageVO> spuPage(@RequestParam(value = "name", required = false) String name,

View File

@ -36,7 +36,7 @@ public class UsersProductSpuController {
@ApiOperation("商品 SPU 分页列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "cid", value = "分类编号", example = "1"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 0 开始", example = "0"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<UsersProductSpuPageVO> page(@RequestParam(value = "cid", required = false) Integer cid,

View File

@ -20,6 +20,4 @@ public interface ProductCategoryMapper {
int update(ProductCategoryDO productCategoryDO);
}

20
promotion/pom.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mall-parent</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>promotion</artifactId>
<packaging>pom</packaging>
<modules>
<module>promotion-service-api</module>
<module>promotion-service-impl</module>
<module>promotion-application</module>
</modules>
</project>

View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>promotion</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>promotion-application</artifactId>
<properties>
<org.mapstruct.version>1.3.0.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>promotion-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>promotion-service-impl</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-sdk</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>admin-sdk</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 提供给 mapstruct 使用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source> <!-- or higher, depending on your project -->
<target>1.8</target> <!-- or higher, depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package cn.iocoder.mall.promotion.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.promotion"})
public class PromotionApplication {
public static void main(String[] args) {
SpringApplication.run(PromotionApplication.class, args);
}
}

View File

@ -0,0 +1,51 @@
package cn.iocoder.mall.promotion.application.config;
import cn.iocoder.common.framework.config.GlobalExceptionHandler;
import cn.iocoder.common.framework.servlet.CorsFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
@Configuration
@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
// AdminSecurityInterceptor.class
})
public class MVCConfiguration implements WebMvcConfigurer {
// @Autowired
// private UserSecurityInterceptor securityInterceptor;
// @Autowired
// private AdminSecurityInterceptor adminSecurityInterceptor;
// @Autowired
// private AdminAccessLogInterceptor adminAccessLogInterceptor;
//
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(securityInterceptor).addPathPatterns("/user/**", "/admin/**"); // 只拦截我们定义的接口
// registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
// registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 解决 swagger-ui.html 的访问参考自 https://stackoverflow.com/questions/43545540/swagger-ui-no-mapping-found-for-http-request 解决
registry.addResourceHandler("swagger-ui.html**").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
registry.addResourceHandler("webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new CorsFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.mall.promotion.application.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2 // TODO 生产环境时禁用掉
public class SwaggerConfiguration {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.promotion.application.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("营销子系统")
.description("营销子系统")
.termsOfServiceUrl("http://www.iocoder.cn")
.version("1.0.0")
.build();
}
}

View File

@ -0,0 +1,99 @@
package cn.iocoder.mall.promotion.application.controller.admins;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
import cn.iocoder.mall.promotion.api.BannerService;
import cn.iocoder.mall.promotion.api.bo.BannerPageBO;
import cn.iocoder.mall.promotion.api.dto.BannerAddDTO;
import cn.iocoder.mall.promotion.api.dto.BannerPageDTO;
import cn.iocoder.mall.promotion.api.dto.BannerUpdateDTO;
import cn.iocoder.mall.promotion.application.convert.BannerConvert;
import cn.iocoder.mall.promotion.application.vo.BannerPageVO;
import cn.iocoder.mall.promotion.application.vo.BannerVO;
import com.alibaba.dubbo.config.annotation.Reference;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("admins/banner")
@Api("Banner 模块")
public class AdminsBannerController {
@Reference(validation = "true")
private BannerService bannerService;
@GetMapping("/page")
@ApiOperation(value = "Banner 分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "title", value = "标题,模糊匹配", example = "活动 A"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<BannerPageVO> page(@RequestParam(value = "title", required = false) String title,
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
CommonResult<BannerPageBO> result = bannerService.getBannerPage(new BannerPageDTO().setTitle(title).setPageNo(pageNo).setPageSize(pageSize));
return BannerConvert.INSTANCE.convert(result);
}
@PostMapping("/add")
@ApiOperation(value = "创建 Banner")
@ApiImplicitParams({
@ApiImplicitParam(name = "title", value = "标题", required = true, example = "活动A"),
@ApiImplicitParam(name = "url", value = "跳转链接", required = true, example = "http://www.iocoder.cn"),
@ApiImplicitParam(name = "picUrl", value = "图片链接", required = true, example = "http://www.iocoder.cn/01.jpg"),
@ApiImplicitParam(name = "sort", value = "排序", required = true, example = "10"),
@ApiImplicitParam(name = "memo", value = "备注", required = true, example = "活动很牛逼"),
})
public CommonResult<BannerVO> add(@RequestParam("title") String title,
@RequestParam("url") String url,
@RequestParam("picUrl") String picUrl,
@RequestParam("sort") Integer sort,
@RequestParam(value = "memo", required = false) String memo) {
BannerAddDTO bannerAddDTO = new BannerAddDTO().setTitle(title).setUrl(url).setPicUrl(picUrl)
.setSort(sort).setMemo(memo);
return BannerConvert.INSTANCE.convert2(bannerService.addBanner(AdminSecurityContextHolder.getContext().getAdminId(), bannerAddDTO));
}
@PostMapping("/update")
@ApiOperation(value = "更新 Banner")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "Banner 编号", required = true, example = "1"),
@ApiImplicitParam(name = "url", value = "跳转链接", required = true, example = "http://www.iocoder.cn"),
@ApiImplicitParam(name = "picUrl", value = "图片链接", required = true, example = "http://www.iocoder.cn/01.jpg"),
@ApiImplicitParam(name = "sort", value = "排序", required = true, example = "10"),
@ApiImplicitParam(name = "memo", value = "备注", required = true, example = "活动很牛逼"),
})
public CommonResult<Boolean> update(@RequestParam("id") Integer id,
@RequestParam("title") String title,
@RequestParam("url") String url,
@RequestParam("picUrl") String picUrl,
@RequestParam("sort") Integer sort,
@RequestParam(value = "memo", required = false) String memo) {
BannerUpdateDTO bannerUpdateDTO = new BannerUpdateDTO().setId(id).setTitle(title).setUrl(url).setPicUrl(picUrl)
.setSort(sort).setMemo(memo);
return bannerService.updateBanner(AdminSecurityContextHolder.getContext().getAdminId(), bannerUpdateDTO);
}
@PostMapping("/update_status")
@ApiOperation(value = "更新 Banner 状态")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "Banner 编号", required = true, example = "1"),
@ApiImplicitParam(name = "status", value = "状态。1 - 开启2 - 禁用", required = true, example = "1"),
})
public CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id,
@RequestParam("status") Integer status) {
return bannerService.updateBannerStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status);
}
@PostMapping("/delete")
@ApiOperation(value = "删除 Banner")
@ApiImplicitParam(name = "id", value = "Banner 编号", required = true, example = "1")
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
return bannerService.deleteBanner(AdminSecurityContextHolder.getContext().getAdminId(), id);
}
}

View File

@ -0,0 +1,26 @@
package cn.iocoder.mall.promotion.application.convert;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.bo.BannerBO;
import cn.iocoder.mall.promotion.api.bo.BannerPageBO;
import cn.iocoder.mall.promotion.application.vo.BannerPageVO;
import cn.iocoder.mall.promotion.application.vo.BannerVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public interface BannerConvert {
BannerConvert INSTANCE = Mappers.getMapper(BannerConvert.class);
@Mappings({})
BannerVO convert(BannerBO bannerBO);
@Mappings({})
CommonResult<BannerVO> convert2(CommonResult<BannerBO> result);
@Mappings({})
CommonResult<BannerPageVO> convert(CommonResult<BannerPageBO> result);
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.mall.promotion.application.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
@ApiModel("Banner 分页 VO")
public class BannerPageVO {
@ApiModelProperty(value = "Banner 数组")
private List<BannerVO> list;
@ApiModelProperty(value = "Banner 总数")
private Integer total;
public List<BannerVO> getList() {
return list;
}
public BannerPageVO setList(List<BannerVO> list) {
this.list = list;
return this;
}
public Integer getTotal() {
return total;
}
public BannerPageVO setTotal(Integer total) {
this.total = total;
return this;
}
}

View File

@ -0,0 +1,99 @@
package cn.iocoder.mall.promotion.application.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
@ApiModel("Banner VO")
public class BannerVO {
@ApiModelProperty(value = "Banner 编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "标题", required = true, example = "活动 A")
private String title;
@ApiModelProperty(value = "跳转链接", required = true, example = "http://www.baidu.com")
private String url;
@ApiModelProperty(value = "突脸链接", required = true, example = "http://www.iocoder.cn/01.jpg")
private String picUrl;
@ApiModelProperty(value = "排序", required = true, example = "10")
private Integer sort;
@ApiModelProperty(value = "状态", required = true, example = "1")
private Integer status;
@ApiModelProperty(value = "备注", required = true, example = "这个活动很牛逼")
private String memo;
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
private Date createTime;
public Integer getId() {
return id;
}
public BannerVO setId(Integer id) {
this.id = id;
return this;
}
public String getTitle() {
return title;
}
public BannerVO setTitle(String title) {
this.title = title;
return this;
}
public String getUrl() {
return url;
}
public BannerVO setUrl(String url) {
this.url = url;
return this;
}
public Integer getSort() {
return sort;
}
public BannerVO setSort(Integer sort) {
this.sort = sort;
return this;
}
public Integer getStatus() {
return status;
}
public BannerVO setStatus(Integer status) {
this.status = status;
return this;
}
public String getMemo() {
return memo;
}
public BannerVO setMemo(String memo) {
this.memo = memo;
return this;
}
public Date getCreateTime() {
return createTime;
}
public BannerVO setCreateTime(Date createTime) {
this.createTime = createTime;
return this;
}
public String getPicUrl() {
return picUrl;
}
public BannerVO setPicUrl(String picUrl) {
this.picUrl = picUrl;
return this;
}
}

View File

@ -0,0 +1,9 @@
spring:
application:
name: promotion-application
# server
server:
port: 18085
servlet:
context-path: /promotion-api/

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>promotion</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>promotion-service-api</artifactId>
<dependencies>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,22 @@
package cn.iocoder.mall.promotion.api;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.bo.BannerBO;
import cn.iocoder.mall.promotion.api.bo.BannerPageBO;
import cn.iocoder.mall.promotion.api.dto.BannerAddDTO;
import cn.iocoder.mall.promotion.api.dto.BannerPageDTO;
import cn.iocoder.mall.promotion.api.dto.BannerUpdateDTO;
public interface BannerService {
CommonResult<BannerPageBO> getBannerPage(BannerPageDTO bannerPageDTO);
CommonResult<BannerBO> addBanner(Integer adminId, BannerAddDTO bannerAddDTO);
CommonResult<Boolean> updateBanner(Integer adminId, BannerUpdateDTO bannerUpdateDTO);
CommonResult<Boolean> updateBannerStatus(Integer adminId, Integer bannerId, Integer status);
CommonResult<Boolean> deleteBanner(Integer adminId, Integer bannerId);
}

View File

@ -0,0 +1,114 @@
package cn.iocoder.mall.promotion.api.bo;
import java.util.Date;
/**
* Banner BO
*/
public class BannerBO {
/**
* 编号
*/
private Integer id;
/**
* 标题
*/
private String title;
/**
* 跳转链接
*/
private String url;
/**
* 图片链接
*/
private String picUrl;
/**
* 排序
*/
private Integer sort;
/**
* 状态
*/
private Integer status;
/**
* 备注
*/
private String memo;
/**
* 创建时间
*/
private Date createTime;
public Integer getId() {
return id;
}
public BannerBO setId(Integer id) {
this.id = id;
return this;
}
public String getTitle() {
return title;
}
public BannerBO setTitle(String title) {
this.title = title;
return this;
}
public String getUrl() {
return url;
}
public BannerBO setUrl(String url) {
this.url = url;
return this;
}
public Integer getSort() {
return sort;
}
public BannerBO setSort(Integer sort) {
this.sort = sort;
return this;
}
public Integer getStatus() {
return status;
}
public BannerBO setStatus(Integer status) {
this.status = status;
return this;
}
public String getMemo() {
return memo;
}
public BannerBO setMemo(String memo) {
this.memo = memo;
return this;
}
public Date getCreateTime() {
return createTime;
}
public BannerBO setCreateTime(Date createTime) {
this.createTime = createTime;
return this;
}
public String getPicUrl() {
return picUrl;
}
public BannerBO setPicUrl(String picUrl) {
this.picUrl = picUrl;
return this;
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.mall.promotion.api.bo;
import java.util.List;
public class BannerPageBO {
/**
* Banner 数组
*/
private List<BannerBO> list;
/**
* 总量
*/
private Integer total;
public List<BannerBO> getList() {
return list;
}
public BannerPageBO setList(List<BannerBO> list) {
this.list = list;
return this;
}
public Integer getTotal() {
return total;
}
public BannerPageBO setTotal(Integer total) {
this.total = total;
return this;
}
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.mall.promotion.api.constant;
/**
* 错误码枚举类
*
* 营销系统使用 1-006-000-000
*/
public enum PromotionErrorCodeEnum {
// ========== Banner 模块 ==========
BANNER_NOT_EXISTS(1002002000, "账号不存在"),
;
private final int code;
private final String message;
PromotionErrorCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,72 @@
package cn.iocoder.mall.promotion.api.dto;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* Banner 添加 DTO
*/
public class BannerAddDTO {
@NotEmpty(message = "标题不能为空")
@Length(min = 6, max = 32, message = "标题长度为 6-32 位")
private String title;
@NotEmpty(message = "跳转链接不能为空")
@URL(message = "跳转链接格式不正确")
private String url;
@NotEmpty(message = "图片链接不能为空")
@URL(message = "图片链接格式不正确")
private String picUrl;
@NotNull(message = "排序不能为空")
private Integer sort;
@Length(max = 255, message = "备注最大长度为 255 位")
private String memo;
public String getTitle() {
return title;
}
public BannerAddDTO setTitle(String title) {
this.title = title;
return this;
}
public String getUrl() {
return url;
}
public BannerAddDTO setUrl(String url) {
this.url = url;
return this;
}
public Integer getSort() {
return sort;
}
public BannerAddDTO setSort(Integer sort) {
this.sort = sort;
return this;
}
public String getMemo() {
return memo;
}
public BannerAddDTO setMemo(String memo) {
this.memo = memo;
return this;
}
public String getPicUrl() {
return picUrl;
}
public BannerAddDTO setPicUrl(String picUrl) {
this.picUrl = picUrl;
return this;
}
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.mall.promotion.api.dto;
import javax.validation.constraints.NotNull;
public class BannerPageDTO {
/**
* 标题模糊匹配
*/
private String title;
@NotNull(message = "页码不能为空")
private Integer pageNo;
@NotNull(message = "每页条数不能为空")
private Integer pageSize;
public Integer getPageNo() {
return pageNo;
}
public BannerPageDTO setPageNo(Integer pageNo) {
this.pageNo = pageNo;
return this;
}
public Integer getPageSize() {
return pageSize;
}
public BannerPageDTO setPageSize(Integer pageSize) {
this.pageSize = pageSize;
return this;
}
public String getTitle() {
return title;
}
public BannerPageDTO setTitle(String title) {
this.title = title;
return this;
}
}

View File

@ -0,0 +1,83 @@
package cn.iocoder.mall.promotion.api.dto;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* Banner 更新 DTO
*/
public class BannerUpdateDTO {
@NotNull(message = "编号不能为空")
private Integer id;
@NotEmpty(message = "标题不能为空")
@Length(min = 6, max = 32, message = "标题长度为 6-32 位")
private String title;
@NotEmpty(message = "跳转链接不能为空")
@URL(message = "跳转链接格式不正确")
private String url;
@URL(message = "图片链接格式不正确")
private String picUrl;
@NotNull(message = "排序不能为空")
private Integer sort;
@Length(max = 255, message = "备注最大长度为 255 位")
private String memo;
public Integer getId() {
return id;
}
public BannerUpdateDTO setId(Integer id) {
this.id = id;
return this;
}
public String getTitle() {
return title;
}
public BannerUpdateDTO setTitle(String title) {
this.title = title;
return this;
}
public String getUrl() {
return url;
}
public BannerUpdateDTO setUrl(String url) {
this.url = url;
return this;
}
public Integer getSort() {
return sort;
}
public BannerUpdateDTO setSort(Integer sort) {
this.sort = sort;
return this;
}
public String getMemo() {
return memo;
}
public BannerUpdateDTO setMemo(String memo) {
this.memo = memo;
return this;
}
public String getPicUrl() {
return picUrl;
}
public BannerUpdateDTO setPicUrl(String picUrl) {
this.picUrl = picUrl;
return this;
}
}

View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>promotion</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>promotion-service-impl</artifactId>
<properties>
<org.mapstruct.version>1.3.0.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>promotion-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>admin-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
<dependency>
<groupId>Pingplusplus</groupId>
<artifactId>pingpp-java</artifactId>
<version>2.2.4</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-sdk</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>product-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 提供给 mapstruct 使用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source> <!-- or higher, depending on your project -->
<target>1.8</target> <!-- or higher, depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,14 @@
package cn.iocoder.mall.promotion.biz.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@MapperScan("cn.iocoder.mall.promotion.biz.dao") // 扫描对应的 Mapper 接口
@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理为什么使用 proxyTargetClass 参数参见 https://blog.csdn.net/huang_550/article/details/76492600
public class DatabaseConfiguration {
// 数据源使用 HikariCP
}

View File

@ -0,0 +1,26 @@
package cn.iocoder.mall.promotion.biz.config;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.mall.user.service.api.constant.UserErrorCodeEnum;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
@Configuration
public class ServiceExceptionConfiguration {
@EventListener(ApplicationReadyEvent.class) // 可参考 https://www.cnblogs.com/ssslinppp/p/7607509.html
public void initMessages() {
// service_exception_message.properties 加载错误码的方案
// Properties properties;
// try {
// properties = PropertiesLoaderUtils.loadAllProperties("classpath:service_exception_message.properties");
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
for (UserErrorCodeEnum item : UserErrorCodeEnum.values()) {
ServiceExceptionUtil.put(item.getCode(), item.getMessage());
}
}
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.mall.promotion.biz.convert;
import cn.iocoder.mall.promotion.api.bo.BannerBO;
import cn.iocoder.mall.promotion.api.dto.BannerAddDTO;
import cn.iocoder.mall.promotion.api.dto.BannerUpdateDTO;
import cn.iocoder.mall.promotion.biz.dataobject.BannerDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface BannerConvert {
BannerConvert INSTANCE = Mappers.getMapper(BannerConvert.class);
@Mappings({})
BannerBO convertToBO(BannerDO banner);
@Mappings({})
List<BannerBO> convertToBO(List<BannerDO> bannerList);
@Mappings({})
BannerDO convert(BannerAddDTO bannerAddDTO);
@Mappings({})
BannerDO convert(BannerUpdateDTO bannerUpdateDTO);
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.mall.promotion.biz.dao;
import cn.iocoder.mall.promotion.biz.dataobject.BannerDO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface BannerMapper {
BannerDO selectById(@Param("id") Integer id);
List<BannerDO> selectListByTitleLike(@Param("title") String title,
@Param("offset") Integer offset,
@Param("limit") Integer limit);
Integer selectCountByTitleLike(@Param("title") String title);
void insert(BannerDO bannerDO);
int update(BannerDO bannerDO);
}

View File

@ -0,0 +1,106 @@
package cn.iocoder.mall.promotion.biz.dataobject;
import cn.iocoder.common.framework.dataobject.DeletableDO;
/**
* Banner 广告页
*/
public class BannerDO extends DeletableDO {
/**
* 编号
*/
private Integer id;
/**
* 标题
*/
private String title;
/**
* 跳转链接
*/
private String url;
/**
* 图片链接
*/
private String picUrl;
/**
* 排序
*/
private Integer sort;
/**
* 状态
*
* {@link cn.iocoder.common.framework.constant.CommonStatusEnum}
*/
private Integer status;
/**
* 备注
*/
private String memo;
// TODO 芋艿 点击次数&& 其他数据相关
public Integer getId() {
return id;
}
public BannerDO setId(Integer id) {
this.id = id;
return this;
}
public String getTitle() {
return title;
}
public BannerDO setTitle(String title) {
this.title = title;
return this;
}
public String getUrl() {
return url;
}
public BannerDO setUrl(String url) {
this.url = url;
return this;
}
public Integer getStatus() {
return status;
}
public BannerDO setStatus(Integer status) {
this.status = status;
return this;
}
public String getMemo() {
return memo;
}
public BannerDO setMemo(String memo) {
this.memo = memo;
return this;
}
public Integer getSort() {
return sort;
}
public BannerDO setSort(Integer sort) {
this.sort = sort;
return this;
}
public String getPicUrl() {
return picUrl;
}
public BannerDO setPicUrl(String picUrl) {
this.picUrl = picUrl;
return this;
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.mall.promotion.biz;

View File

@ -0,0 +1,92 @@
package cn.iocoder.mall.promotion.biz.service;
import cn.iocoder.common.framework.constant.CommonStatusEnum;
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.BannerService;
import cn.iocoder.mall.promotion.api.bo.BannerBO;
import cn.iocoder.mall.promotion.api.bo.BannerPageBO;
import cn.iocoder.mall.promotion.api.constant.PromotionErrorCodeEnum;
import cn.iocoder.mall.promotion.api.dto.BannerAddDTO;
import cn.iocoder.mall.promotion.api.dto.BannerPageDTO;
import cn.iocoder.mall.promotion.api.dto.BannerUpdateDTO;
import cn.iocoder.mall.promotion.biz.convert.BannerConvert;
import cn.iocoder.mall.promotion.biz.dao.BannerMapper;
import cn.iocoder.mall.promotion.biz.dataobject.BannerDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service // 实际上不用添加添加的原因是必须 Spring 报错提示
@com.alibaba.dubbo.config.annotation.Service(validation = "true")
public class BannerServiceImpl implements BannerService {
@Autowired
private BannerMapper bannerMapper;
@Override
public CommonResult<BannerPageBO> getBannerPage(BannerPageDTO bannerPageDTO) {
BannerPageBO bannerPageBO = new BannerPageBO();
// 查询分页数据
int offset = (bannerPageDTO.getPageNo() - 1) * bannerPageDTO.getPageSize();
bannerPageBO.setList(BannerConvert.INSTANCE.convertToBO(bannerMapper.selectListByTitleLike(bannerPageDTO.getTitle(),
offset, bannerPageDTO.getPageSize())));
// 查询分页总数
bannerPageBO.setTotal(bannerMapper.selectCountByTitleLike(bannerPageDTO.getTitle()));
return CommonResult.success(bannerPageBO);
}
@Override
public CommonResult<BannerBO> addBanner(Integer adminId, BannerAddDTO bannerAddDTO) {
// 保存到数据库
BannerDO banner = BannerConvert.INSTANCE.convert(bannerAddDTO);
banner.setDeleted(DeletedStatusEnum.DELETED_NO.getValue()).setCreateTime(new Date());
bannerMapper.insert(banner);
// 返回成功
return CommonResult.success(BannerConvert.INSTANCE.convertToBO(banner));
}
@Override
public CommonResult<Boolean> updateBanner(Integer adminId, BannerUpdateDTO bannerUpdateDTO) {
// 校验 Banner 存在
if (bannerMapper.selectById(bannerUpdateDTO.getId()) == null) {
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.BANNER_NOT_EXISTS.getCode());
}
// 更新到数据库
BannerDO updateBanner = BannerConvert.INSTANCE.convert(bannerUpdateDTO);
bannerMapper.update(updateBanner);
// 返回成功
return CommonResult.success(true);
}
@Override
public CommonResult<Boolean> updateBannerStatus(Integer adminId, Integer bannerId, Integer status) {
// 校验参数
if (!CommonStatusEnum.isValid(status)) {
return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "变更状态必须是开启1或关闭2"); // TODO 有点搓
}
// 更新到数据库
BannerDO updateBanner = new BannerDO().setId(bannerId).setStatus(status);
bannerMapper.update(updateBanner);
// 返回成功
return CommonResult.success(true);
}
@Override
public CommonResult<Boolean> deleteBanner(Integer adminId, Integer bannerId) {
// 校验 Banner 存在
if (bannerMapper.selectById(bannerId) == null) {
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.BANNER_NOT_EXISTS.getCode());
}
// 更新到数据库
BannerDO updateBanner = new BannerDO().setId(bannerId);
updateBanner.setDeleted(DeletedStatusEnum.DELETED_YES.getValue());
bannerMapper.update(updateBanner);
// 返回成功
return CommonResult.success(true);
}
}

View File

@ -0,0 +1,30 @@
spring:
# datasource
datasource:
url: jdbc:mysql://180.167.213.26:13306/mall_promotion?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ${MALL_MYSQL_PASSWORD}
# mybatis
mybatis:
config-location: classpath:mybatis-config.xml
mapper-locations: classpath:mapper/*.xml
type-aliases-package: cn.iocoder.mall.promotion.biz.dataobject
# dubbo
dubbo:
application:
name: promotion-service
registry:
address: zookeeper://127.0.0.1:2181
protocol:
port: -1
name: dubbo
scan:
base-packages: cn.iocoder.mall.promotion.biz.service
# logging
logging:
level:
cn.iocoder.mall.promotion.dao: debug

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.iocoder.mall.promotion.biz.dao.BannerMapper">
<sql id="FIELDS">
id, title, url, pic_url, sort,
status, memo, create_time
</sql>
<!-- <select id="selectListByPidAndStatusOrderBySort" resultType="BannerDO">-->
<!-- SELECT-->
<!-- <include refid="FIELDS" />-->
<!-- FROM banner-->
<!-- WHERE pid = #{pid}-->
<!-- AND status = #{status}-->
<!-- AND deleted = 0-->
<!-- ORDER BY sort ASC-->
<!-- </select>-->
<!-- <select id="selectList" resultType="BannerDO">-->
<!-- SELECT-->
<!-- <include refid="FIELDS" />-->
<!-- FROM banner-->
<!-- WHERE deleted = 0-->
<!-- </select>-->
<select id="selectById" parameterType="Integer" resultType="BannerDO">
SELECT
<include refid="FIELDS" />
FROM banner
WHERE id = #{id}
AND deleted = 0
</select>
<select id="selectListByTitleLike" resultType="BannerDO">
SELECT
<include refid="FIELDS" />
FROM banner
<where>
<if test="title != null">
title LIKE "%"#{title}"%"
</if>
AND deleted = 0
</where>
LIMIT #{offset}, #{limit}
</select>
<select id="selectCountByTitleLike" resultType="Integer">
SELECT
COUNT(1)
FROM banner
<where>
<if test="title != null">
title LIKE "%"#{title}"%"
</if>
AND deleted = 0
</where>
</select>
<insert id="insert" parameterType="BannerDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO banner (
title, url, pic_url, sort, status,
memo, create_time, deleted
) VALUES (
#{title}, #{url}, #{picUrl}, #{sort}, #{status},
#{memo}, #{createTime}, #{deleted}
)
</insert>
<update id="update" parameterType="BannerDO">
UPDATE banner
<set>
<if test="title != null">
title = #{title},
</if>
<if test="url != null">
url = #{url},
</if>
<if test="pic_url != null">
pic_url = #{picUrl} ,
</if>
<if test="sort != null">
sort = #{sort},
</if>
<if test="status != null">
status = #{status},
</if>
<if test="VALUES != null">
VALUES = #{VALUES},
</if>
<if test="deleted != null">
deleted = #{deleted}
</if>
</set>
WHERE id = #{id}
</update>
</mapper>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 使用驼峰命名法转换字段。 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer"/>
<typeAlias alias="Long" type="java.lang.Long"/>
<typeAlias alias="HashMap" type="java.util.HashMap"/>
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap"/>
<typeAlias alias="ArrayList" type="java.util.ArrayList"/>
<typeAlias alias="LinkedList" type="java.util.LinkedList"/>
</typeAliases>
</configuration>

View File

@ -27,7 +27,6 @@ public class MVCConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// CORS
// 用户
registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**");
registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口
@ -42,15 +41,6 @@ public class MVCConfiguration implements WebMvcConfigurer {
registry.addResourceHandler("webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
// TODO 芋艿允许跨域
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedHeaders("*")
// .allowedMethods("*")
// .allowedOrigins("*");
// }
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();

View File

@ -19,7 +19,7 @@ public class SwaggerConfiguration {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.user.controller"))
.apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.user.application.controller"))
.paths(PathSelectors.any())
.build();
}

View File

@ -27,7 +27,7 @@ public class AdminsUserController {
@ApiOperation(value = "用户分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "nickname", value = "昵称,模糊匹配", example = "小王"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 0 开始", example = "0"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<AdminsUserPageVO> page(@RequestParam(value = "nickname", required = false) String nickname,