Merge remote-tracking branch 'origin/master' into feature/springdoc
# Conflicts: # yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.javaplp
commit
f2adb441cd
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@
|
||||
<?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>yudao</artifactId>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>yudao-module-mp</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<description>
|
||||
wechat 模块,主要实现微信平台的相关业务。
|
||||
例如:微信公众号、企业微信 SCRM 等
|
||||
</description>
|
||||
<modules>
|
||||
<module>yudao-module-mp-api</module>
|
||||
<module>yudao-module-mp-biz</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.mp.enums.message;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 公众号消息自动回复的匹配模式
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MpAutoReplyMatchEnum {
|
||||
|
||||
ALL(1, "完全匹配"),
|
||||
LIKE(2, "半匹配"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 匹配
|
||||
*/
|
||||
private final Integer match;
|
||||
/**
|
||||
* 匹配的名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.mp.enums.message;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 公众号消息自动回复的类型
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MpAutoReplyTypeEnum {
|
||||
|
||||
SUBSCRIBE(1, "关注时回复"),
|
||||
MESSAGE(2, "收到消息回复"),
|
||||
KEYWORD(3, "关键词回复"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 来源
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 类型的名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.mp.enums.message;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 微信公众号消息的发送来源
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MpMessageSendFromEnum {
|
||||
|
||||
USER_TO_MP(1, "粉丝发送给公众号"),
|
||||
MP_TO_USER(2, "公众号发给粉丝"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 来源
|
||||
*/
|
||||
private final Integer from;
|
||||
/**
|
||||
* 来源的名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
<?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>yudao-module-mp</artifactId>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-mp-biz</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
mp 模块,我们放微信微信公众号。
|
||||
例如说:提供微信公众号的账号、菜单、粉丝、标签、消息、自动回复、素材、模板通知、运营数据等功能
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-mp-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-system-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-infra-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 业务组件 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 消息队列相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,98 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.account;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.*;
|
||||
import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号账号")
|
||||
@RestController
|
||||
@RequestMapping("/mp/account")
|
||||
@Validated
|
||||
public class MpAccountController {
|
||||
|
||||
@Resource
|
||||
private MpAccountService mpAccountService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建公众号账号")
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:create')")
|
||||
public CommonResult<Long> createAccount(@Valid @RequestBody MpAccountCreateReqVO createReqVO) {
|
||||
return success(mpAccountService.createAccount(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新公众号账号")
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:update')")
|
||||
public CommonResult<Boolean> updateAccount(@Valid @RequestBody MpAccountUpdateReqVO updateReqVO) {
|
||||
mpAccountService.updateAccount(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除公众号账号")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:delete')")
|
||||
public CommonResult<Boolean> deleteAccount(@RequestParam("id") Long id) {
|
||||
mpAccountService.deleteAccount(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得公众号账号")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:query')")
|
||||
public CommonResult<MpAccountRespVO> getAccount(@RequestParam("id") Long id) {
|
||||
MpAccountDO wxAccount = mpAccountService.getAccount(id);
|
||||
return success(MpAccountConvert.INSTANCE.convert(wxAccount));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得公众号账号分页")
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:query')")
|
||||
public CommonResult<PageResult<MpAccountRespVO>> getAccountPage(@Valid MpAccountPageReqVO pageVO) {
|
||||
PageResult<MpAccountDO> pageResult = mpAccountService.getAccountPage(pageVO);
|
||||
return success(MpAccountConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/list-all-simple")
|
||||
@ApiOperation(value = "获取公众号账号精简信息列表")
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:query')")
|
||||
public CommonResult<List<MpAccountSimpleRespVO>> getSimpleAccounts() {
|
||||
List<MpAccountDO> list = mpAccountService.getAccountList();
|
||||
return success(MpAccountConvert.INSTANCE.convertList02(list));
|
||||
}
|
||||
|
||||
@PutMapping("/generate-qr-code")
|
||||
@ApiOperation("生成公众号二维码")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:qr-code')")
|
||||
public CommonResult<Boolean> generateAccountQrCode(@RequestParam("id") Long id) {
|
||||
mpAccountService.generateAccountQrCode(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/clear-quota")
|
||||
@ApiOperation("清空公众号 API 配额")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:clear-quota')")
|
||||
public CommonResult<Boolean> clearAccountQuota(@RequestParam("id") Long id) {
|
||||
mpAccountService.clearAccountQuota(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.account.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@ApiModel("管理后台 - 公众号账号创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAccountCreateReqVO extends MpAccountBaseVO {
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.account.vo;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.annotations.*;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
@ApiModel("管理后台 - 公众号账号分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAccountPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号名称", notes = "模糊匹配")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "公众号账号", notes = "模糊匹配")
|
||||
private String account;
|
||||
|
||||
@ApiModelProperty(value = "公众号 appid", notes = "模糊匹配")
|
||||
private String appId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.account.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 公众号账号 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAccountRespVO extends MpAccountBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "二维码图片URL", example = "https://www.iocoder.cn/1024.png")
|
||||
private String qrCodeUrl;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.account.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("管理后台 - 公众号账号精简信息 Response VO")
|
||||
@Data
|
||||
public class MpAccountSimpleRespVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "公众号名称", required = true, example = "芋道源码")
|
||||
private String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.account.vo;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.annotations.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@ApiModel("管理后台 - 公众号账号更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAccountUpdateReqVO extends MpAccountBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
### 请求 /mp/material/page 接口 => 成功
|
||||
GET {{baseUrl}}/mp/material/page?permanent=true&pageNo=1&pageSize=10
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.material;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.material.vo.*;
|
||||
import cn.iocoder.yudao.module.mp.convert.material.MpMaterialConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.material.MpMaterialDO;
|
||||
import cn.iocoder.yudao.module.mp.service.material.MpMaterialService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号素材")
|
||||
@RestController
|
||||
@RequestMapping("/mp/material")
|
||||
@Validated
|
||||
public class MpMaterialController {
|
||||
|
||||
@Resource
|
||||
private MpMaterialService mpMaterialService;
|
||||
|
||||
@ApiOperation("上传临时素材")
|
||||
@PostMapping("/upload-temporary")
|
||||
@PreAuthorize("@ss.hasPermission('mp:material:upload-temporary')")
|
||||
public CommonResult<MpMaterialUploadRespVO> uploadTemporaryMaterial(
|
||||
@Valid MpMaterialUploadTemporaryReqVO reqVO) throws IOException {
|
||||
MpMaterialDO material = mpMaterialService.uploadTemporaryMaterial(reqVO);
|
||||
return success(MpMaterialConvert.INSTANCE.convert(material));
|
||||
}
|
||||
|
||||
@ApiOperation("上传永久素材")
|
||||
@PostMapping("/upload-permanent")
|
||||
@PreAuthorize("@ss.hasPermission('mp:material:upload-permanent')")
|
||||
public CommonResult<MpMaterialUploadRespVO> uploadPermanentMaterial(
|
||||
@Valid MpMaterialUploadPermanentReqVO reqVO) throws IOException {
|
||||
MpMaterialDO material = mpMaterialService.uploadPermanentMaterial(reqVO);
|
||||
return success(MpMaterialConvert.INSTANCE.convert(material));
|
||||
}
|
||||
|
||||
@ApiOperation("删除素材")
|
||||
@DeleteMapping("/delete-permanent")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:material:delete')")
|
||||
public CommonResult<Boolean> deleteMaterial(@RequestParam("id") Long id) {
|
||||
mpMaterialService.deleteMaterial(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@ApiOperation("上传图文内容中的图片")
|
||||
@PostMapping("/upload-news-image")
|
||||
@PreAuthorize("@ss.hasPermission('mp:material:upload-news-image')")
|
||||
public CommonResult<String> uploadNewsImage(@Valid MpMaterialUploadNewsImageReqVO reqVO)
|
||||
throws IOException {
|
||||
return success(mpMaterialService.uploadNewsImage(reqVO));
|
||||
}
|
||||
|
||||
@ApiOperation("获得素材分页")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('mp:material:query')")
|
||||
public CommonResult<PageResult<MpMaterialRespVO>> getMaterialPage(@Valid MpMaterialPageReqVO pageReqVO) {
|
||||
PageResult<MpMaterialDO> pageResult = mpMaterialService.getMaterialPage(pageReqVO);
|
||||
return success(MpMaterialConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.material.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号素材的分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpMaterialPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "是否永久", example = "true")
|
||||
private Boolean permanent;
|
||||
|
||||
@ApiModelProperty(value = "文件类型", example = "image", notes = "参见 WxConsts.MediaFileType 枚举")
|
||||
private String type;
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.material.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号素材上传图文内容中的图片 Request VO")
|
||||
@Data
|
||||
public class MpMaterialUploadNewsImageReqVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "文件附件", required = true)
|
||||
@NotNull(message = "文件不能为空")
|
||||
@JsonIgnore // 避免被操作日志,进行序列化,导致报错
|
||||
private MultipartFile file;
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.material.vo;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号素材上传永久 Request VO")
|
||||
@Data
|
||||
public class MpMaterialUploadPermanentReqVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "文件类型", required = true, example = "image", notes = "参见 WxConsts.MediaFileType 枚举")
|
||||
@NotEmpty(message = "文件类型不能为空")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty(value = "文件附件", required = true)
|
||||
@NotNull(message = "文件不能为空")
|
||||
@JsonIgnore // 避免被操作日志,进行序列化,导致报错
|
||||
private MultipartFile file;
|
||||
|
||||
@ApiModelProperty(value = "名字", example = "wechat.mp", notes = "如果 name 为空,则使用 file 文件名")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "视频素材的标题", example = "视频素材的标题", notes = "文件类型为 video 时,必填")
|
||||
private String title;
|
||||
@ApiModelProperty(value = "视频素材的描述", example = "视频素材的描述", notes = "文件类型为 video 时,必填")
|
||||
private String introduction;
|
||||
|
||||
@AssertTrue(message = "标题不能为空")
|
||||
public boolean isTitleValid() {
|
||||
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
|
||||
return ObjectUtil.notEqual(type, WxConsts.MediaFileType.VIDEO)
|
||||
|| title != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "描述不能为空")
|
||||
public boolean isIntroductionValid() {
|
||||
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
|
||||
return ObjectUtil.notEqual(type, WxConsts.MediaFileType.VIDEO)
|
||||
|| introduction != null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.material.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("管理后台 - 公众号素材上传结果 Response VO")
|
||||
@Data
|
||||
public class MpMaterialUploadRespVO {
|
||||
|
||||
@ApiModelProperty(value = "素材的 media_id", required = true, example = "123")
|
||||
private String mediaId;
|
||||
|
||||
@ApiModelProperty(value = "素材的 URL", required = true, example = "https://www.iocoder.cn/1.png")
|
||||
private String url;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.material.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号素材上传临时 Request VO")
|
||||
@Data
|
||||
public class MpMaterialUploadTemporaryReqVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "文件类型", required = true, example = "image", notes = "参见 WxConsts.MediaFileType 枚举")
|
||||
@NotEmpty(message = "文件类型不能为空")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty(value = "文件附件", required = true)
|
||||
@NotNull(message = "文件不能为空")
|
||||
@JsonIgnore // 避免被操作日志,进行序列化,导致报错
|
||||
private MultipartFile file;
|
||||
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
### 请求 /mp/menu/save 接口 => 成功
|
||||
POST {{baseUrl}}/mp/menu/save
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"accountId": "1",
|
||||
"menus": [
|
||||
{
|
||||
"type":"click",
|
||||
"name":"今日歌曲",
|
||||
"menuKey":"V1001_TODAY_MUSIC"
|
||||
},
|
||||
{
|
||||
"name":"搜索",
|
||||
"type":"view",
|
||||
"url":"https://www.soso.com/"
|
||||
},
|
||||
{
|
||||
"name": "父按钮",
|
||||
"children": [
|
||||
{
|
||||
"type":"click",
|
||||
"name":"归去来兮",
|
||||
"menuKey":"MUSIC"
|
||||
},
|
||||
{
|
||||
"name":"不说",
|
||||
"type":"view",
|
||||
"url":"https://www.soso.com/"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
|
||||
### 请求 /mp/menu/save 接口 => 成功(清空)
|
||||
POST {{baseUrl}}/mp/menu/save
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"accountId": "1",
|
||||
"menus": []
|
||||
}
|
||||
|
||||
### 请求 /mp/menu/list 接口 => 成功
|
||||
GET {{baseUrl}}/mp/menu/list?accountId=1
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
@ -0,0 +1,57 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.menu;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
|
||||
import cn.iocoder.yudao.module.mp.convert.menu.MpMenuConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
||||
import cn.iocoder.yudao.module.mp.service.menu.MpMenuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号菜单")
|
||||
@RestController
|
||||
@RequestMapping("/mp/menu")
|
||||
@Validated
|
||||
public class MpMenuController {
|
||||
|
||||
@Resource
|
||||
private MpMenuService mpMenuService;
|
||||
|
||||
@PostMapping("/save")
|
||||
@ApiOperation("保存公众号菜单")
|
||||
@PreAuthorize("@ss.hasPermission('mp:menu:save')")
|
||||
public CommonResult<Boolean> saveMenu(@Valid @RequestBody MpMenuSaveReqVO createReqVO) {
|
||||
mpMenuService.saveMenu(createReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除公众号菜单")
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, example = "10", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:menu:delete')")
|
||||
public CommonResult<Boolean> deleteMenu(@RequestParam("accountId") Long accountId) {
|
||||
mpMenuService.deleteMenuByAccountId(accountId);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得公众号菜单列表")
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, example = "10", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:menu:query')")
|
||||
public CommonResult<List<MpMenuRespVO>> getMenuList(@RequestParam("accountId") Long accountId) {
|
||||
List<MpMenuDO> list = mpMenuService.getMenuListByAccountId(accountId);
|
||||
return success(MpMenuConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 公众号菜单 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpMenuRespVO extends MpMenuBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "主键", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "公众号 appId", required = true, example = "wx1234567890ox")
|
||||
private String appId;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 公众号菜单保存 Request VO")
|
||||
@Data
|
||||
public class MpMenuSaveReqVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@NotEmpty(message = "菜单不能为空")
|
||||
@Valid
|
||||
private List<Menu> menus;
|
||||
|
||||
@ApiModel("管理后台 - 公众号菜单保存时的每个菜单")
|
||||
@Data
|
||||
public static class Menu extends MpMenuBaseVO {
|
||||
|
||||
/**
|
||||
* 子菜单数组
|
||||
*/
|
||||
private List<Menu> children;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
### 请求 /mp/message/page 接口 => 成功
|
||||
GET {{baseUrl}}/mp/auto-reply/page?accountId=1&pageNo=1&pageSize=10
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply.MpAutoReplyCreateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply.MpAutoReplyRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply.MpAutoReplyUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessagePageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.convert.message.MpAutoReplyConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpAutoReplyDO;
|
||||
import cn.iocoder.yudao.module.mp.service.message.MpAutoReplyService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号自动回复")
|
||||
@RestController
|
||||
@RequestMapping("/mp/auto-reply")
|
||||
@Validated
|
||||
public class MpAutoReplyController {
|
||||
|
||||
@Resource
|
||||
private MpAutoReplyService mpAutoReplyService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得公众号自动回复分页")
|
||||
@PreAuthorize("@ss.hasPermission('mp:auto-reply:query')")
|
||||
public CommonResult<PageResult<MpAutoReplyRespVO>> getAutoReplyPage(@Valid MpMessagePageReqVO pageVO) {
|
||||
PageResult<MpAutoReplyDO> pageResult = mpAutoReplyService.getAutoReplyPage(pageVO);
|
||||
return success(MpAutoReplyConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得公众号自动回复")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:auto-reply:query')")
|
||||
public CommonResult<MpAutoReplyRespVO> getAutoReply(@RequestParam("id") Long id) {
|
||||
MpAutoReplyDO autoReply = mpAutoReplyService.getAutoReply(id);
|
||||
return success(MpAutoReplyConvert.INSTANCE.convert(autoReply));
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建公众号自动回复")
|
||||
@PreAuthorize("@ss.hasPermission('mp:auto-reply:create')")
|
||||
public CommonResult<Long> createAutoReply(@Valid @RequestBody MpAutoReplyCreateReqVO createReqVO) {
|
||||
return success(mpAutoReplyService.createAutoReply(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新公众号自动回复")
|
||||
@PreAuthorize("@ss.hasPermission('mp:auto-reply:update')")
|
||||
public CommonResult<Boolean> updateAutoReply(@Valid @RequestBody MpAutoReplyUpdateReqVO updateReqVO) {
|
||||
mpAutoReplyService.updateAutoReply(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除公众号自动回复")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:auto-reply:delete')")
|
||||
public CommonResult<Boolean> deleteAutoReply(@RequestParam("id") Long id) {
|
||||
mpAutoReplyService.deleteAutoReply(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
### 请求 /mp/message/page 接口 => 成功
|
||||
GET {{baseUrl}}/mp/message/page?accountId=1&pageNo=1&pageSize=10
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /mp/message/send 接口 => 成功(文本)
|
||||
POST {{baseUrl}}/mp/message/send
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"userId": 3,
|
||||
"type": "text",
|
||||
"content": "测试消息"
|
||||
}
|
||||
|
||||
### 请求 /mp/message/send 接口 => 成功(音乐)
|
||||
POST {{baseUrl}}/mp/message/send
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"userId": 3,
|
||||
"type": "music",
|
||||
"title": "测试音乐标题",
|
||||
"description": "测试音乐内容",
|
||||
"musicUrl": "https://www.iocoder.cn/xx.mp3",
|
||||
"hqMusicUrl": "https://www.iocoder.cn/xx_high.mp3",
|
||||
"thumbMediaId": "s98Iveeg9vDVFwa9q0u8-zSfdKe3xIzAm7wCrFE4WKGPIo4d9qAhtC-n6qvnyWyH"
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessagePageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessageRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessageSendReqVO;
|
||||
import cn.iocoder.yudao.module.mp.convert.message.MpMessageConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO;
|
||||
import cn.iocoder.yudao.module.mp.service.message.MpMessageService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号消息")
|
||||
@RestController
|
||||
@RequestMapping("/mp/message")
|
||||
@Validated
|
||||
public class MpMessageController {
|
||||
|
||||
@Resource
|
||||
private MpMessageService mpMessageService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得公众号消息分页")
|
||||
@PreAuthorize("@ss.hasPermission('mp:message:query')")
|
||||
public CommonResult<PageResult<MpMessageRespVO>> getMessagePage(@Valid MpMessagePageReqVO pageVO) {
|
||||
PageResult<MpMessageDO> pageResult = mpMessageService.getMessagePage(pageVO);
|
||||
return success(MpMessageConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@PostMapping("/send")
|
||||
@ApiOperation("给粉丝发送消息")
|
||||
@PreAuthorize("@ss.hasPermission('mp:message:send')")
|
||||
public CommonResult<MpMessageRespVO> sendMessage(@Valid @RequestBody MpMessageSendReqVO reqVO) {
|
||||
MpMessageDO message = mpMessageService.sendKefuMessage(reqVO);
|
||||
return success(MpMessageConvert.INSTANCE.convert(message));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号自动回复的创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAutoReplyCreateReqVO extends MpAutoReplyBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1024")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号自动回复的分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAutoReplyPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 公众号自动回复 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAutoReplyRespVO extends MpAutoReplyBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "主键", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1024")
|
||||
private Long accountId;
|
||||
@ApiModelProperty(value = "公众号 appId", required = true, example = "wx1234567890")
|
||||
private String appId;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号自动回复的更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpAutoReplyUpdateReqVO extends MpAutoReplyBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "主键", required = true, example = "1024")
|
||||
@NotNull(message = "主键不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message.vo.message;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import io.swagger.annotations.*;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel("管理后台 - 公众号消息分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpMessagePageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1024")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "消息类型", example = "text", notes = "参见 WxConsts.XmlMsgType 枚举")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty(value = "公众号粉丝标识", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M")
|
||||
private String openid;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message.vo.message;
|
||||
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 公众号消息 Response VO")
|
||||
@Data
|
||||
public class MpMessageRespVO {
|
||||
|
||||
@ApiModelProperty(value = "主键", required = true, example = "1024")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value = "微信公众号消息 id", required = true, example = "23953173569869169")
|
||||
private Long msgId;
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1")
|
||||
private Long accountId;
|
||||
@ApiModelProperty(value = "公众号账号的 appid", required = true, example = "wx1234567890")
|
||||
private String appId;
|
||||
|
||||
@ApiModelProperty(value = "公众号粉丝编号", required = true, example = "2048")
|
||||
private Long userId;
|
||||
@ApiModelProperty(value = "公众号粉丝标志", required = true, example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M")
|
||||
private String openid;
|
||||
|
||||
@ApiModelProperty(value = "消息类型", required = true, example = "text", notes = "参见 WxConsts.XmlMsgType 枚举")
|
||||
private String type;
|
||||
@ApiModelProperty(value = "消息来源", required = true, example = "1", notes = "参见 MpMessageSendFromEnum 枚举")
|
||||
private Integer sendFrom;
|
||||
|
||||
// ========= 普通消息内容 https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
|
||||
|
||||
@ApiModelProperty(value = "消息内容", example = "你好呀", notes = "消息类型为 text 时,才有值")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "媒体素材的编号", example = "1234567890", notes = "消息类型为 image、voice、video 时,才有值")
|
||||
private String mediaId;
|
||||
@ApiModelProperty(value = "媒体文件的 URL", example = "https://www.iocoder.cn/xxx.png",
|
||||
notes = "消息类型为 image、voice、video 时,才有值")
|
||||
private String mediaUrl;
|
||||
|
||||
@ApiModelProperty(value = "语音识别后文本", example = "语音识别后文本", notes = "消息类型为 voice 时,才有值")
|
||||
private String recognition;
|
||||
@ApiModelProperty(value = "语音格式", example = "amr", notes = "消息类型为 voice 时,才有值")
|
||||
private String format;
|
||||
|
||||
@ApiModelProperty(value = "标题", example = "我是标题", notes = "消息类型为 video、music、link 时,才有值")
|
||||
private String title;
|
||||
|
||||
@ApiModelProperty(value = "描述", example = "我是描述", notes = "消息类型为 video、music 时,才有值")
|
||||
private String description;
|
||||
|
||||
@ApiModelProperty(value = "缩略图的媒体 id", example = "1234567890", notes = "消息类型为 video、music 时,才有值")
|
||||
private String thumbMediaId;
|
||||
@ApiModelProperty(value = "缩略图的媒体 URL", example = "https://www.iocoder.cn/xxx.png",
|
||||
notes = "消息类型为 video、music 时,才有值")
|
||||
private String thumbMediaUrl;
|
||||
|
||||
@ApiModelProperty(value = "点击图文消息跳转链接", example = "https://www.iocoder.cn", notes = "消息类型为 link 时,才有值")
|
||||
private String url;
|
||||
|
||||
@ApiModelProperty(value = "地理位置维度", example = "23.137466", notes = "消息类型为 location 时,才有值")
|
||||
private Double locationX;
|
||||
|
||||
@ApiModelProperty(value = "地理位置经度", example = "113.352425", notes = "消息类型为 location 时,才有值")
|
||||
private Double locationY;
|
||||
|
||||
@ApiModelProperty(value = "地图缩放大小", example = "13", notes = "消息类型为 location 时,才有值")
|
||||
private Double scale;
|
||||
|
||||
@ApiModelProperty(value = "详细地址", example = "杨浦区黄兴路 221-4 号临", notes = "消息类型为 location 时,才有值")
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* 图文消息数组
|
||||
*
|
||||
* 消息类型为 {@link WxConsts.XmlMsgType} 的 NEWS
|
||||
*/
|
||||
@TableField(typeHandler = MpMessageDO.ArticleTypeHandler.class)
|
||||
private List<MpMessageDO.Article> articles;
|
||||
|
||||
@ApiModelProperty(value = "音乐链接", example = "https://www.iocoder.cn/xxx.mp3", notes = "消息类型为 music 时,才有值")
|
||||
private String musicUrl;
|
||||
@ApiModelProperty(value = "高质量音乐链接", example = "https://www.iocoder.cn/xxx.mp3", notes = "消息类型为 music 时,才有值")
|
||||
private String hqMusicUrl;
|
||||
|
||||
// ========= 事件推送 https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html
|
||||
|
||||
@ApiModelProperty(value = "事件类型", example = "subscribe", notes = "参见 WxConsts.EventType 枚举")
|
||||
private String event;
|
||||
@ApiModelProperty(value = "事件 Key", example = "qrscene_123456", notes = "参见 WxConsts.EventType 枚举")
|
||||
private String eventKey;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.message.vo.message;
|
||||
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO;
|
||||
import cn.iocoder.yudao.module.mp.framework.mp.core.util.MpUtils.*;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 公众号消息发送 Request VO")
|
||||
@Data
|
||||
public class MpMessageSendReqVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号粉丝的编号", required = true, example = "1024")
|
||||
@NotNull(message = "公众号粉丝的编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
// ========== 消息内容 ==========
|
||||
|
||||
@ApiModelProperty(value = "消息类型", required = true, example = "text", notes = "TEXT/IMAGE/VOICE/VIDEO/NEWS")
|
||||
@NotEmpty(message = "消息类型不能为空")
|
||||
public String type;
|
||||
|
||||
@ApiModelProperty(value = "消息内容", required = true, example = "你好呀")
|
||||
@NotEmpty(message = "消息内容不能为空", groups = TextMessageGroup.class)
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "媒体 ID", required = true, example = "qqc_2Fot30Jse-HDoZmo5RrUDijz2nGUkP")
|
||||
@NotEmpty(message = "消息内容不能为空", groups = {ImageMessageGroup.class, VoiceMessageGroup.class, VideoMessageGroup.class})
|
||||
private String mediaId;
|
||||
|
||||
@ApiModelProperty(value = "标题", required = true, example = "没有标题")
|
||||
@NotEmpty(message = "消息内容不能为空", groups = VideoMessageGroup.class)
|
||||
private String title;
|
||||
|
||||
@ApiModelProperty(value = "描述", required = true, example = "你猜")
|
||||
@NotEmpty(message = "消息描述不能为空", groups = VideoMessageGroup.class)
|
||||
private String description;
|
||||
|
||||
@ApiModelProperty(value = "缩略图的媒体 id", required = true, example = "qqc_2Fot30Jse-HDoZmo5RrUDijz2nGUkP")
|
||||
@NotEmpty(message = "缩略图的媒体 id 不能为空", groups = MusicMessageGroup.class)
|
||||
private String thumbMediaId;
|
||||
|
||||
@ApiModelProperty(value = "图文消息", required = true)
|
||||
@Valid
|
||||
@NotNull(message = "图文消息不能为空", groups = NewsMessageGroup.class)
|
||||
private List<MpMessageDO.Article> articles;
|
||||
|
||||
@ApiModelProperty(value = "音乐链接", example = "https://www.iocoder.cn/music.mp3", notes = "消息类型为 MUSIC 时")
|
||||
private String musicUrl;
|
||||
|
||||
@ApiModelProperty(value = "高质量音乐链接", example = "https://www.iocoder.cn/music.mp3", notes = "消息类型为 MUSIC 时")
|
||||
private String hqMusicUrl;
|
||||
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.news;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.news.vo.MpDraftPageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.material.MpMaterialDO;
|
||||
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
|
||||
import cn.iocoder.yudao.module.mp.service.material.MpMaterialService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.draft.*;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
|
||||
import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.*;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号草稿")
|
||||
@RestController
|
||||
@RequestMapping("/mp/draft")
|
||||
@Validated
|
||||
public class MpDraftController {
|
||||
|
||||
@Resource
|
||||
private MpServiceFactory mpServiceFactory;
|
||||
|
||||
@Resource
|
||||
private MpMaterialService mpMaterialService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得草稿分页")
|
||||
@PreAuthorize("@ss.hasPermission('mp:draft:query')")
|
||||
public CommonResult<PageResult<WxMpDraftItem>> getDraftPage(MpDraftPageReqVO reqVO) {
|
||||
// 从公众号查询草稿箱
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(reqVO.getAccountId());
|
||||
WxMpDraftList draftList;
|
||||
try {
|
||||
draftList = mpService.getDraftService().listDraft(PageUtils.getStart(reqVO), reqVO.getPageSize());
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(DRAFT_LIST_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
// 查询对应的图片地址。目的:解决公众号的图片链接无法在我们后台展示
|
||||
setDraftThumbUrl(draftList.getItems());
|
||||
|
||||
// 返回分页
|
||||
return success(new PageResult<>(draftList.getItems(), draftList.getTotalCount().longValue()));
|
||||
}
|
||||
|
||||
private void setDraftThumbUrl(List<WxMpDraftItem> items) {
|
||||
// 1.1 获得 mediaId 数组
|
||||
Set<String> mediaIds = new HashSet<>();
|
||||
items.forEach(item -> item.getContent().getNewsItem().forEach(newsItem -> mediaIds.add(newsItem.getThumbMediaId())));
|
||||
if (CollUtil.isEmpty(mediaIds)) {
|
||||
return;
|
||||
}
|
||||
// 1.2 批量查询对应的 Media 素材
|
||||
Map<String, MpMaterialDO> materials = CollectionUtils.convertMap(mpMaterialService.getMaterialListByMediaId(mediaIds),
|
||||
MpMaterialDO::getMediaId);
|
||||
|
||||
// 2. 设置回 WxMpDraftItem 记录
|
||||
items.forEach(item -> item.getContent().getNewsItem().forEach(newsItem ->
|
||||
findAndThen(materials, newsItem.getThumbMediaId(), material -> newsItem.setThumbUrl(material.getUrl()))));
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建草稿")
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true,
|
||||
example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:draft:create')")
|
||||
public CommonResult<String> deleteDraft(@RequestParam("accountId") Long accountId,
|
||||
@RequestBody WxMpAddDraft draft) {
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(accountId);
|
||||
try {
|
||||
String mediaId = mpService.getDraftService().addDraft(draft);
|
||||
return success(mediaId);
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(DRAFT_CREATE_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新草稿")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true,
|
||||
example = "1024", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "mediaId", value = "草稿素材的编号", required = true,
|
||||
example = "xxx", dataTypeClass = String.class),
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('mp:draft:update')")
|
||||
public CommonResult<Boolean> deleteDraft(@RequestParam("accountId") Long accountId,
|
||||
@RequestParam("mediaId") String mediaId,
|
||||
@RequestBody List<WxMpDraftArticles> articles) {
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(accountId);
|
||||
try {
|
||||
for (int i = 0; i < articles.size(); i++) {
|
||||
WxMpDraftArticles article = articles.get(i);
|
||||
mpService.getDraftService().updateDraft(new WxMpUpdateDraft(mediaId, i, article));
|
||||
}
|
||||
return success(true);
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(DRAFT_UPDATE_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除草稿")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true,
|
||||
example = "1024", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "mediaId", value = "草稿素材的编号", required = true,
|
||||
example = "xxx", dataTypeClass = String.class),
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('mp:draft:delete')")
|
||||
public CommonResult<Boolean> deleteDraft(@RequestParam("accountId") Long accountId,
|
||||
@RequestParam("mediaId") String mediaId) {
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(accountId);
|
||||
try {
|
||||
mpService.getDraftService().delDraft(mediaId);
|
||||
return success(true);
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(DRAFT_DELETE_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
### 请求 /mp/free-publish/page 接口 => 成功
|
||||
GET {{baseUrl}}/mp/free-publish/page?accountId=1&pageNo=1&pageSize=10
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /mp/free-publish/submit 接口 => 成功
|
||||
POST {{baseUrl}}/mp/free-publish/submit?accountId=1&mediaId=r6ryvl6LrxBU0miaST4Y-vilmd7iS51D8IPddxflWrau0hIQ2ovY8YanO5jlgUcM
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{}
|
||||
@ -0,0 +1,123 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.news;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.news.vo.MpFreePublishPageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.material.MpMaterialDO;
|
||||
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
|
||||
import cn.iocoder.yudao.module.mp.service.material.MpMaterialService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishItem;
|
||||
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishList;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
|
||||
import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.*;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号发布能力")
|
||||
@RestController
|
||||
@RequestMapping("/mp/free-publish")
|
||||
@Validated
|
||||
public class MpFreePublishController {
|
||||
|
||||
@Resource
|
||||
private MpServiceFactory mpServiceFactory;
|
||||
|
||||
@Resource
|
||||
private MpMaterialService mpMaterialService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得已发布的图文分页")
|
||||
@PreAuthorize("@ss.hasPermission('mp:free-publish:query')")
|
||||
public CommonResult<PageResult<WxMpFreePublishItem>> getFreePublishPage(MpFreePublishPageReqVO reqVO) {
|
||||
// 从公众号查询已发布的图文列表
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(reqVO.getAccountId());
|
||||
WxMpFreePublishList publicationRecords;
|
||||
try {
|
||||
publicationRecords = mpService.getFreePublishService().getPublicationRecords(
|
||||
PageUtils.getStart(reqVO), reqVO.getPageSize());
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(FREE_PUBLISH_LIST_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
// 查询对应的图片地址。目的:解决公众号的图片链接无法在我们后台展示
|
||||
setFreePublishThumbUrl(publicationRecords.getItems());
|
||||
|
||||
// 返回分页
|
||||
return success(new PageResult<>(publicationRecords.getItems(), publicationRecords.getTotalCount().longValue()));
|
||||
}
|
||||
|
||||
private void setFreePublishThumbUrl(List<WxMpFreePublishItem> items) {
|
||||
// 1.1 获得 mediaId 数组
|
||||
Set<String> mediaIds = new HashSet<>();
|
||||
items.forEach(item -> item.getContent().getNewsItem().forEach(newsItem -> mediaIds.add(newsItem.getThumbMediaId())));
|
||||
if (CollUtil.isEmpty(mediaIds)) {
|
||||
return;
|
||||
}
|
||||
// 1.2 批量查询对应的 Media 素材
|
||||
Map<String, MpMaterialDO> materials = CollectionUtils.convertMap(mpMaterialService.getMaterialListByMediaId(mediaIds),
|
||||
MpMaterialDO::getMediaId);
|
||||
|
||||
// 2. 设置回 WxMpFreePublishItem 记录
|
||||
items.forEach(item -> item.getContent().getNewsItem().forEach(newsItem ->
|
||||
findAndThen(materials, newsItem.getThumbMediaId(), material -> newsItem.setThumbUrl(material.getUrl()))));
|
||||
}
|
||||
|
||||
@PostMapping("/submit")
|
||||
@ApiOperation("发布草稿")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true,
|
||||
example = "1024", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "mediaId", value = "要发布的草稿的 media_id", required = true,
|
||||
example = "2048", dataTypeClass = String.class)
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('mp:free-publish:submit')")
|
||||
public CommonResult<String> submitFreePublish(@RequestParam("accountId") Long accountId,
|
||||
@RequestParam("mediaId") String mediaId) {
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(accountId);
|
||||
try {
|
||||
String publishId = mpService.getFreePublishService().submit(mediaId);
|
||||
return success(publishId);
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(FREE_PUBLISH_SUBMIT_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除草稿")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true,
|
||||
example = "1024", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "articleId", value = "发布记录的编号", required = true,
|
||||
example = "2048", dataTypeClass = String.class)
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('mp:free-publish:delete')")
|
||||
public CommonResult<Boolean> deleteFreePublish(@RequestParam("accountId") Long accountId,
|
||||
@RequestParam("articleId") String articleId) {
|
||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(accountId);
|
||||
try {
|
||||
mpService.getFreePublishService().deletePushAllArticle(articleId);
|
||||
return success(true);
|
||||
} catch (WxErrorException e) {
|
||||
throw exception(FREE_PUBLISH_DELETE_FAIL, e.getError().getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.news.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号草稿的分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpDraftPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1024")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.news.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号已发布列表的分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpFreePublishPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1024")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.open;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.open.vo.MpOpenCheckSignatureReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.open.vo.MpOpenHandleMessageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
|
||||
import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder;
|
||||
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号回调")
|
||||
@RestController
|
||||
@RequestMapping("/mp/open")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class MpOpenController {
|
||||
|
||||
@Resource
|
||||
private MpServiceFactory mpServiceFactory;
|
||||
|
||||
@Resource
|
||||
private MpAccountService mpAccountService;
|
||||
|
||||
/**
|
||||
* 接收微信公众号的校验签名
|
||||
*
|
||||
* 对应 <a href="https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html">文档</a>
|
||||
*/
|
||||
@ApiOperation("校验签名") // 参见
|
||||
@GetMapping(value = "/{appId}", produces = "text/plain;charset=utf-8")
|
||||
public String checkSignature(@PathVariable("appId") String appId,
|
||||
MpOpenCheckSignatureReqVO reqVO) {
|
||||
log.info("[checkSignature][appId({}) 接收到来自微信服务器的认证消息({})]", appId, reqVO);
|
||||
// 校验请求签名
|
||||
WxMpService wxMpService = mpServiceFactory.getRequiredMpService(appId);
|
||||
// 校验通过
|
||||
if (wxMpService.checkSignature(reqVO.getTimestamp(), reqVO.getNonce(), reqVO.getSignature())) {
|
||||
return reqVO.getEchostr();
|
||||
}
|
||||
// 校验不通过
|
||||
return "非法请求";
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收微信公众号的消息推送
|
||||
*
|
||||
* <a href="https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html">文档</a>
|
||||
*/
|
||||
@ApiOperation("处理消息")
|
||||
@PostMapping(value = "/{appId}", produces = "application/xml; charset=UTF-8")
|
||||
@OperateLog(enable = false) // 回调地址,无需记录操作日志
|
||||
public String handleMessage(@PathVariable("appId") String appId,
|
||||
@RequestBody String content,
|
||||
MpOpenHandleMessageReqVO reqVO) {
|
||||
log.info("[handleMessage][appId({}) 推送消息,参数({}) 内容({})]", appId, reqVO, content);
|
||||
|
||||
// 处理 appId + 多租户的上下文
|
||||
MpAccountDO account = mpAccountService.getAccountFromCache(appId);
|
||||
Assert.notNull(account, "公众号 appId({}) 不存在", appId);
|
||||
try {
|
||||
MpContextHolder.setAppId(appId);
|
||||
return TenantUtils.execute(account.getTenantId(),
|
||||
() -> handleMessage0(appId, content, reqVO));
|
||||
} finally {
|
||||
MpContextHolder.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private String handleMessage0(String appId, String content, MpOpenHandleMessageReqVO reqVO) {
|
||||
// 校验请求签名
|
||||
WxMpService mppService = mpServiceFactory.getRequiredMpService(appId);
|
||||
Assert.isTrue(mppService.checkSignature(reqVO.getTimestamp(), reqVO.getNonce(), reqVO.getSignature()),
|
||||
"非法请求");
|
||||
|
||||
// 第一步,解析消息
|
||||
WxMpXmlMessage inMessage = null;
|
||||
if (StrUtil.isBlank(reqVO.getEncrypt_type())) { // 明文模式
|
||||
inMessage = WxMpXmlMessage.fromXml(content);
|
||||
} else if (Objects.equals(reqVO.getEncrypt_type(), MpOpenHandleMessageReqVO.ENCRYPT_TYPE_AES)) { // AES 加密模式
|
||||
inMessage = WxMpXmlMessage.fromEncryptedXml(content, mppService.getWxMpConfigStorage(),
|
||||
reqVO.getTimestamp(), reqVO.getNonce(), reqVO.getMsg_signature());
|
||||
}
|
||||
Assert.notNull(inMessage, "消息解析失败,原因:消息为空");
|
||||
|
||||
// 第二步,处理消息
|
||||
WxMpMessageRouter mpMessageRouter = mpServiceFactory.getRequiredMpMessageRouter(appId);
|
||||
WxMpXmlOutMessage outMessage = mpMessageRouter.route(inMessage);
|
||||
if (outMessage == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// 第三步,返回消息
|
||||
if (StrUtil.isBlank(reqVO.getEncrypt_type())) { // 明文模式
|
||||
return outMessage.toXml();
|
||||
} else if (Objects.equals(reqVO.getEncrypt_type(), MpOpenHandleMessageReqVO.ENCRYPT_TYPE_AES)) { // AES 加密模式
|
||||
return outMessage.toEncryptedXml(mppService.getWxMpConfigStorage());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.open.vo;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@ApiModel("管理后台 - 公众号校验签名 Request VO")
|
||||
@Data
|
||||
public class MpOpenCheckSignatureReqVO {
|
||||
|
||||
@ApiModelProperty(value = "微信加密签名", required = true, example = "490eb57f448b87bd5f20ccef58aa4de46aa1908e")
|
||||
@NotEmpty(message = "微信加密签名不能为空")
|
||||
private String signature;
|
||||
|
||||
@ApiModelProperty(value = "时间戳", required = true, example = "1672587863")
|
||||
@NotEmpty(message = "时间戳不能为空")
|
||||
private String timestamp;
|
||||
|
||||
@ApiModelProperty(value = "随机数", required = true, example = "1827365808")
|
||||
@NotEmpty(message = "随机数不能为空")
|
||||
private String nonce;
|
||||
|
||||
@ApiModelProperty(value = "随机字符串", required = true, example = "2721154047828672511")
|
||||
@NotEmpty(message = "随机字符串不能为空")
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private String echostr;
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.open.vo;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@ApiModel("管理后台 - 公众号处理消息 Request VO")
|
||||
@Data
|
||||
public class MpOpenHandleMessageReqVO {
|
||||
|
||||
public static final String ENCRYPT_TYPE_AES = "aes";
|
||||
|
||||
@ApiModelProperty(value = "微信加密签名", required = true, example = "490eb57f448b87bd5f20ccef58aa4de46aa1908e")
|
||||
@NotEmpty(message = "微信加密签名不能为空")
|
||||
private String signature;
|
||||
|
||||
@ApiModelProperty(value = "时间戳", required = true, example = "1672587863")
|
||||
@NotEmpty(message = "时间戳不能为空")
|
||||
private String timestamp;
|
||||
|
||||
@ApiModelProperty(value = "随机数", required = true, example = "1827365808")
|
||||
@NotEmpty(message = "随机数不能为空")
|
||||
private String nonce;
|
||||
|
||||
@ApiModelProperty(value = "粉丝 openid", required = true, example = "oz-Jdtyn-WGm4C4I5Z-nvBMO_ZfY")
|
||||
@NotEmpty(message = "粉丝 openid 不能为空")
|
||||
private String openid;
|
||||
|
||||
@ApiModelProperty(value = "消息加密类型", example = "aes")
|
||||
private String encrypt_type;
|
||||
|
||||
@ApiModelProperty(value = "微信签名", example = "QW5kcm9pZCBUaGUgQmFzZTY0IGlzIGEgZ2VuZXJhdGVkIHN0cmluZw==")
|
||||
private String msg_signature;
|
||||
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.statistics;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.statistics.vo.*;
|
||||
import cn.iocoder.yudao.module.mp.convert.statistics.MpStatisticsConvert;
|
||||
import cn.iocoder.yudao.module.mp.service.statistics.MpStatisticsService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeInterfaceResult;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeMsgResult;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeUserCumulate;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeUserSummary;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号统计")
|
||||
@RestController
|
||||
@RequestMapping("/mp/statistics")
|
||||
@Validated
|
||||
public class MpStatisticsController {
|
||||
|
||||
@Resource
|
||||
private MpStatisticsService mpStatisticsService;
|
||||
|
||||
@GetMapping("/user-summary")
|
||||
@ApiOperation("获得粉丝增减数据")
|
||||
@PreAuthorize("@ss.hasPermission('mp:statistics:query')")
|
||||
public CommonResult<List<MpStatisticsUserSummaryRespVO>> getUserSummary(MpStatisticsGetReqVO getReqVO) {
|
||||
List<WxDataCubeUserSummary> list = mpStatisticsService.getUserSummary(
|
||||
getReqVO.getAccountId(), getReqVO.getDate());
|
||||
return success(MpStatisticsConvert.INSTANCE.convertList01(list));
|
||||
}
|
||||
|
||||
@GetMapping("/user-cumulate")
|
||||
@ApiOperation("获得粉丝累计数据")
|
||||
@PreAuthorize("@ss.hasPermission('mp:statistics:query')")
|
||||
public CommonResult<List<MpStatisticsUserCumulateRespVO>> getUserCumulate(MpStatisticsGetReqVO getReqVO) {
|
||||
List<WxDataCubeUserCumulate> list = mpStatisticsService.getUserCumulate(
|
||||
getReqVO.getAccountId(), getReqVO.getDate());
|
||||
return success(MpStatisticsConvert.INSTANCE.convertList02(list));
|
||||
}
|
||||
|
||||
@GetMapping("/upstream-message")
|
||||
@ApiOperation("获取消息发送概况数据")
|
||||
@PreAuthorize("@ss.hasPermission('mp:statistics:query')")
|
||||
public CommonResult<List<MpStatisticsUpstreamMessageRespVO>> getUpstreamMessage(MpStatisticsGetReqVO getReqVO) {
|
||||
List<WxDataCubeMsgResult> list = mpStatisticsService.getUpstreamMessage(
|
||||
getReqVO.getAccountId(), getReqVO.getDate());
|
||||
return success(MpStatisticsConvert.INSTANCE.convertList03(list));
|
||||
}
|
||||
|
||||
@GetMapping("/interface-summary")
|
||||
@ApiOperation("获取消息发送概况数据")
|
||||
@PreAuthorize("@ss.hasPermission('mp:statistics:query')")
|
||||
public CommonResult<List<MpStatisticsInterfaceSummaryRespVO>> getInterfaceSummary(MpStatisticsGetReqVO getReqVO) {
|
||||
List<WxDataCubeInterfaceResult> list = mpStatisticsService.getInterfaceSummary(
|
||||
getReqVO.getAccountId(), getReqVO.getDate());
|
||||
return success(MpStatisticsConvert.INSTANCE.convertList04(list));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel("管理后台 - 获得统计数据 Request VO")
|
||||
@Data
|
||||
public class MpStatisticsGetReqVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1024")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "查询时间范围")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@NotNull(message = "查询时间范围不能为空")
|
||||
private LocalDateTime[] date;
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 某一天的接口分析数据 Response VO")
|
||||
@Data
|
||||
public class MpStatisticsInterfaceSummaryRespVO {
|
||||
|
||||
@ApiModelProperty(value = "日期", required = true)
|
||||
private Date refDate;
|
||||
|
||||
@ApiModelProperty(value = "通过服务器配置地址获得消息后,被动回复粉丝消息的次数", required = true, example = "10")
|
||||
private Integer callbackCount;
|
||||
|
||||
@ApiModelProperty(value = "上述动作的失败次数", required = true, example = "20")
|
||||
private Integer failCount;
|
||||
|
||||
@ApiModelProperty(value = "总耗时,除以 callback_count 即为平均耗时", required = true, example = "30")
|
||||
private Integer totalTimeCost;
|
||||
|
||||
@ApiModelProperty(value = "最大耗时", required = true, example = "40")
|
||||
private Integer maxTimeCost;
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 某一天的粉丝增减数据 Response VO")
|
||||
@Data
|
||||
public class MpStatisticsUpstreamMessageRespVO {
|
||||
|
||||
@ApiModelProperty(value = "日期", required = true)
|
||||
private Date refDate;
|
||||
|
||||
@ApiModelProperty(value = "上行发送了(向公众号发送了)消息的粉丝数", required = true, example = "10")
|
||||
private Integer messageUser;
|
||||
|
||||
@ApiModelProperty(value = "上行发送了消息的消息总数", required = true, example = "20")
|
||||
private Integer messageCount;
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 某一天的消息发送概况数据 Response VO")
|
||||
@Data
|
||||
public class MpStatisticsUserCumulateRespVO {
|
||||
|
||||
@ApiModelProperty(value = "日期", required = true)
|
||||
private Date refDate;
|
||||
|
||||
@ApiModelProperty(value = "累计粉丝量", required = true, example = "10")
|
||||
private Integer cumulateUser;
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 某一天的粉丝增减数据 Response VO")
|
||||
@Data
|
||||
public class MpStatisticsUserSummaryRespVO {
|
||||
|
||||
@ApiModelProperty(value = "日期", required = true)
|
||||
private Date refDate;
|
||||
|
||||
@ApiModelProperty(value = "粉丝来源", required = true, example = "0")
|
||||
private Integer userSource;
|
||||
|
||||
@ApiModelProperty(value = "新关注的粉丝数量", required = true, example = "10")
|
||||
private Integer newUser;
|
||||
|
||||
@ApiModelProperty(value = "取消关注的粉丝数量", required = true, example = "20")
|
||||
private Integer cancelUser;
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
### 请求 /mp/tag/create 接口 => 成功
|
||||
POST {{baseUrl}}/mp/tag/create
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"accountId": "1",
|
||||
"name": "测试"
|
||||
}
|
||||
|
||||
### 请求 /mp/tag/update 接口 => 成功
|
||||
PUT {{baseUrl}}/mp/tag/update
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"id": "3",
|
||||
"name": "测试标签啦"
|
||||
}
|
||||
|
||||
### 请求 /mp/tag/delete 接口 => 成功
|
||||
DELETE {{baseUrl}}/mp/tag/delete?id=3
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /mp/tag/page 接口 => 成功
|
||||
GET {{baseUrl}}/mp/tag/page?accountId=1&pageNo=1&pageSize=10
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /mp/tag/sync 接口 => 成功
|
||||
POST {{baseUrl}}/mp/tag/sync?accountId=1
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
@ -0,0 +1,80 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.tag;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.*;
|
||||
import cn.iocoder.yudao.module.mp.convert.tag.MpTagConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
|
||||
import cn.iocoder.yudao.module.mp.service.tag.MpTagService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号标签")
|
||||
@RestController
|
||||
@RequestMapping("/mp/tag")
|
||||
@Validated
|
||||
public class MpTagController {
|
||||
|
||||
@Resource
|
||||
private MpTagService mpTagService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建公众号标签")
|
||||
@PreAuthorize("@ss.hasPermission('mp:tag:create')")
|
||||
public CommonResult<Long> createTag(@Valid @RequestBody MpTagCreateReqVO createReqVO) {
|
||||
return success(mpTagService.createTag(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新公众号标签")
|
||||
@PreAuthorize("@ss.hasPermission('mp:tag:update')")
|
||||
public CommonResult<Boolean> updateTag(@Valid @RequestBody MpTagUpdateReqVO updateReqVO) {
|
||||
mpTagService.updateTag(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除公众号标签")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:tag:delete')")
|
||||
public CommonResult<Boolean> deleteTag(@RequestParam("id") Long id) {
|
||||
mpTagService.deleteTag(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获取公众号标签分页")
|
||||
@PreAuthorize("@ss.hasPermission('mp:tag:query')")
|
||||
public CommonResult<PageResult<MpTagRespVO>> getTagPage(MpTagPageReqVO pageReqVO) {
|
||||
PageResult<MpTagDO> pageResult = mpTagService.getTagPage(pageReqVO);
|
||||
return success(MpTagConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/list-all-simple")
|
||||
@ApiOperation(value = "获取公众号账号精简信息列表")
|
||||
@PreAuthorize("@ss.hasPermission('mp:account:query')")
|
||||
public CommonResult<List<MpTagSimpleRespVO>> getSimpleTags() {
|
||||
List<MpTagDO> list = mpTagService.getTagList();
|
||||
return success(MpTagConvert.INSTANCE.convertList02(list));
|
||||
}
|
||||
|
||||
@PostMapping("/sync")
|
||||
@ApiOperation("同步公众号标签")
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:tag:sync')")
|
||||
public CommonResult<Boolean> syncTag(@RequestParam("accountId") Long accountId) {
|
||||
mpTagService.syncTag(accountId);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.tag.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号标签创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpTagCreateReqVO extends MpTagBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.tag.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@ApiModel("管理后台 - 公众号标签分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpTagPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotEmpty(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "标签名", example = "哈哈", notes = "模糊匹配")
|
||||
private String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.tag.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 公众号标签 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpTagRespVO extends MpTagBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "此标签下粉丝数量", required = true, example = "0")
|
||||
private Integer count;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.tag.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("管理后台 - 公众号标签精简信息 Response VO")
|
||||
@Data
|
||||
public class MpTagSimpleRespVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "公众号的标签编号", required = true, example = "2048")
|
||||
private Long tagId;
|
||||
|
||||
@ApiModelProperty(value = "标签名称", required = true, example = "快乐")
|
||||
private String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.tag.vo;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@ApiModel("管理后台 - 公众号标签更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpTagUpdateReqVO extends MpTagBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true)
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
### 请求 /mp/user/sync 接口 => 成功
|
||||
POST {{baseUrl}}/mp/user/sync?accountId=1
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /mp/user/update 接口 => 成功
|
||||
PUT {{baseUrl}}/mp/user/update
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"id": "3",
|
||||
"nickname": "test",
|
||||
"remark": "测试备注",
|
||||
"tagIds": [103, 104]
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.user;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.convert.user.MpUserConvert;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
|
||||
import cn.iocoder.yudao.module.mp.service.user.MpUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 公众号粉丝")
|
||||
@RestController
|
||||
@RequestMapping("/mp/user")
|
||||
@Validated
|
||||
public class MpUserController {
|
||||
|
||||
@Resource
|
||||
private MpUserService mpUserService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得公众号粉丝分页")
|
||||
@PreAuthorize("@ss.hasPermission('mp:user:query')")
|
||||
public CommonResult<PageResult<MpUserRespVO>> getUserPage(@Valid MpUserPageReqVO pageVO) {
|
||||
PageResult<MpUserDO> pageResult = mpUserService.getUserPage(pageVO);
|
||||
return success(MpUserConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得公众号粉丝")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:user:query')")
|
||||
public CommonResult<MpUserRespVO> getUser(@RequestParam("id") Long id) {
|
||||
return success(MpUserConvert.INSTANCE.convert(mpUserService.getUser(id)));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新公众号粉丝")
|
||||
@PreAuthorize("@ss.hasPermission('mp:user:update')")
|
||||
public CommonResult<Boolean> updateUser(@Valid @RequestBody MpUserUpdateReqVO updateReqVO) {
|
||||
mpUserService.updateUser(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/sync")
|
||||
@ApiOperation("同步公众号粉丝")
|
||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('mp:user:sync')")
|
||||
public CommonResult<Boolean> syncUser(@RequestParam("accountId") Long accountId) {
|
||||
mpUserService.syncUser(accountId);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.user.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 公众号粉丝分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MpUserPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||
@NotNull(message = "公众号账号的编号不能为空")
|
||||
private Long accountId;
|
||||
|
||||
@ApiModelProperty(value = "公众号粉丝标识", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", notes = "模糊匹配")
|
||||
private String openid;
|
||||
|
||||
@ApiModelProperty(value = "公众号粉丝昵称", example = "芋艿", notes = "模糊匹配")
|
||||
private String nickname;
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.user.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 公众号粉丝 Response VO")
|
||||
@Data
|
||||
public class MpUserRespVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "公众号粉丝标识", required = true, example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M")
|
||||
private String openid;
|
||||
|
||||
@ApiModelProperty(value = "关注状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
||||
private Integer subscribeStatus;
|
||||
@ApiModelProperty(value = "关注时间", required = true)
|
||||
private LocalDateTime subscribeTime;
|
||||
@ApiModelProperty(value = "取消关注时间")
|
||||
private LocalDateTime unsubscribeTime;
|
||||
|
||||
@ApiModelProperty(value = "昵称", example = "芋道")
|
||||
private String nickname;
|
||||
@ApiModelProperty(value = "头像地址", example = "https://www.iocoder.cn/1.png")
|
||||
private String headImageUrl;
|
||||
@ApiModelProperty(value = "语言", example = "zh_CN")
|
||||
private String language;
|
||||
@ApiModelProperty(value = "国家", example = "中国")
|
||||
private String country;
|
||||
@ApiModelProperty(value = "省份", example = "广东省")
|
||||
private String province;
|
||||
@ApiModelProperty(value = "城市", example = "广州市")
|
||||
private String city;
|
||||
@ApiModelProperty(value = "备注", example = "你是一个芋头嘛")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "标签编号数组", example = "1,2,3")
|
||||
private List<Long> tagIds;
|
||||
|
||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "1")
|
||||
private Long accountId;
|
||||
@ApiModelProperty(value = "公众号账号的 appId", required = true, example = "wx1234567890")
|
||||
private String appId;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.mp.controller.admin.user.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 公众号粉丝更新 Request VO")
|
||||
@Data
|
||||
public class MpUserUpdateReqVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "昵称", example = "芋道")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty(value = "备注", example = "你是一个芋头嘛")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "标签编号数组", example = "1,2,3")
|
||||
private List<Long> tagIds;
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.account;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountSimpleRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpAccountConvert {
|
||||
|
||||
MpAccountConvert INSTANCE = Mappers.getMapper(MpAccountConvert.class);
|
||||
|
||||
MpAccountDO convert(MpAccountCreateReqVO bean);
|
||||
|
||||
MpAccountDO convert(MpAccountUpdateReqVO bean);
|
||||
|
||||
MpAccountRespVO convert(MpAccountDO bean);
|
||||
|
||||
List<MpAccountRespVO> convertList(List<MpAccountDO> list);
|
||||
|
||||
PageResult<MpAccountRespVO> convertPage(PageResult<MpAccountDO> page);
|
||||
|
||||
List<MpAccountSimpleRespVO> convertList02(List<MpAccountDO> list);
|
||||
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.material;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.material.vo.MpMaterialRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.material.vo.MpMaterialUploadRespVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.material.MpMaterialDO;
|
||||
import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Mapper
|
||||
public interface MpMaterialConvert {
|
||||
|
||||
MpMaterialConvert INSTANCE = Mappers.getMapper(MpMaterialConvert.class);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "id", ignore = true),
|
||||
@Mapping(source = "account.id", target = "accountId"),
|
||||
@Mapping(source = "account.appId", target = "appId"),
|
||||
@Mapping(source = "name", target = "name")
|
||||
})
|
||||
MpMaterialDO convert(String mediaId, String type, String url, MpAccountDO account,
|
||||
String name);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "id", ignore = true),
|
||||
@Mapping(source = "account.id", target = "accountId"),
|
||||
@Mapping(source = "account.appId", target = "appId"),
|
||||
@Mapping(source = "name", target = "name")
|
||||
})
|
||||
MpMaterialDO convert(String mediaId, String type, String url, MpAccountDO account,
|
||||
String name, String title, String introduction, String mpUrl);
|
||||
|
||||
MpMaterialUploadRespVO convert(MpMaterialDO bean);
|
||||
|
||||
default WxMpMaterial convert(String name, File file, String title, String introduction) {
|
||||
return new WxMpMaterial(name, file, title, introduction);
|
||||
}
|
||||
|
||||
PageResult<MpMaterialRespVO> convertPage(PageResult<MpMaterialDO> page);
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.menu;
|
||||
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
||||
import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
|
||||
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpMenuConvert {
|
||||
|
||||
MpMenuConvert INSTANCE = Mappers.getMapper(MpMenuConvert.class);
|
||||
|
||||
MpMenuRespVO convert(MpMenuDO bean);
|
||||
|
||||
List<MpMenuRespVO> convertList(List<MpMenuDO> list);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "menu.appId", target = "appId"),
|
||||
@Mapping(source = "menu.replyMessageType", target = "type"),
|
||||
@Mapping(source = "menu.replyContent", target = "content"),
|
||||
@Mapping(source = "menu.replyMediaId", target = "mediaId"),
|
||||
@Mapping(source = "menu.replyThumbMediaId", target = "thumbMediaId"),
|
||||
@Mapping(source = "menu.replyTitle", target = "title"),
|
||||
@Mapping(source = "menu.replyDescription", target = "description"),
|
||||
@Mapping(source = "menu.replyArticles", target = "articles"),
|
||||
@Mapping(source = "menu.replyMusicUrl", target = "musicUrl"),
|
||||
@Mapping(source = "menu.replyHqMusicUrl", target = "hqMusicUrl"),
|
||||
})
|
||||
MpMessageSendOutReqBO convert(String openid, MpMenuDO menu);
|
||||
|
||||
List<WxMenuButton> convert(List<MpMenuSaveReqVO.Menu> list);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "menuKey", target = "key"),
|
||||
@Mapping(source = "children", target = "subButtons"),
|
||||
})
|
||||
WxMenuButton convert(MpMenuSaveReqVO.Menu bean);
|
||||
|
||||
MpMenuDO convert02(MpMenuSaveReqVO.Menu menu);
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.message;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply.MpAutoReplyCreateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply.MpAutoReplyRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.autoreply.MpAutoReplyUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpAutoReplyDO;
|
||||
import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface MpAutoReplyConvert {
|
||||
|
||||
MpAutoReplyConvert INSTANCE = Mappers.getMapper(MpAutoReplyConvert.class);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "reply.appId", target = "appId"),
|
||||
@Mapping(source = "reply.responseMessageType", target = "type"),
|
||||
@Mapping(source = "reply.responseContent", target = "content"),
|
||||
@Mapping(source = "reply.responseMediaId", target = "mediaId"),
|
||||
@Mapping(source = "reply.responseTitle", target = "title"),
|
||||
@Mapping(source = "reply.responseDescription", target = "description"),
|
||||
@Mapping(source = "reply.responseArticles", target = "articles"),
|
||||
})
|
||||
MpMessageSendOutReqBO convert(String openid, MpAutoReplyDO reply);
|
||||
|
||||
PageResult<MpAutoReplyRespVO> convertPage(PageResult<MpAutoReplyDO> page);
|
||||
|
||||
MpAutoReplyRespVO convert(MpAutoReplyDO bean);
|
||||
|
||||
MpAutoReplyDO convert(MpAutoReplyCreateReqVO bean);
|
||||
|
||||
MpAutoReplyDO convert(MpAutoReplyUpdateReqVO bean);
|
||||
}
|
||||
@ -0,0 +1,172 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.message;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessageRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessageSendReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
|
||||
import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
|
||||
import me.chanjar.weixin.mp.builder.outxml.BaseBuilder;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpMessageConvert {
|
||||
|
||||
MpMessageConvert INSTANCE = Mappers.getMapper(MpMessageConvert.class);
|
||||
|
||||
MpMessageRespVO convert(MpMessageDO bean);
|
||||
|
||||
List<MpMessageRespVO> convertList(List<MpMessageDO> list);
|
||||
|
||||
PageResult<MpMessageRespVO> convertPage(PageResult<MpMessageDO> page);
|
||||
|
||||
default MpMessageDO convert(WxMpXmlMessage wxMessage, MpAccountDO account, MpUserDO user) {
|
||||
MpMessageDO message = convert(wxMessage);
|
||||
if (account != null) {
|
||||
message.setAccountId(account.getId()).setAppId(account.getAppId());
|
||||
}
|
||||
if (user != null) {
|
||||
message.setUserId(user.getId()).setOpenid(user.getOpenid());
|
||||
}
|
||||
return message;
|
||||
}
|
||||
@Mappings(value = {
|
||||
@Mapping(source = "msgType", target = "type"),
|
||||
@Mapping(target = "createTime", ignore = true),
|
||||
})
|
||||
MpMessageDO convert(WxMpXmlMessage bean);
|
||||
|
||||
default MpMessageDO convert(MpMessageSendOutReqBO sendReqBO, MpAccountDO account, MpUserDO user) {
|
||||
// 构建消息
|
||||
MpMessageDO message = new MpMessageDO();
|
||||
message.setType(sendReqBO.getType());
|
||||
switch (sendReqBO.getType()) {
|
||||
case WxConsts.XmlMsgType.TEXT: // 1. 文本
|
||||
message.setContent(sendReqBO.getContent());
|
||||
break;
|
||||
case WxConsts.XmlMsgType.IMAGE: // 2. 图片
|
||||
case WxConsts.XmlMsgType.VOICE: // 3. 语音
|
||||
message.setMediaId(sendReqBO.getMediaId());
|
||||
break;
|
||||
case WxConsts.XmlMsgType.VIDEO: // 4. 视频
|
||||
message.setMediaId(sendReqBO.getMediaId())
|
||||
.setTitle(sendReqBO.getTitle()).setDescription(sendReqBO.getDescription());
|
||||
break;
|
||||
case WxConsts.XmlMsgType.NEWS: // 5. 图文
|
||||
message.setArticles(sendReqBO.getArticles());
|
||||
case WxConsts.XmlMsgType.MUSIC: // 6. 音乐
|
||||
message.setTitle(sendReqBO.getTitle()).setDescription(sendReqBO.getDescription())
|
||||
.setMusicUrl(sendReqBO.getMusicUrl()).setHqMusicUrl(sendReqBO.getHqMusicUrl())
|
||||
.setThumbMediaId(sendReqBO.getThumbMediaId());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("不支持的消息类型:" + message.getType());
|
||||
}
|
||||
|
||||
// 其它字段
|
||||
if (account != null) {
|
||||
message.setAccountId(account.getId()).setAppId(account.getAppId());
|
||||
}
|
||||
if (user != null) {
|
||||
message.setUserId(user.getId()).setOpenid(user.getOpenid());
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
default WxMpXmlOutMessage convert02(MpMessageDO message, MpAccountDO account) {
|
||||
BaseBuilder<?, ? extends WxMpXmlOutMessage> builder;
|
||||
// 个性化字段
|
||||
switch (message.getType()) {
|
||||
case WxConsts.XmlMsgType.TEXT:
|
||||
builder = WxMpXmlOutMessage.TEXT().content(message.getContent());
|
||||
break;
|
||||
case WxConsts.XmlMsgType.IMAGE:
|
||||
builder = WxMpXmlOutMessage.IMAGE().mediaId(message.getMediaId());
|
||||
break;
|
||||
case WxConsts.XmlMsgType.VOICE:
|
||||
builder = WxMpXmlOutMessage.VOICE().mediaId(message.getMediaId());
|
||||
break;
|
||||
case WxConsts.XmlMsgType.VIDEO:
|
||||
builder = WxMpXmlOutMessage.VIDEO().mediaId(message.getMediaId())
|
||||
.title(message.getTitle()).description(message.getDescription());
|
||||
break;
|
||||
case WxConsts.XmlMsgType.NEWS:
|
||||
builder = WxMpXmlOutMessage.NEWS().articles(convertList02(message.getArticles()));
|
||||
break;
|
||||
case WxConsts.XmlMsgType.MUSIC:
|
||||
builder = WxMpXmlOutMessage.MUSIC().title(message.getTitle()).description(message.getDescription())
|
||||
.musicUrl(message.getMusicUrl()).hqMusicUrl(message.getHqMusicUrl())
|
||||
.thumbMediaId(message.getThumbMediaId());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("不支持的消息类型:" + message.getType());
|
||||
}
|
||||
// 通用字段
|
||||
builder.fromUser(account.getAccount());
|
||||
builder.toUser(message.getOpenid());
|
||||
return builder.build();
|
||||
}
|
||||
List<WxMpXmlOutNewsMessage.Item> convertList02(List<MpMessageDO.Article> list);
|
||||
|
||||
default WxMpKefuMessage convert(MpMessageSendReqVO sendReqVO, MpUserDO user) {
|
||||
me.chanjar.weixin.mp.builder.kefu.BaseBuilder<?> builder;
|
||||
// 个性化字段
|
||||
switch (sendReqVO.getType()) {
|
||||
case WxConsts.KefuMsgType.TEXT:
|
||||
builder = WxMpKefuMessage.TEXT().content(sendReqVO.getContent());
|
||||
break;
|
||||
case WxConsts.KefuMsgType.IMAGE:
|
||||
builder = WxMpKefuMessage.IMAGE().mediaId(sendReqVO.getMediaId());
|
||||
break;
|
||||
case WxConsts.KefuMsgType.VOICE:
|
||||
builder = WxMpKefuMessage.VOICE().mediaId(sendReqVO.getMediaId());
|
||||
break;
|
||||
case WxConsts.KefuMsgType.VIDEO:
|
||||
builder = WxMpKefuMessage.VIDEO().mediaId(sendReqVO.getMediaId())
|
||||
.title(sendReqVO.getTitle()).description(sendReqVO.getDescription());
|
||||
break;
|
||||
case WxConsts.KefuMsgType.NEWS:
|
||||
builder = WxMpKefuMessage.NEWS().articles(convertList03(sendReqVO.getArticles()));
|
||||
break;
|
||||
case WxConsts.KefuMsgType.MUSIC:
|
||||
builder = WxMpKefuMessage.MUSIC().title(sendReqVO.getTitle()).description(sendReqVO.getDescription())
|
||||
.thumbMediaId(sendReqVO.getThumbMediaId())
|
||||
.musicUrl(sendReqVO.getMusicUrl()).hqMusicUrl(sendReqVO.getHqMusicUrl());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("不支持的消息类型:" + sendReqVO.getType());
|
||||
}
|
||||
// 通用字段
|
||||
builder.toUser(user.getOpenid());
|
||||
return builder.build();
|
||||
}
|
||||
List<WxMpKefuMessage.WxArticle> convertList03(List<MpMessageDO.Article> list);
|
||||
|
||||
default MpMessageDO convert(WxMpKefuMessage wxMessage, MpAccountDO account, MpUserDO user) {
|
||||
MpMessageDO message = convert(wxMessage);
|
||||
if (account != null) {
|
||||
message.setAccountId(account.getId()).setAppId(account.getAppId());
|
||||
}
|
||||
if (user != null) {
|
||||
message.setUserId(user.getId()).setOpenid(user.getOpenid());
|
||||
}
|
||||
return message;
|
||||
}
|
||||
@Mappings(value = {
|
||||
@Mapping(source = "msgType", target = "type"),
|
||||
@Mapping(target = "createTime", ignore = true),
|
||||
})
|
||||
MpMessageDO convert(WxMpKefuMessage bean);
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.statistics;
|
||||
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.statistics.vo.MpStatisticsInterfaceSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.statistics.vo.MpStatisticsUpstreamMessageRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.statistics.vo.MpStatisticsUserCumulateRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.statistics.vo.MpStatisticsUserSummaryRespVO;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeInterfaceResult;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeMsgResult;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeUserCumulate;
|
||||
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeUserSummary;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpStatisticsConvert {
|
||||
|
||||
MpStatisticsConvert INSTANCE = Mappers.getMapper(MpStatisticsConvert.class);
|
||||
|
||||
List<MpStatisticsUserSummaryRespVO> convertList01(List<WxDataCubeUserSummary> list);
|
||||
|
||||
List<MpStatisticsUserCumulateRespVO> convertList02(List<WxDataCubeUserCumulate> list);
|
||||
|
||||
List<MpStatisticsUpstreamMessageRespVO> convertList03(List<WxDataCubeMsgResult> list);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "refDate", target = "refDate", dateFormat = "yyyy-MM-dd"),
|
||||
@Mapping(source = "msgUser", target = "messageUser"),
|
||||
@Mapping(source = "msgCount", target = "messageCount"),
|
||||
})
|
||||
MpStatisticsUpstreamMessageRespVO convert(WxDataCubeMsgResult bean);
|
||||
|
||||
List<MpStatisticsInterfaceSummaryRespVO> convertList04(List<WxDataCubeInterfaceResult> list);
|
||||
|
||||
@Mapping(source = "refDate", target = "refDate", dateFormat = "yyyy-MM-dd")
|
||||
MpStatisticsInterfaceSummaryRespVO convert(WxDataCubeInterfaceResult bean);
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.tag;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagSimpleRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
|
||||
import me.chanjar.weixin.mp.bean.tag.WxUserTag;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpTagConvert {
|
||||
|
||||
MpTagConvert INSTANCE = Mappers.getMapper(MpTagConvert.class);
|
||||
|
||||
WxUserTag convert(MpTagUpdateReqVO bean);
|
||||
|
||||
MpTagRespVO convert(WxUserTag bean);
|
||||
|
||||
List<MpTagRespVO> convertList(List<WxUserTag> list);
|
||||
|
||||
PageResult<MpTagRespVO> convertPage(PageResult<MpTagDO> page);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "id", ignore = true),
|
||||
@Mapping(source = "tag.id", target = "tagId"),
|
||||
@Mapping(source = "tag.name", target = "name"),
|
||||
@Mapping(source = "tag.count", target = "count"),
|
||||
@Mapping(source = "account.id", target = "accountId"),
|
||||
@Mapping(source = "account.appId", target = "appId"),
|
||||
})
|
||||
MpTagDO convert(WxUserTag tag, MpAccountDO account);
|
||||
|
||||
List<MpTagSimpleRespVO> convertList02(List<MpTagDO> list);
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package cn.iocoder.yudao.module.mp.convert.user;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserRespVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpUserConvert {
|
||||
|
||||
MpUserConvert INSTANCE = Mappers.getMapper(MpUserConvert.class);
|
||||
|
||||
MpUserRespVO convert(MpUserDO bean);
|
||||
|
||||
List<MpUserRespVO> convertList(List<MpUserDO> list);
|
||||
|
||||
PageResult<MpUserRespVO> convertPage(PageResult<MpUserDO> page);
|
||||
|
||||
@Mappings(value = {
|
||||
@Mapping(source = "openId", target = "openid"),
|
||||
@Mapping(source = "headImgUrl", target = "headImageUrl"),
|
||||
@Mapping(target = "subscribeTime", ignore = true), // 单独转换
|
||||
})
|
||||
MpUserDO convert(WxMpUser wxMpUser);
|
||||
|
||||
default MpUserDO convert(MpAccountDO account, WxMpUser wxMpUser) {
|
||||
MpUserDO user = convert(wxMpUser);
|
||||
user.setSubscribeStatus(wxMpUser.getSubscribe() ? CommonStatusEnum.ENABLE.getStatus()
|
||||
: CommonStatusEnum.DISABLE.getStatus());
|
||||
user.setSubscribeTime(LocalDateTimeUtil.of(wxMpUser.getSubscribeTime() * 1000L));
|
||||
if (account != null) {
|
||||
user.setAccountId(account.getId());
|
||||
user.setAppId(account.getAppId());
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
default List<MpUserDO> convertList(MpAccountDO account, List<WxMpUser> wxUsers) {
|
||||
return CollectionUtils.convertList(wxUsers, wxUser -> convert(account, wxUser));
|
||||
}
|
||||
|
||||
MpUserDO convert(MpUserUpdateReqVO bean);
|
||||
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package cn.iocoder.yudao.module.mp.dal.dataobject.account;
|
||||
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 公众号账号 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("mp_account")
|
||||
@KeySequence("mp_account_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MpAccountDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 公众号名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 公众号账号
|
||||
*/
|
||||
private String account;
|
||||
/**
|
||||
* 公众号 appid
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 公众号密钥
|
||||
*/
|
||||
private String appSecret;
|
||||
/**
|
||||
* 公众号token
|
||||
*/
|
||||
private String token;
|
||||
/**
|
||||
* 消息加解密密钥
|
||||
*/
|
||||
private String aesKey;
|
||||
/**
|
||||
* 二维码图片 URL
|
||||
*/
|
||||
private String qrCodeUrl;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.mp.dal.mysql.account;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface MpAccountMapper extends BaseMapperX<MpAccountDO> {
|
||||
|
||||
default PageResult<MpAccountDO> selectPage(MpAccountPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<MpAccountDO>()
|
||||
.likeIfPresent(MpAccountDO::getName, reqVO.getName())
|
||||
.likeIfPresent(MpAccountDO::getAccount, reqVO.getAccount())
|
||||
.likeIfPresent(MpAccountDO::getAppId, reqVO.getAppId())
|
||||
.orderByDesc(MpAccountDO::getId));
|
||||
}
|
||||
|
||||
default MpAccountDO selectByAppId(String appId) {
|
||||
return selectOne(MpAccountDO::getAppId, appId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.mp.dal.mysql.material;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.material.vo.MpMaterialPageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.material.MpMaterialDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpMaterialMapper extends BaseMapperX<MpMaterialDO> {
|
||||
|
||||
default MpMaterialDO selectByAccountIdAndMediaId(Long accountId, String mediaId) {
|
||||
return selectOne(MpMaterialDO::getAccountId, accountId,
|
||||
MpMaterialDO::getMediaId, mediaId);
|
||||
}
|
||||
|
||||
default PageResult<MpMaterialDO> selectPage(MpMaterialPageReqVO pageReqVO) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<MpMaterialDO>()
|
||||
.eq(MpMaterialDO::getAccountId, pageReqVO.getAccountId())
|
||||
.eqIfPresent(MpMaterialDO::getPermanent, pageReqVO.getPermanent())
|
||||
.eqIfPresent(MpMaterialDO::getType, pageReqVO.getType())
|
||||
.orderByDesc(MpMaterialDO::getId));
|
||||
}
|
||||
|
||||
default List<MpMaterialDO> selectListByMediaId(Collection<String> mediaIds) {
|
||||
return selectList(MpMaterialDO::getMediaId, mediaIds);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.mp.dal.mysql.menu;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpMenuMapper extends BaseMapperX<MpMenuDO> {
|
||||
|
||||
default MpMenuDO selectByAppIdAndMenuKey(String appId, String menuKey) {
|
||||
return selectOne(MpMenuDO::getAppId, appId,
|
||||
MpMenuDO::getMenuKey, menuKey);
|
||||
}
|
||||
|
||||
default List<MpMenuDO> selectListByAccountId(Long accountId) {
|
||||
return selectList(MpMenuDO::getAccountId, accountId);
|
||||
}
|
||||
|
||||
default void deleteByAccountId(Long accountId) {
|
||||
delete(new LambdaQueryWrapperX<MpMenuDO>().eq(MpMenuDO::getAccountId, accountId));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package cn.iocoder.yudao.module.mp.dal.mysql.message;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessagePageReqVO;
|
||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpAutoReplyDO;
|
||||
import cn.iocoder.yudao.module.mp.enums.message.MpAutoReplyMatchEnum;
|
||||
import cn.iocoder.yudao.module.mp.enums.message.MpAutoReplyTypeEnum;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MpAutoReplyMapper extends BaseMapperX<MpAutoReplyDO> {
|
||||
|
||||
default PageResult<MpAutoReplyDO> selectPage(MpMessagePageReqVO pageVO) {
|
||||
return selectPage(pageVO, new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||
.eq(MpAutoReplyDO::getAccountId, pageVO.getAccountId())
|
||||
.eqIfPresent(MpAutoReplyDO::getType, pageVO.getType()));
|
||||
}
|
||||
|
||||
default List<MpAutoReplyDO> selectListByAppIdAndKeywordAll(String appId, String requestKeyword) {
|
||||
return selectList(new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||
.eq(MpAutoReplyDO::getAppId, appId)
|
||||
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.KEYWORD.getType())
|
||||
.eq(MpAutoReplyDO::getRequestMatch, MpAutoReplyMatchEnum.ALL.getMatch())
|
||||
.eq(MpAutoReplyDO::getRequestKeyword, requestKeyword));
|
||||
}
|
||||
|
||||
default List<MpAutoReplyDO> selectListByAppIdAndKeywordLike(String appId, String requestKeyword) {
|
||||
return selectList(new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||
.eq(MpAutoReplyDO::getAppId, appId)
|
||||
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.KEYWORD.getType())
|
||||
.eq(MpAutoReplyDO::getRequestMatch, MpAutoReplyMatchEnum.LIKE.getMatch())
|
||||
.like(MpAutoReplyDO::getRequestKeyword, requestKeyword));
|
||||
}
|
||||
|
||||
default List<MpAutoReplyDO> selectListByAppIdAndMessage(String appId, String requestMessageType) {
|
||||
return selectList(new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||
.eq(MpAutoReplyDO::getAppId, appId)
|
||||
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.MESSAGE.getType())
|
||||
.eq(MpAutoReplyDO::getRequestMessageType, requestMessageType));
|
||||
}
|
||||
|
||||
default List<MpAutoReplyDO> selectListByAppIdAndSubscribe(String appId) {
|
||||
return selectList(new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||
.eq(MpAutoReplyDO::getAppId, appId)
|
||||
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.SUBSCRIBE.getType()));
|
||||
}
|
||||
|
||||
default MpAutoReplyDO selectByAccountIdAndSubscribe(Long accountId) {
|
||||
return selectOne(MpAutoReplyDO::getAccountId, accountId,
|
||||
MpAutoReplyDO::getType, MpAutoReplyTypeEnum.SUBSCRIBE.getType());
|
||||
}
|
||||
|
||||
default MpAutoReplyDO selectByAccountIdAndMessage(Long accountId, String requestMessageType) {
|
||||
return selectOne(new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||
.eq(MpAutoReplyDO::getAccountId, accountId)
|
||||
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.MESSAGE.getType())
|
||||
.eq(MpAutoReplyDO::getRequestMessageType, requestMessageType));
|
||||
}
|
||||
|
||||
default MpAutoReplyDO selectByAccountIdAndKeyword(Long accountId, String requestKeyword) {
|
||||
return selectOne(new LambdaQueryWrapperX<MpAutoReplyDO>()
|
||||
.eq(MpAutoReplyDO::getAccountId, accountId)
|
||||
.eq(MpAutoReplyDO::getType, MpAutoReplyTypeEnum.KEYWORD.getType())
|
||||
.eq(MpAutoReplyDO::getRequestKeyword, requestKeyword));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue