Commit 39b2afd506f177c7410e63f0af3df4980d22340c
1 parent
71beeabe
mp:完成的公众号的管理界面
Showing
16 changed files
with
272 additions
and
184 deletions
yudao-module-mp/yudao-module-mp-api/src/main/java/cn/iocoder/yudao/module/mp/enums/ErrorCodeConstants.java
| @@ -9,9 +9,12 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | @@ -9,9 +9,12 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 9 | */ | 9 | */ |
| 10 | public interface ErrorCodeConstants { | 10 | public interface ErrorCodeConstants { |
| 11 | 11 | ||
| 12 | - // ========== 用户相关 1004001000============ | ||
| 13 | - ErrorCode WX_ACCOUNT_NOT_EXISTS = new ErrorCode(1006001000, "公众号账户不存在"); | ||
| 14 | - ErrorCode WX_ACCOUNT_FANS_NOT_EXISTS = new ErrorCode(1006001001, "粉丝账号不存在"); | 12 | + // ========== 公众号账号 1006000000============ |
| 13 | + ErrorCode ACCOUNT_NOT_EXISTS = new ErrorCode(1006000000, "公众号账号不存在"); | ||
| 14 | + ErrorCode ACCOUNT_GENERATE_QR_CODE_FAIL = new ErrorCode(1006000001, "生成公众号二维码失败,原因:{}"); | ||
| 15 | + ErrorCode ACCOUNT_CLEAR_QUOTA_FAIL = new ErrorCode(1006000001, "清空公众号的 API 配额失败,原因:{}"); | ||
| 16 | + | ||
| 17 | + // TODO 要处理下 | ||
| 15 | ErrorCode COMMON_NOT_EXISTS = new ErrorCode(1006001002, "用户不存在"); | 18 | ErrorCode COMMON_NOT_EXISTS = new ErrorCode(1006001002, "用户不存在"); |
| 16 | 19 | ||
| 17 | } | 20 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/MpAccountController.java
| @@ -2,7 +2,10 @@ package cn.iocoder.yudao.module.mp.controller.admin.account; | @@ -2,7 +2,10 @@ package cn.iocoder.yudao.module.mp.controller.admin.account; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.module.mp.controller.admin.account.vo.*; | 5 | +import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReqVO; |
| 6 | +import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountUpdateReqVO; | ||
| 6 | import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert; | 9 | import cn.iocoder.yudao.module.mp.convert.account.MpAccountConvert; |
| 7 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; | 10 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 8 | import cn.iocoder.yudao.module.mp.service.account.MpAccountService; | 11 | import cn.iocoder.yudao.module.mp.service.account.MpAccountService; |
| @@ -18,54 +21,72 @@ import javax.validation.Valid; | @@ -18,54 +21,72 @@ import javax.validation.Valid; | ||
| 18 | 21 | ||
| 19 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 20 | 23 | ||
| 21 | -@Api(tags = "管理后台 - 公众号账户") | 24 | +@Api(tags = "管理后台 - 公众号账号") |
| 22 | @RestController | 25 | @RestController |
| 23 | @RequestMapping("/mp/account") | 26 | @RequestMapping("/mp/account") |
| 24 | @Validated | 27 | @Validated |
| 25 | public class MpAccountController { | 28 | public class MpAccountController { |
| 26 | 29 | ||
| 27 | @Resource | 30 | @Resource |
| 28 | - private MpAccountService wxAccountService; | 31 | + private MpAccountService mpAccountService; |
| 29 | 32 | ||
| 30 | @PostMapping("/create") | 33 | @PostMapping("/create") |
| 31 | - @ApiOperation("创建公众号账户") | 34 | + @ApiOperation("创建公众号账号") |
| 32 | @PreAuthorize("@ss.hasPermission('mp:account:create')") | 35 | @PreAuthorize("@ss.hasPermission('mp:account:create')") |
| 33 | public CommonResult<Long> createWxAccount(@Valid @RequestBody MpAccountCreateReqVO createReqVO) { | 36 | public CommonResult<Long> createWxAccount(@Valid @RequestBody MpAccountCreateReqVO createReqVO) { |
| 34 | - return success(wxAccountService.createAccount(createReqVO)); | 37 | + return success(mpAccountService.createAccount(createReqVO)); |
| 35 | } | 38 | } |
| 36 | 39 | ||
| 37 | @PutMapping("/update") | 40 | @PutMapping("/update") |
| 38 | - @ApiOperation("更新公众号账户") | 41 | + @ApiOperation("更新公众号账号") |
| 39 | @PreAuthorize("@ss.hasPermission('mp:account:update')") | 42 | @PreAuthorize("@ss.hasPermission('mp:account:update')") |
| 40 | public CommonResult<Boolean> updateWxAccount(@Valid @RequestBody MpAccountUpdateReqVO updateReqVO) { | 43 | public CommonResult<Boolean> updateWxAccount(@Valid @RequestBody MpAccountUpdateReqVO updateReqVO) { |
| 41 | - wxAccountService.updateAccount(updateReqVO); | 44 | + mpAccountService.updateAccount(updateReqVO); |
| 42 | return success(true); | 45 | return success(true); |
| 43 | } | 46 | } |
| 44 | 47 | ||
| 45 | @DeleteMapping("/delete") | 48 | @DeleteMapping("/delete") |
| 46 | - @ApiOperation("删除公众号账户") | 49 | + @ApiOperation("删除公众号账号") |
| 47 | @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) | 50 | @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) |
| 48 | @PreAuthorize("@ss.hasPermission('mp:account:delete')") | 51 | @PreAuthorize("@ss.hasPermission('mp:account:delete')") |
| 49 | public CommonResult<Boolean> deleteWxAccount(@RequestParam("id") Long id) { | 52 | public CommonResult<Boolean> deleteWxAccount(@RequestParam("id") Long id) { |
| 50 | - wxAccountService.deleteAccount(id); | 53 | + mpAccountService.deleteAccount(id); |
| 51 | return success(true); | 54 | return success(true); |
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | @GetMapping("/get") | 57 | @GetMapping("/get") |
| 55 | - @ApiOperation("获得公众号账户") | 58 | + @ApiOperation("获得公众号账号") |
| 56 | @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | 59 | @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) |
| 57 | @PreAuthorize("@ss.hasPermission('mp:account:query')") | 60 | @PreAuthorize("@ss.hasPermission('mp:account:query')") |
| 58 | public CommonResult<MpAccountRespVO> getWxAccount(@RequestParam("id") Long id) { | 61 | public CommonResult<MpAccountRespVO> getWxAccount(@RequestParam("id") Long id) { |
| 59 | - MpAccountDO wxAccount = wxAccountService.getAccount(id); | 62 | + MpAccountDO wxAccount = mpAccountService.getAccount(id); |
| 60 | return success(MpAccountConvert.INSTANCE.convert(wxAccount)); | 63 | return success(MpAccountConvert.INSTANCE.convert(wxAccount)); |
| 61 | } | 64 | } |
| 62 | 65 | ||
| 63 | @GetMapping("/page") | 66 | @GetMapping("/page") |
| 64 | - @ApiOperation("获得公众号账户分页") | 67 | + @ApiOperation("获得公众号账号分页") |
| 65 | @PreAuthorize("@ss.hasPermission('mp:account:query')") | 68 | @PreAuthorize("@ss.hasPermission('mp:account:query')") |
| 66 | public CommonResult<PageResult<MpAccountRespVO>> getWxAccountPage(@Valid MpAccountPageReqVO pageVO) { | 69 | public CommonResult<PageResult<MpAccountRespVO>> getWxAccountPage(@Valid MpAccountPageReqVO pageVO) { |
| 67 | - PageResult<MpAccountDO> pageResult = wxAccountService.getAccountPage(pageVO); | 70 | + PageResult<MpAccountDO> pageResult = mpAccountService.getAccountPage(pageVO); |
| 68 | return success(MpAccountConvert.INSTANCE.convertPage(pageResult)); | 71 | return success(MpAccountConvert.INSTANCE.convertPage(pageResult)); |
| 69 | } | 72 | } |
| 70 | 73 | ||
| 74 | + @PutMapping("/generate-qr-code") | ||
| 75 | + @ApiOperation("生成公众号二维码") | ||
| 76 | + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) | ||
| 77 | + @PreAuthorize("@ss.hasPermission('mp:account:qr-code')") | ||
| 78 | + public CommonResult<Boolean> generateAccountQrCode(@RequestParam("id") Long id) { | ||
| 79 | + mpAccountService.generateAccountQrCode(id); | ||
| 80 | + return success(true); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + @PutMapping("/clear-quota") | ||
| 84 | + @ApiOperation("清空公众号 API 配额") | ||
| 85 | + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) | ||
| 86 | + @PreAuthorize("@ss.hasPermission('mp:account:clear-quota')") | ||
| 87 | + public CommonResult<Boolean> clearAccountQuota(@RequestParam("id") Long id) { | ||
| 88 | + mpAccountService.clearAccountQuota(id); | ||
| 89 | + return success(true); | ||
| 90 | + } | ||
| 91 | + | ||
| 71 | } | 92 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/vo/MpAccountBaseVO.java
| @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mp.controller.admin.account.vo; | @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mp.controller.admin.account.vo; | ||
| 3 | import io.swagger.annotations.ApiModelProperty; | 3 | import io.swagger.annotations.ApiModelProperty; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | 5 | ||
| 6 | -import javax.validation.constraints.NotNull; | 6 | +import javax.validation.constraints.NotEmpty; |
| 7 | 7 | ||
| 8 | /** | 8 | /** |
| 9 | - * 公众号账户 Base VO,提供给添加、修改、详细的子 VO 使用 | 9 | + * 公众号账号 Base VO,提供给添加、修改、详细的子 VO 使用 |
| 10 | * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | 10 | * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 |
| 11 | * | 11 | * |
| 12 | * @author fengdan | 12 | * @author fengdan |
| @@ -14,29 +14,30 @@ import javax.validation.constraints.NotNull; | @@ -14,29 +14,30 @@ import javax.validation.constraints.NotNull; | ||
| 14 | @Data | 14 | @Data |
| 15 | public class MpAccountBaseVO { | 15 | public class MpAccountBaseVO { |
| 16 | 16 | ||
| 17 | - @ApiModelProperty(value = "公众号名称", required = true) | ||
| 18 | - @NotNull(message = "公众号名称不能为空") | 17 | + @ApiModelProperty(value = "公众号名称", required = true, example = "芋道源码") |
| 18 | + @NotEmpty(message = "公众号名称不能为空") | ||
| 19 | private String name; | 19 | private String name; |
| 20 | 20 | ||
| 21 | - @ApiModelProperty(value = "公众号账户", required = true) | ||
| 22 | - @NotNull(message = "公众号账户不能为空") | 21 | + @ApiModelProperty(value = "公众号微信号", required = true, example = "yudaoyuanma") |
| 22 | + @NotEmpty(message = "公众号微信号不能为空") | ||
| 23 | private String account; | 23 | private String account; |
| 24 | 24 | ||
| 25 | @ApiModelProperty(value = "公众号 appId", required = true, example = "wx5b23ba7a5589ecbb") | 25 | @ApiModelProperty(value = "公众号 appId", required = true, example = "wx5b23ba7a5589ecbb") |
| 26 | - @NotNull(message = "公众号 appId 不能为空") | 26 | + @NotEmpty(message = "公众号 appId 不能为空") |
| 27 | private String appId; | 27 | private String appId; |
| 28 | 28 | ||
| 29 | - @ApiModelProperty(value = "公众号密钥", required = true) | ||
| 30 | - @NotNull(message = "公众号密钥不能为空") | 29 | + @ApiModelProperty(value = "公众号密钥", required = true, example = "3a7b3b20c537e52e74afd395eb85f61f") |
| 30 | + @NotEmpty(message = "公众号密钥不能为空") | ||
| 31 | private String appSecret; | 31 | private String appSecret; |
| 32 | 32 | ||
| 33 | - @ApiModelProperty(value = "公众号 token", required = true) | 33 | + @ApiModelProperty(value = "公众号 token", required = true, example = "kangdayuzhen") |
| 34 | + @NotEmpty(message = "公众号 token 不能为空") | ||
| 34 | private String token; | 35 | private String token; |
| 35 | 36 | ||
| 36 | - @ApiModelProperty(value = "加密密钥") | 37 | + @ApiModelProperty(value = "加密密钥", example = "gjN+Ksei") |
| 37 | private String aesKey; | 38 | private String aesKey; |
| 38 | 39 | ||
| 39 | - @ApiModelProperty(value = "备注") | 40 | + @ApiModelProperty(value = "备注", example = "请关注芋道源码,学习技术") |
| 40 | private String remark; | 41 | private String remark; |
| 41 | 42 | ||
| 42 | } | 43 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/vo/MpAccountCreateReqVO.java
| @@ -5,7 +5,7 @@ import lombok.Data; | @@ -5,7 +5,7 @@ import lombok.Data; | ||
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | import lombok.ToString; | 6 | import lombok.ToString; |
| 7 | 7 | ||
| 8 | -@ApiModel("管理后台 - 公众号账户创建 Request VO") | 8 | +@ApiModel("管理后台 - 公众号账号创建 Request VO") |
| 9 | @Data | 9 | @Data |
| 10 | @EqualsAndHashCode(callSuper = true) | 10 | @EqualsAndHashCode(callSuper = true) |
| 11 | @ToString(callSuper = true) | 11 | @ToString(callSuper = true) |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/vo/MpAccountPageReqVO.java
| @@ -4,7 +4,7 @@ import lombok.*; | @@ -4,7 +4,7 @@ import lombok.*; | ||
| 4 | import io.swagger.annotations.*; | 4 | import io.swagger.annotations.*; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 6 | 6 | ||
| 7 | -@ApiModel("管理后台 - 公众号账户分页 Request VO") | 7 | +@ApiModel("管理后台 - 公众号账号分页 Request VO") |
| 8 | @Data | 8 | @Data |
| 9 | @EqualsAndHashCode(callSuper = true) | 9 | @EqualsAndHashCode(callSuper = true) |
| 10 | @ToString(callSuper = true) | 10 | @ToString(callSuper = true) |
| @@ -13,7 +13,7 @@ public class MpAccountPageReqVO extends PageParam { | @@ -13,7 +13,7 @@ public class MpAccountPageReqVO extends PageParam { | ||
| 13 | @ApiModelProperty(value = "公众号名称", notes = "模糊匹配") | 13 | @ApiModelProperty(value = "公众号名称", notes = "模糊匹配") |
| 14 | private String name; | 14 | private String name; |
| 15 | 15 | ||
| 16 | - @ApiModelProperty(value = "公众号账户", notes = "模糊匹配") | 16 | + @ApiModelProperty(value = "公众号账号", notes = "模糊匹配") |
| 17 | private String account; | 17 | private String account; |
| 18 | 18 | ||
| 19 | @ApiModelProperty(value = "公众号 appid", notes = "模糊匹配") | 19 | @ApiModelProperty(value = "公众号 appid", notes = "模糊匹配") |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/vo/MpAccountRespVO.java
| @@ -8,25 +8,19 @@ import lombok.ToString; | @@ -8,25 +8,19 @@ import lombok.ToString; | ||
| 8 | 8 | ||
| 9 | import java.util.Date; | 9 | import java.util.Date; |
| 10 | 10 | ||
| 11 | -/** | ||
| 12 | - * @author fengdan | ||
| 13 | - */ | ||
| 14 | -@ApiModel("管理后台 - 公众号账户 Response VO") | 11 | +@ApiModel("管理后台 - 公众号账号 Response VO") |
| 15 | @Data | 12 | @Data |
| 16 | @EqualsAndHashCode(callSuper = true) | 13 | @EqualsAndHashCode(callSuper = true) |
| 17 | @ToString(callSuper = true) | 14 | @ToString(callSuper = true) |
| 18 | public class MpAccountRespVO extends MpAccountBaseVO { | 15 | public class MpAccountRespVO extends MpAccountBaseVO { |
| 19 | 16 | ||
| 20 | - @ApiModelProperty(value = "编号", required = true) | 17 | + @ApiModelProperty(value = "编号", required = true, example = "1024") |
| 21 | private Long id; | 18 | private Long id; |
| 22 | 19 | ||
| 23 | - @ApiModelProperty(value = "二维码图片URL") | 20 | + @ApiModelProperty(value = "二维码图片URL", example = "https://www.iocoder.cn/1024.png") |
| 24 | private String qrCodeUrl; | 21 | private String qrCodeUrl; |
| 25 | 22 | ||
| 26 | @ApiModelProperty(value = "创建时间", required = true) | 23 | @ApiModelProperty(value = "创建时间", required = true) |
| 27 | private Date createTime; | 24 | private Date createTime; |
| 28 | 25 | ||
| 29 | - @ApiModelProperty(value = "公众号密钥", required = true) | ||
| 30 | - private String appSecret; | ||
| 31 | - | ||
| 32 | } | 26 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/account/vo/MpAccountUpdateReqVO.java
| @@ -7,7 +7,7 @@ import javax.validation.constraints.*; | @@ -7,7 +7,7 @@ import javax.validation.constraints.*; | ||
| 7 | /** | 7 | /** |
| 8 | * @author fengdan | 8 | * @author fengdan |
| 9 | */ | 9 | */ |
| 10 | -@ApiModel("管理后台 - 公众号账户更新 Request VO") | 10 | +@ApiModel("管理后台 - 公众号账号更新 Request VO") |
| 11 | @Data | 11 | @Data |
| 12 | @EqualsAndHashCode(callSuper = true) | 12 | @EqualsAndHashCode(callSuper = true) |
| 13 | @ToString(callSuper = true) | 13 | @ToString(callSuper = true) |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/dataobject/account/MpAccountDO.java
| 1 | package cn.iocoder.yudao.module.mp.dal.dataobject.account; | 1 | package cn.iocoder.yudao.module.mp.dal.dataobject.account; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; | 3 | import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; |
| 5 | import com.baomidou.mybatisplus.annotation.KeySequence; | 4 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 6 | import com.baomidou.mybatisplus.annotation.TableId; | 5 | import com.baomidou.mybatisplus.annotation.TableId; |
| 7 | import com.baomidou.mybatisplus.annotation.TableName; | 6 | import com.baomidou.mybatisplus.annotation.TableName; |
| 8 | -import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties; | ||
| 9 | import lombok.*; | 7 | import lombok.*; |
| 10 | -import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; | ||
| 11 | -import me.chanjar.weixin.mp.config.WxMpConfigStorage; | ||
| 12 | -import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl; | ||
| 13 | 8 | ||
| 14 | /** | 9 | /** |
| 15 | - * 公众号账户 DO | 10 | + * 公众号账号 DO |
| 16 | * | 11 | * |
| 17 | * @author 芋道源码 | 12 | * @author 芋道源码 |
| 18 | */ | 13 | */ |
| @@ -36,7 +31,7 @@ public class MpAccountDO extends TenantBaseDO { | @@ -36,7 +31,7 @@ public class MpAccountDO extends TenantBaseDO { | ||
| 36 | */ | 31 | */ |
| 37 | private String name; | 32 | private String name; |
| 38 | /** | 33 | /** |
| 39 | - * 公众号账户 | 34 | + * 公众号账号 |
| 40 | */ | 35 | */ |
| 41 | private String account; | 36 | private String account; |
| 42 | /** | 37 | /** |
| @@ -52,7 +47,7 @@ public class MpAccountDO extends TenantBaseDO { | @@ -52,7 +47,7 @@ public class MpAccountDO extends TenantBaseDO { | ||
| 52 | */ | 47 | */ |
| 53 | private String token; | 48 | private String token; |
| 54 | /** | 49 | /** |
| 55 | - * 加密密钥 | 50 | + * 消息加解密密钥 |
| 56 | */ | 51 | */ |
| 57 | private String aesKey; | 52 | private String aesKey; |
| 58 | /** | 53 | /** |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/account/MpAccountMapper.java
| @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; | 6 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; |
| 7 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; | 7 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | -import org.apache.ibatis.annotations.Select; | ||
| 10 | - | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | 9 | ||
| 13 | @Mapper | 10 | @Mapper |
| 14 | public interface MpAccountMapper extends BaseMapperX<MpAccountDO> { | 11 | public interface MpAccountMapper extends BaseMapperX<MpAccountDO> { |
| @@ -21,7 +18,8 @@ public interface MpAccountMapper extends BaseMapperX<MpAccountDO> { | @@ -21,7 +18,8 @@ public interface MpAccountMapper extends BaseMapperX<MpAccountDO> { | ||
| 21 | .orderByDesc(MpAccountDO::getId)); | 18 | .orderByDesc(MpAccountDO::getId)); |
| 22 | } | 19 | } |
| 23 | 20 | ||
| 24 | - @Select("SELECT COUNT(*) FROM mp_account WHERE update_time > #{maxUpdateTime}") | ||
| 25 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | 21 | + default MpAccountDO selectByAppId(String appId) { |
| 22 | + return selectOne(MpAccountDO::getAppId, appId); | ||
| 23 | + } | ||
| 26 | 24 | ||
| 27 | } | 25 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/consumer/MpConfigRefreshConsumer.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/consumer/MpAccountRefreshConsumer.java
| 1 | package cn.iocoder.yudao.module.mp.mq.consumer; | 1 | package cn.iocoder.yudao.module.mp.mq.consumer; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; | 3 | import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; |
| 4 | -import cn.iocoder.yudao.module.mp.mq.message.MpConfigRefreshMessage; | 4 | +import cn.iocoder.yudao.module.mp.mq.message.MpAccountRefreshMessage; |
| 5 | import cn.iocoder.yudao.module.mp.service.account.MpAccountService; | 5 | import cn.iocoder.yudao.module.mp.service.account.MpAccountService; |
| 6 | import lombok.extern.slf4j.Slf4j; | 6 | import lombok.extern.slf4j.Slf4j; |
| 7 | import org.springframework.stereotype.Component; | 7 | import org.springframework.stereotype.Component; |
| @@ -9,21 +9,21 @@ import org.springframework.stereotype.Component; | @@ -9,21 +9,21 @@ import org.springframework.stereotype.Component; | ||
| 9 | import javax.annotation.Resource; | 9 | import javax.annotation.Resource; |
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | - * 针对 {@link MpConfigRefreshMessage} 的消费者 | 12 | + * 针对 {@link MpAccountRefreshMessage} 的消费者 |
| 13 | * | 13 | * |
| 14 | - * @author lyz | 14 | + * @author 芋道源码 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
| 17 | @Slf4j | 17 | @Slf4j |
| 18 | -public class MpConfigRefreshConsumer extends AbstractChannelMessageListener<MpConfigRefreshMessage> { | 18 | +public class MpAccountRefreshConsumer extends AbstractChannelMessageListener<MpAccountRefreshMessage> { |
| 19 | 19 | ||
| 20 | @Resource | 20 | @Resource |
| 21 | - private MpAccountService wxAccountService; | 21 | + private MpAccountService mpAccountService; |
| 22 | 22 | ||
| 23 | @Override | 23 | @Override |
| 24 | - public void onMessage(MpConfigRefreshMessage message) { | ||
| 25 | - log.info("[onMessage][收到 MpConfig 刷新消息]"); | ||
| 26 | - wxAccountService.initLocalCache(); | 24 | + public void onMessage(MpAccountRefreshMessage message) { |
| 25 | + log.info("[onMessage][收到 Account 刷新消息]"); | ||
| 26 | + mpAccountService.initLocalCache(); | ||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | } | 29 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/MpConfigRefreshMessage.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/message/MpAccountRefreshMessage.java
| @@ -5,15 +5,17 @@ import lombok.Data; | @@ -5,15 +5,17 @@ import lombok.Data; | ||
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | - * 微信配置数据刷新 Message | 8 | + * 公众号账号刷新 Message |
| 9 | + * | ||
| 10 | + * @author 芋道源码 | ||
| 9 | */ | 11 | */ |
| 10 | @Data | 12 | @Data |
| 11 | @EqualsAndHashCode(callSuper = true) | 13 | @EqualsAndHashCode(callSuper = true) |
| 12 | -public class MpConfigRefreshMessage extends AbstractChannelMessage { | 14 | +public class MpAccountRefreshMessage extends AbstractChannelMessage { |
| 13 | 15 | ||
| 14 | @Override | 16 | @Override |
| 15 | public String getChannel() { | 17 | public String getChannel() { |
| 16 | - return "mp.config-data.refresh"; | 18 | + return "mp.account.refresh"; |
| 17 | } | 19 | } |
| 18 | 20 | ||
| 19 | } | 21 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/MpConfigProducer.java renamed to yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/mq/producer/MpAccountProducer.java
| 1 | package cn.iocoder.yudao.module.mp.mq.producer; | 1 | package cn.iocoder.yudao.module.mp.mq.producer; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; | 3 | import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; |
| 4 | -import cn.iocoder.yudao.module.mp.mq.message.MpConfigRefreshMessage; | 4 | +import cn.iocoder.yudao.module.mp.mq.message.MpAccountRefreshMessage; |
| 5 | import org.springframework.stereotype.Component; | 5 | import org.springframework.stereotype.Component; |
| 6 | 6 | ||
| 7 | import javax.annotation.Resource; | 7 | import javax.annotation.Resource; |
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| 10 | - * 微信配置数据相关消息的 Producer | 10 | + * 公众号账号 Producer |
| 11 | + * | ||
| 12 | + * @author 芋道源码 | ||
| 11 | */ | 13 | */ |
| 12 | @Component | 14 | @Component |
| 13 | -public class MpConfigProducer { | 15 | +public class MpAccountProducer { |
| 14 | 16 | ||
| 15 | @Resource | 17 | @Resource |
| 16 | private RedisMQTemplate redisMQTemplate; | 18 | private RedisMQTemplate redisMQTemplate; |
| 17 | 19 | ||
| 18 | /** | 20 | /** |
| 19 | - * 发送 {@link MpConfigRefreshMessage} 消息 | 21 | + * 发送 {@link MpAccountRefreshMessage} 消息 |
| 20 | */ | 22 | */ |
| 21 | - public void sendDictDataRefreshMessage() { | ||
| 22 | - MpConfigRefreshMessage message = new MpConfigRefreshMessage(); | 23 | + public void sendAccountRefreshMessage() { |
| 24 | + MpAccountRefreshMessage message = new MpAccountRefreshMessage(); | ||
| 23 | redisMQTemplate.send(message); | 25 | redisMQTemplate.send(message); |
| 24 | } | 26 | } |
| 25 | 27 |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountService.java
| @@ -5,12 +5,11 @@ import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReq | @@ -5,12 +5,11 @@ import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReq | ||
| 5 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; | 5 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO; |
| 6 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountUpdateReqVO; | 6 | import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; | 7 | import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; |
| 8 | -import com.baomidou.mybatisplus.core.toolkit.support.SFunction; | ||
| 9 | 8 | ||
| 10 | import javax.validation.Valid; | 9 | import javax.validation.Valid; |
| 11 | 10 | ||
| 12 | /** | 11 | /** |
| 13 | - * 公众号账户 Service 接口 | 12 | + * 公众号账号 Service 接口 |
| 14 | * | 13 | * |
| 15 | * @author 芋道源码 | 14 | * @author 芋道源码 |
| 16 | */ | 15 | */ |
| @@ -22,7 +21,7 @@ public interface MpAccountService { | @@ -22,7 +21,7 @@ public interface MpAccountService { | ||
| 22 | void initLocalCache(); | 21 | void initLocalCache(); |
| 23 | 22 | ||
| 24 | /** | 23 | /** |
| 25 | - * 创建公众号账户 | 24 | + * 创建公众号账号 |
| 26 | * | 25 | * |
| 27 | * @param createReqVO 创建信息 | 26 | * @param createReqVO 创建信息 |
| 28 | * @return 编号 | 27 | * @return 编号 |
| @@ -30,51 +29,57 @@ public interface MpAccountService { | @@ -30,51 +29,57 @@ public interface MpAccountService { | ||
| 30 | Long createAccount(@Valid MpAccountCreateReqVO createReqVO); | 29 | Long createAccount(@Valid MpAccountCreateReqVO createReqVO); |
| 31 | 30 | ||
| 32 | /** | 31 | /** |
| 33 | - * 更新公众号账户 | 32 | + * 更新公众号账号 |
| 34 | * | 33 | * |
| 35 | * @param updateReqVO 更新信息 | 34 | * @param updateReqVO 更新信息 |
| 36 | */ | 35 | */ |
| 37 | void updateAccount(@Valid MpAccountUpdateReqVO updateReqVO); | 36 | void updateAccount(@Valid MpAccountUpdateReqVO updateReqVO); |
| 38 | 37 | ||
| 39 | /** | 38 | /** |
| 40 | - * 删除公众号账户 | 39 | + * 删除公众号账号 |
| 41 | * | 40 | * |
| 42 | * @param id 编号 | 41 | * @param id 编号 |
| 43 | */ | 42 | */ |
| 44 | void deleteAccount(Long id); | 43 | void deleteAccount(Long id); |
| 45 | 44 | ||
| 46 | /** | 45 | /** |
| 47 | - * 获得公众号账户 | 46 | + * 获得公众号账号 |
| 48 | * | 47 | * |
| 49 | * @param id 编号 | 48 | * @param id 编号 |
| 50 | - * @return 公众号账户 | 49 | + * @return 公众号账号 |
| 51 | */ | 50 | */ |
| 52 | MpAccountDO getAccount(Long id); | 51 | MpAccountDO getAccount(Long id); |
| 53 | 52 | ||
| 54 | /** | 53 | /** |
| 55 | - * 从缓存中,获得公众号账户 | 54 | + * 从缓存中,获得公众号账号 |
| 56 | * | 55 | * |
| 57 | * @param appId 微信公众号 appId | 56 | * @param appId 微信公众号 appId |
| 58 | - * @return 公众号账户 | 57 | + * @return 公众号账号 |
| 59 | */ | 58 | */ |
| 60 | MpAccountDO getAccountFromCache(String appId); | 59 | MpAccountDO getAccountFromCache(String appId); |
| 61 | 60 | ||
| 62 | /** | 61 | /** |
| 63 | - * 获得公众号账户分页 | 62 | + * 获得公众号账号分页 |
| 64 | * | 63 | * |
| 65 | * @param pageReqVO 分页查询 | 64 | * @param pageReqVO 分页查询 |
| 66 | - * @return 公众号账户分页 | 65 | + * @return 公众号账号分页 |
| 67 | */ | 66 | */ |
| 68 | PageResult<MpAccountDO> getAccountPage(MpAccountPageReqVO pageReqVO); | 67 | PageResult<MpAccountDO> getAccountPage(MpAccountPageReqVO pageReqVO); |
| 69 | 68 | ||
| 70 | - // TODO 芋艿:去除这样的方法 | ||
| 71 | /** | 69 | /** |
| 72 | - * 查询账户 | 70 | + * 生成公众号账号的二维码 |
| 73 | * | 71 | * |
| 74 | - * @param field | ||
| 75 | - * @param val | ||
| 76 | - * @return | 72 | + * @param id 编号 |
| 73 | + */ | ||
| 74 | + void generateAccountQrCode(Long id); | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 清空公众号账号的 API 配额 | ||
| 78 | + * | ||
| 79 | + * 参考文档:<a href="https://developers.weixin.qq.com/doc/offiaccount/Message_Management/API_Call_Limits.html">接口调用频次限制说明</a> | ||
| 80 | + * | ||
| 81 | + * @param id 编号 | ||
| 77 | */ | 82 | */ |
| 78 | - MpAccountDO findBy(SFunction<MpAccountDO, ?> field, Object val); | 83 | + void clearAccountQuota(Long id); |
| 79 | 84 | ||
| 80 | } | 85 | } |
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java
| 1 | package cn.iocoder.yudao.module.mp.service.account; | 1 | package cn.iocoder.yudao.module.mp.service.account; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.ObjUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | 4 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| @@ -12,24 +13,27 @@ import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; | @@ -12,24 +13,27 @@ import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; | ||
| 12 | import cn.iocoder.yudao.module.mp.dal.mysql.account.MpAccountMapper; | 13 | import cn.iocoder.yudao.module.mp.dal.mysql.account.MpAccountMapper; |
| 13 | import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants; | 14 | import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants; |
| 14 | import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory; | 15 | import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory; |
| 15 | -import cn.iocoder.yudao.module.mp.mq.producer.MpConfigProducer; | ||
| 16 | -import com.baomidou.mybatisplus.core.toolkit.support.SFunction; | 16 | +import cn.iocoder.yudao.module.mp.mq.producer.MpAccountProducer; |
| 17 | +import com.google.common.annotations.VisibleForTesting; | ||
| 17 | import lombok.Getter; | 18 | import lombok.Getter; |
| 18 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
| 20 | +import me.chanjar.weixin.common.error.WxErrorException; | ||
| 21 | +import me.chanjar.weixin.mp.api.WxMpService; | ||
| 22 | +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; | ||
| 19 | import org.springframework.context.annotation.Lazy; | 23 | import org.springframework.context.annotation.Lazy; |
| 20 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 21 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
| 22 | import org.springframework.validation.annotation.Validated; | 25 | import org.springframework.validation.annotation.Validated; |
| 23 | 26 | ||
| 24 | import javax.annotation.PostConstruct; | 27 | import javax.annotation.PostConstruct; |
| 25 | import javax.annotation.Resource; | 28 | import javax.annotation.Resource; |
| 26 | -import java.time.LocalDateTime; | ||
| 27 | import java.util.List; | 29 | import java.util.List; |
| 28 | import java.util.Map; | 30 | import java.util.Map; |
| 29 | 31 | ||
| 32 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 33 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS; | ||
| 30 | 34 | ||
| 31 | /** | 35 | /** |
| 32 | - * 公众号账户 Service 实现类 | 36 | + * 公众号账号 Service 实现类 |
| 33 | * | 37 | * |
| 34 | * @author fengdan | 38 | * @author fengdan |
| 35 | */ | 39 | */ |
| @@ -39,12 +43,6 @@ import java.util.Map; | @@ -39,12 +43,6 @@ import java.util.Map; | ||
| 39 | public class MpAccountServiceImpl implements MpAccountService { | 43 | public class MpAccountServiceImpl implements MpAccountService { |
| 40 | 44 | ||
| 41 | /** | 45 | /** |
| 42 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 43 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 44 | - */ | ||
| 45 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 46 | - | ||
| 47 | - /** | ||
| 48 | * 账号缓存 | 46 | * 账号缓存 |
| 49 | * key:账号编号 {@link MpAccountDO#getAppId()} | 47 | * key:账号编号 {@link MpAccountDO#getAppId()} |
| 50 | * | 48 | * |
| @@ -52,11 +50,6 @@ public class MpAccountServiceImpl implements MpAccountService { | @@ -52,11 +50,6 @@ public class MpAccountServiceImpl implements MpAccountService { | ||
| 52 | */ | 50 | */ |
| 53 | @Getter | 51 | @Getter |
| 54 | private volatile Map<String, MpAccountDO> accountCache; | 52 | private volatile Map<String, MpAccountDO> accountCache; |
| 55 | - /** | ||
| 56 | - * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 57 | - */ | ||
| 58 | - @Getter | ||
| 59 | - private volatile LocalDateTime maxUpdateTime; | ||
| 60 | 53 | ||
| 61 | @Resource | 54 | @Resource |
| 62 | private MpAccountMapper mpAccountMapper; | 55 | private MpAccountMapper mpAccountMapper; |
| @@ -66,89 +59,85 @@ public class MpAccountServiceImpl implements MpAccountService { | @@ -66,89 +59,85 @@ public class MpAccountServiceImpl implements MpAccountService { | ||
| 66 | private MpServiceFactory mpServiceFactory; | 59 | private MpServiceFactory mpServiceFactory; |
| 67 | 60 | ||
| 68 | @Resource | 61 | @Resource |
| 69 | - private MpConfigProducer mpConfigDataProducer; | 62 | + private MpAccountProducer mpAccountProducer; |
| 70 | 63 | ||
| 71 | @Override | 64 | @Override |
| 72 | @PostConstruct | 65 | @PostConstruct |
| 73 | public void initLocalCache() { | 66 | public void initLocalCache() { |
| 74 | - initLocalCacheIfUpdate(null); | ||
| 75 | - } | ||
| 76 | - | ||
| 77 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 78 | - public void schedulePeriodicRefresh() { | ||
| 79 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 80 | - } | ||
| 81 | - | ||
| 82 | - /** | ||
| 83 | - * 刷新本地缓存 | ||
| 84 | - * | ||
| 85 | - * @param maxUpdateTime 最大更新时间 | ||
| 86 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 87 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 88 | - */ | ||
| 89 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 90 | // 注意:忽略自动多租户,因为要全局初始化缓存 | 67 | // 注意:忽略自动多租户,因为要全局初始化缓存 |
| 91 | TenantUtils.executeIgnore(() -> { | 68 | TenantUtils.executeIgnore(() -> { |
| 92 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 93 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 94 | - if (maxUpdateTime != null | ||
| 95 | - && mpAccountMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 96 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 97 | - return; | ||
| 98 | - } | 69 | + // 第一步:查询数据 |
| 99 | List<MpAccountDO> accounts = mpAccountMapper.selectList(); | 70 | List<MpAccountDO> accounts = mpAccountMapper.selectList(); |
| 100 | log.info("[initLocalCacheIfUpdate][缓存公众号账号,数量为:{}]", accounts.size()); | 71 | log.info("[initLocalCacheIfUpdate][缓存公众号账号,数量为:{}]", accounts.size()); |
| 101 | 72 | ||
| 102 | // 第二步:构建缓存。创建或更新支付 Client | 73 | // 第二步:构建缓存。创建或更新支付 Client |
| 103 | mpServiceFactory.init(accounts); | 74 | mpServiceFactory.init(accounts); |
| 104 | accountCache = CollectionUtils.convertMap(accounts, MpAccountDO::getAppId); | 75 | accountCache = CollectionUtils.convertMap(accounts, MpAccountDO::getAppId); |
| 105 | - | ||
| 106 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 107 | - this.maxUpdateTime = CollectionUtils.getMaxValue(accounts, MpAccountDO::getUpdateTime); | ||
| 108 | }); | 76 | }); |
| 109 | } | 77 | } |
| 110 | 78 | ||
| 111 | @Override | 79 | @Override |
| 112 | public Long createAccount(MpAccountCreateReqVO createReqVO) { | 80 | public Long createAccount(MpAccountCreateReqVO createReqVO) { |
| 113 | - // TODO 芋艿:校验唯一性 | 81 | + // 校验 appId 唯一 |
| 82 | + validateAppIdUnique(null, createReqVO.getAppId()); | ||
| 83 | + | ||
| 114 | // 插入 | 84 | // 插入 |
| 115 | - MpAccountDO wxAccount = MpAccountConvert.INSTANCE.convert(createReqVO); | ||
| 116 | - mpAccountMapper.insert(wxAccount); | 85 | + MpAccountDO account = MpAccountConvert.INSTANCE.convert(createReqVO); |
| 86 | + mpAccountMapper.insert(account); | ||
| 117 | 87 | ||
| 118 | - // TODO 芋艿:刷新的方式 | ||
| 119 | - mpConfigDataProducer.sendDictDataRefreshMessage(); | ||
| 120 | - // 返回 | ||
| 121 | - return wxAccount.getId(); | 88 | + // 发送刷新消息 |
| 89 | + mpAccountProducer.sendAccountRefreshMessage(); | ||
| 90 | + return account.getId(); | ||
| 122 | } | 91 | } |
| 123 | 92 | ||
| 124 | @Override | 93 | @Override |
| 125 | public void updateAccount(MpAccountUpdateReqVO updateReqVO) { | 94 | public void updateAccount(MpAccountUpdateReqVO updateReqVO) { |
| 126 | - // TODO 芋艿:校验唯一性 | ||
| 127 | // 校验存在 | 95 | // 校验存在 |
| 128 | - validateWxAccountExists(updateReqVO.getId()); | 96 | + validateAccountExists(updateReqVO.getId()); |
| 97 | + // 校验 appId 唯一 | ||
| 98 | + validateAppIdUnique(updateReqVO.getId(), updateReqVO.getAppId()); | ||
| 99 | + | ||
| 129 | // 更新 | 100 | // 更新 |
| 130 | MpAccountDO updateObj = MpAccountConvert.INSTANCE.convert(updateReqVO); | 101 | MpAccountDO updateObj = MpAccountConvert.INSTANCE.convert(updateReqVO); |
| 131 | mpAccountMapper.updateById(updateObj); | 102 | mpAccountMapper.updateById(updateObj); |
| 132 | 103 | ||
| 133 | - // TODO 芋艿:刷新的方式 | ||
| 134 | - mpConfigDataProducer.sendDictDataRefreshMessage(); | 104 | + // 发送刷新消息 |
| 105 | + mpAccountProducer.sendAccountRefreshMessage(); | ||
| 135 | } | 106 | } |
| 136 | 107 | ||
| 137 | @Override | 108 | @Override |
| 138 | public void deleteAccount(Long id) { | 109 | public void deleteAccount(Long id) { |
| 139 | // 校验存在 | 110 | // 校验存在 |
| 140 | - validateWxAccountExists(id); | 111 | + validateAccountExists(id); |
| 141 | // 删除 | 112 | // 删除 |
| 142 | mpAccountMapper.deleteById(id); | 113 | mpAccountMapper.deleteById(id); |
| 143 | 114 | ||
| 144 | - // TODO 芋艿:刷新的方式 | ||
| 145 | - mpConfigDataProducer.sendDictDataRefreshMessage(); | 115 | + // 发送刷新消息 |
| 116 | + mpAccountProducer.sendAccountRefreshMessage(); | ||
| 146 | } | 117 | } |
| 147 | 118 | ||
| 148 | - private void validateWxAccountExists(Long id) { | ||
| 149 | - if (mpAccountMapper.selectById(id) == null) { | ||
| 150 | - throw ServiceExceptionUtil.exception(ErrorCodeConstants.WX_ACCOUNT_NOT_EXISTS); | 119 | + private MpAccountDO validateAccountExists(Long id) { |
| 120 | + MpAccountDO account = mpAccountMapper.selectById(id); | ||
| 121 | + if (account == null) { | ||
| 122 | + throw ServiceExceptionUtil.exception(ErrorCodeConstants.ACCOUNT_NOT_EXISTS); | ||
| 151 | } | 123 | } |
| 124 | + return account; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + @VisibleForTesting | ||
| 128 | + public void validateAppIdUnique(Long id, String appId) { | ||
| 129 | + // 多个租户,appId 是不能重复,否则公众号回调会无法识别 | ||
| 130 | + TenantUtils.executeIgnore(() -> { | ||
| 131 | + MpAccountDO account = mpAccountMapper.selectByAppId(appId); | ||
| 132 | + if (account == null) { | ||
| 133 | + return; | ||
| 134 | + } | ||
| 135 | + // 存在 account 记录的情况下 | ||
| 136 | + if (id == null // 新增时,说明重复 | ||
| 137 | + || ObjUtil.notEqual(id, account.getId())) { // 更新时,如果 id 不一致,说明重复 | ||
| 138 | + throw exception(USER_USERNAME_EXISTS); | ||
| 139 | + } | ||
| 140 | + }); | ||
| 152 | } | 141 | } |
| 153 | 142 | ||
| 154 | @Override | 143 | @Override |
| @@ -167,8 +156,36 @@ public class MpAccountServiceImpl implements MpAccountService { | @@ -167,8 +156,36 @@ public class MpAccountServiceImpl implements MpAccountService { | ||
| 167 | } | 156 | } |
| 168 | 157 | ||
| 169 | @Override | 158 | @Override |
| 170 | - public MpAccountDO findBy(SFunction<MpAccountDO, ?> field, Object val) { | ||
| 171 | - return mpAccountMapper.selectOne(field, val); | 159 | + public void generateAccountQrCode(Long id) { |
| 160 | + // 校验存在 | ||
| 161 | + MpAccountDO account = validateAccountExists(id); | ||
| 162 | + | ||
| 163 | + // 生成二维码 | ||
| 164 | + WxMpService mpService = mpServiceFactory.getRequiredMpService(account.getAppId()); | ||
| 165 | + String qrCodeUrl; | ||
| 166 | + try { | ||
| 167 | + WxMpQrCodeTicket qrCodeTicket = mpService.getQrcodeService().qrCodeCreateLastTicket("default"); | ||
| 168 | + qrCodeUrl = mpService.getQrcodeService().qrCodePictureUrl(qrCodeTicket.getTicket()); | ||
| 169 | + } catch (WxErrorException e) { | ||
| 170 | + throw exception(ErrorCodeConstants.ACCOUNT_GENERATE_QR_CODE_FAIL, e.getError().getErrorMsg()); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + // 保存二维码 | ||
| 174 | + mpAccountMapper.updateById(new MpAccountDO().setId(id).setQrCodeUrl(qrCodeUrl)); | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + @Override | ||
| 178 | + public void clearAccountQuota(Long id) { | ||
| 179 | + // 校验存在 | ||
| 180 | + MpAccountDO account = validateAccountExists(id); | ||
| 181 | + | ||
| 182 | + // 生成二维码 | ||
| 183 | + WxMpService mpService = mpServiceFactory.getRequiredMpService(account.getAppId()); | ||
| 184 | + try { | ||
| 185 | + mpService.clearQuota(account.getAppId()); | ||
| 186 | + } catch (WxErrorException e) { | ||
| 187 | + throw exception(ErrorCodeConstants.ACCOUNT_CLEAR_QUOTA_FAIL, e.getError().getErrorMsg()); | ||
| 188 | + } | ||
| 172 | } | 189 | } |
| 173 | 190 | ||
| 174 | } | 191 | } |
yudao-ui-admin/src/api/mp/account.js
| 1 | import request from '@/utils/request' | 1 | import request from '@/utils/request' |
| 2 | 2 | ||
| 3 | -// 创建公众号账户 | 3 | +// 创建公众号账号 |
| 4 | export function createAccount(data) { | 4 | export function createAccount(data) { |
| 5 | return request({ | 5 | return request({ |
| 6 | url: '/mp/account/create', | 6 | url: '/mp/account/create', |
| @@ -9,7 +9,7 @@ export function createAccount(data) { | @@ -9,7 +9,7 @@ export function createAccount(data) { | ||
| 9 | }) | 9 | }) |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | -// 更新公众号账户 | 12 | +// 更新公众号账号 |
| 13 | export function updateAccount(data) { | 13 | export function updateAccount(data) { |
| 14 | return request({ | 14 | return request({ |
| 15 | url: '/mp/account/update', | 15 | url: '/mp/account/update', |
| @@ -18,7 +18,7 @@ export function updateAccount(data) { | @@ -18,7 +18,7 @@ export function updateAccount(data) { | ||
| 18 | }) | 18 | }) |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | -// 删除公众号账户 | 21 | +// 删除公众号账号 |
| 22 | export function deleteAccount(id) { | 22 | export function deleteAccount(id) { |
| 23 | return request({ | 23 | return request({ |
| 24 | url: '/mp/account/delete?id=' + id, | 24 | url: '/mp/account/delete?id=' + id, |
| @@ -26,7 +26,7 @@ export function deleteAccount(id) { | @@ -26,7 +26,7 @@ export function deleteAccount(id) { | ||
| 26 | }) | 26 | }) |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | -// 获得公众号账户 | 29 | +// 获得公众号账号 |
| 30 | export function getAccount(id) { | 30 | export function getAccount(id) { |
| 31 | return request({ | 31 | return request({ |
| 32 | url: '/mp/account/get?id=' + id, | 32 | url: '/mp/account/get?id=' + id, |
| @@ -34,7 +34,7 @@ export function getAccount(id) { | @@ -34,7 +34,7 @@ export function getAccount(id) { | ||
| 34 | }) | 34 | }) |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | -// 获得公众号账户分页 | 37 | +// 获得公众号账号分页 |
| 38 | export function getAccountPage(query) { | 38 | export function getAccountPage(query) { |
| 39 | return request({ | 39 | return request({ |
| 40 | url: '/mp/account/page', | 40 | url: '/mp/account/page', |
| @@ -43,12 +43,18 @@ export function getAccountPage(query) { | @@ -43,12 +43,18 @@ export function getAccountPage(query) { | ||
| 43 | }) | 43 | }) |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | -// 导出公众号账户 Excel | ||
| 47 | -export function exportAccountExcel(query) { | 46 | +// 生成公众号二维码 |
| 47 | +export function generateAccountQrCode(id) { | ||
| 48 | return request({ | 48 | return request({ |
| 49 | - url: '/mp/account/export-excel', | ||
| 50 | - method: 'get', | ||
| 51 | - params: query, | ||
| 52 | - responseType: 'blob' | 49 | + url: '/mp/account/generate-qr-code?id=' + id, |
| 50 | + method: 'put' | ||
| 51 | + }) | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +// 清空公众号 API 配额 | ||
| 55 | +export function clearAccountQuota(id) { | ||
| 56 | + return request({ | ||
| 57 | + url: '/mp/account/clear-quota?id=' + id, | ||
| 58 | + method: 'put' | ||
| 53 | }) | 59 | }) |
| 54 | } | 60 | } |
yudao-ui-admin/src/views/mp/account/index.vue
| @@ -28,16 +28,25 @@ | @@ -28,16 +28,25 @@ | ||
| 28 | <el-table-column label="名称" align="center" prop="name"/> | 28 | <el-table-column label="名称" align="center" prop="name"/> |
| 29 | <el-table-column label="微信号" align="center" prop="account" width="180"/> | 29 | <el-table-column label="微信号" align="center" prop="account" width="180"/> |
| 30 | <el-table-column label="appId" align="center" prop="appId" width="180"/> | 30 | <el-table-column label="appId" align="center" prop="appId" width="180"/> |
| 31 | - <el-table-column label="appSecret" align="center" prop="appSecret" width="180"/> | ||
| 32 | - <el-table-column label="Token" align="center" prop="token"/> | ||
| 33 | - <el-table-column label="密钥" align="center" prop="aesKey"/> | ||
| 34 | - <el-table-column label="二维码" align="center" prop="qrCodeUrl"/> | ||
| 35 | - <el-table-column label="备注" align="center" prop="remark"/> | ||
| 36 | - <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | ||
| 37 | - <template slot-scope="scope"> | ||
| 38 | - <span>{{ parseTime(scope.row.createTime) }}</span> | 31 | +<!-- <el-table-column label="appSecret" align="center" prop="appSecret" width="180"/>--> |
| 32 | +<!-- <el-table-column label="token" align="center" prop="token"/>--> | ||
| 33 | +<!-- <el-table-column label="消息加解密密钥" align="center" prop="aesKey"/>--> | ||
| 34 | + <el-table-column label="服务器地址(URL)" align="center" prop="appId" width="360"> | ||
| 35 | + <template v-slot="scope"> | ||
| 36 | + {{ 'http://服务端地址/mp/open/' + scope.row.appId }} | ||
| 39 | </template> | 37 | </template> |
| 40 | </el-table-column> | 38 | </el-table-column> |
| 39 | + <el-table-column label="二维码" align="center" prop="qrCodeUrl"> | ||
| 40 | + <template v-slot="scope"> | ||
| 41 | + <img v-if="scope.row.qrCodeUrl" :src="scope.row.qrCodeUrl" alt="二维码" style="height: 100px;" /> | ||
| 42 | + </template> | ||
| 43 | + </el-table-column> | ||
| 44 | + <el-table-column label="备注" align="center" prop="remark"/> | ||
| 45 | +<!-- <el-table-column label="创建时间" align="center" prop="createTime" width="180">--> | ||
| 46 | +<!-- <template slot-scope="scope">--> | ||
| 47 | +<!-- <span>{{ parseTime(scope.row.createTime) }}</span>--> | ||
| 48 | +<!-- </template>--> | ||
| 49 | +<!-- </el-table-column>--> | ||
| 41 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | 50 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
| 42 | <template slot-scope="scope"> | 51 | <template slot-scope="scope"> |
| 43 | <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" | 52 | <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" |
| @@ -46,6 +55,12 @@ | @@ -46,6 +55,12 @@ | ||
| 46 | <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" | 55 | <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" |
| 47 | v-hasPermi="['mp:account:delete']">删除 | 56 | v-hasPermi="['mp:account:delete']">删除 |
| 48 | </el-button> | 57 | </el-button> |
| 58 | + <el-button size="mini" type="text" icon="el-icon-refresh" @click="handleGenerateQrCode(scope.row)" | ||
| 59 | + v-hasPermi="['mp:account:qr-code']">生成二维码 | ||
| 60 | + </el-button> | ||
| 61 | + <el-button size="mini" type="text" icon="el-icon-share" @click="handleCleanQuota(scope.row)" | ||
| 62 | + v-hasPermi="['mp:account:clear-quota']">清空 API 配额 | ||
| 63 | + </el-button> | ||
| 49 | </template> | 64 | </template> |
| 50 | </el-table-column> | 65 | </el-table-column> |
| 51 | </el-table> | 66 | </el-table> |
| @@ -55,13 +70,13 @@ | @@ -55,13 +70,13 @@ | ||
| 55 | 70 | ||
| 56 | <!-- 对话框(添加 / 修改) --> | 71 | <!-- 对话框(添加 / 修改) --> |
| 57 | <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> | 72 | <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> |
| 58 | - <el-form ref="form" :model="form" :rules="rules" label-width="100px"> | 73 | + <el-form ref="form" :model="form" :rules="rules" label-width="120px"> |
| 59 | <el-form-item label="名称" prop="name"> | 74 | <el-form-item label="名称" prop="name"> |
| 60 | <el-input v-model="form.name" placeholder="请输入名称"/> | 75 | <el-input v-model="form.name" placeholder="请输入名称"/> |
| 61 | </el-form-item> | 76 | </el-form-item> |
| 62 | <el-form-item label="微信号" prop="account"> | 77 | <el-form-item label="微信号" prop="account"> |
| 63 | <span slot="label"> | 78 | <span slot="label"> |
| 64 | - <el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单【设置】-【公众号设置】-【帐号详情】中能找到原始ID" placement="top"> | 79 | + <el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 账号详情] 中能找到「微信号」" placement="top"> |
| 65 | <i class="el-icon-question" /> | 80 | <i class="el-icon-question" /> |
| 66 | </el-tooltip> | 81 | </el-tooltip> |
| 67 | 微信号 | 82 | 微信号 |
| @@ -70,30 +85,30 @@ | @@ -70,30 +85,30 @@ | ||
| 70 | </el-form-item> | 85 | </el-form-item> |
| 71 | <el-form-item label="appId" prop="appId"> | 86 | <el-form-item label="appId" prop="appId"> |
| 72 | <span slot="label"> | 87 | <span slot="label"> |
| 73 | - <el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单【开发】-【基本配置】中能找到 appId" placement="top"> | 88 | + <el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者ID(AppID)」" placement="top"> |
| 74 | <i class="el-icon-question" /> | 89 | <i class="el-icon-question" /> |
| 75 | </el-tooltip> | 90 | </el-tooltip> |
| 76 | appId | 91 | appId |
| 77 | </span> | 92 | </span> |
| 78 | <el-input v-model="form.appId" placeholder="请输入公众号 appId"/> | 93 | <el-input v-model="form.appId" placeholder="请输入公众号 appId"/> |
| 79 | </el-form-item> | 94 | </el-form-item> |
| 80 | - <el-form-item label="密钥" prop="appSecret"> | 95 | + <el-form-item label="appSecret" prop="appSecret"> |
| 81 | <span slot="label"> | 96 | <span slot="label"> |
| 82 | - <el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单【开发】-【基本配置】中能找到密钥" placement="top"> | 97 | + <el-tooltip content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者密码(AppSecret)」" placement="top"> |
| 83 | <i class="el-icon-question" /> | 98 | <i class="el-icon-question" /> |
| 84 | </el-tooltip> | 99 | </el-tooltip> |
| 85 | - 密钥 | 100 | + appSecret |
| 86 | </span> | 101 | </span> |
| 87 | <el-input v-model="form.appSecret" placeholder="请输入公众号 appSecret"/> | 102 | <el-input v-model="form.appSecret" placeholder="请输入公众号 appSecret"/> |
| 88 | </el-form-item> | 103 | </el-form-item> |
| 89 | <el-form-item label="token" prop="token"> | 104 | <el-form-item label="token" prop="token"> |
| 90 | <el-input v-model="form.token" placeholder="请输入公众号token"/> | 105 | <el-input v-model="form.token" placeholder="请输入公众号token"/> |
| 91 | </el-form-item> | 106 | </el-form-item> |
| 92 | - <el-form-item label="加密密钥" prop="aesKey"> | ||
| 93 | - <el-input v-model="form.aesKey" placeholder="请输入加密密钥"/> | 107 | + <el-form-item label="消息加解密密钥" prop="aesKey"> |
| 108 | + <el-input v-model="form.aesKey" placeholder="请输入消息加解密密钥"/> | ||
| 94 | </el-form-item> | 109 | </el-form-item> |
| 95 | <el-form-item label="备注" prop="remark"> | 110 | <el-form-item label="备注" prop="remark"> |
| 96 | - <el-input v-model="form.remark" placeholder="请输入备注"/> | 111 | + <el-input type="textarea" v-model="form.remark" placeholder="请输入备注"/> |
| 97 | </el-form-item> | 112 | </el-form-item> |
| 98 | </el-form> | 113 | </el-form> |
| 99 | <div slot="footer" class="dialog-footer"> | 114 | <div slot="footer" class="dialog-footer"> |
| @@ -105,7 +120,15 @@ | @@ -105,7 +120,15 @@ | ||
| 105 | </template> | 120 | </template> |
| 106 | 121 | ||
| 107 | <script> | 122 | <script> |
| 108 | -import { createAccount, deleteAccount, getAccount, getAccountPage, updateAccount} from '@/api/mp/account' | 123 | +import { |
| 124 | + clearAccountQuota, | ||
| 125 | + createAccount, | ||
| 126 | + deleteAccount, | ||
| 127 | + generateAccountQrCode, | ||
| 128 | + getAccount, | ||
| 129 | + getAccountPage, | ||
| 130 | + updateAccount | ||
| 131 | +} from '@/api/mp/account' | ||
| 109 | 132 | ||
| 110 | export default { | 133 | export default { |
| 111 | name: 'mpAccount', | 134 | name: 'mpAccount', |
| @@ -120,7 +143,7 @@ export default { | @@ -120,7 +143,7 @@ export default { | ||
| 120 | showSearch: true, | 143 | showSearch: true, |
| 121 | // 总条数 | 144 | // 总条数 |
| 122 | total: 0, | 145 | total: 0, |
| 123 | - // 公众号账户列表 | 146 | + // 公众号账号列表 |
| 124 | list: [], | 147 | list: [], |
| 125 | // 弹出层标题 | 148 | // 弹出层标题 |
| 126 | title: '', | 149 | title: '', |
| @@ -139,7 +162,7 @@ export default { | @@ -139,7 +162,7 @@ export default { | ||
| 139 | // 表单校验 | 162 | // 表单校验 |
| 140 | rules: { | 163 | rules: { |
| 141 | name: [{required: true, message: '名称不能为空', trigger: 'blur'}], | 164 | name: [{required: true, message: '名称不能为空', trigger: 'blur'}], |
| 142 | - account: [{required: true, message: '公众号账户不能为空', trigger: 'blur'}], | 165 | + account: [{required: true, message: '公众号账号不能为空', trigger: 'blur'}], |
| 143 | appId: [{required: true, message: '公众号 appId 不能为空', trigger: 'blur'}], | 166 | appId: [{required: true, message: '公众号 appId 不能为空', trigger: 'blur'}], |
| 144 | appSecret: [{required: true, message: '公众号密钥不能为空', trigger: 'blur'}], | 167 | appSecret: [{required: true, message: '公众号密钥不能为空', trigger: 'blur'}], |
| 145 | token: [{required: true, message: '公众号 token 不能为空', trigger: 'blur'}], | 168 | token: [{required: true, message: '公众号 token 不能为空', trigger: 'blur'}], |
| @@ -199,7 +222,7 @@ export default { | @@ -199,7 +222,7 @@ export default { | ||
| 199 | handleAdd() { | 222 | handleAdd() { |
| 200 | this.reset() | 223 | this.reset() |
| 201 | this.open = true | 224 | this.open = true |
| 202 | - this.title = '添加公众号账户' | 225 | + this.title = '添加公众号账号' |
| 203 | }, | 226 | }, |
| 204 | /** 修改按钮操作 */ | 227 | /** 修改按钮操作 */ |
| 205 | handleUpdate(row) { | 228 | handleUpdate(row) { |
| @@ -208,7 +231,7 @@ export default { | @@ -208,7 +231,7 @@ export default { | ||
| 208 | getAccount(id).then(response => { | 231 | getAccount(id).then(response => { |
| 209 | this.form = response.data | 232 | this.form = response.data |
| 210 | this.open = true | 233 | this.open = true |
| 211 | - this.title = '修改公众号账户' | 234 | + this.title = '修改公众号账号' |
| 212 | this.disabled = true | 235 | this.disabled = true |
| 213 | }) | 236 | }) |
| 214 | }, | 237 | }, |
| @@ -238,7 +261,7 @@ export default { | @@ -238,7 +261,7 @@ export default { | ||
| 238 | /** 删除按钮操作 */ | 261 | /** 删除按钮操作 */ |
| 239 | handleDelete(row) { | 262 | handleDelete(row) { |
| 240 | const id = row.id | 263 | const id = row.id |
| 241 | - this.$modal.confirm('是否确认删除公众号账户编号为"' + row.name + '"的数据项?').then(function () { | 264 | + this.$modal.confirm('是否确认删除公众号账号编号为"' + row.name + '"的数据项?').then(function () { |
| 242 | return deleteAccount(id) | 265 | return deleteAccount(id) |
| 243 | }).then(() => { | 266 | }).then(() => { |
| 244 | this.getList() | 267 | this.getList() |
| @@ -246,6 +269,27 @@ export default { | @@ -246,6 +269,27 @@ export default { | ||
| 246 | }).catch(() => { | 269 | }).catch(() => { |
| 247 | }) | 270 | }) |
| 248 | }, | 271 | }, |
| 272 | + /** 生成二维码的按钮操作 */ | ||
| 273 | + handleGenerateQrCode(row) { | ||
| 274 | + const id = row.id | ||
| 275 | + this.$modal.confirm('是否确认生成公众号账号编号为"' + row.name + '"的二维码?').then(function () { | ||
| 276 | + return generateAccountQrCode(id) | ||
| 277 | + }).then(() => { | ||
| 278 | + this.getList() | ||
| 279 | + this.$modal.msgSuccess('生成二维码成功') | ||
| 280 | + }).catch(() => { | ||
| 281 | + }) | ||
| 282 | + }, | ||
| 283 | + /** 清空二维码 API 配额的按钮操作 */ | ||
| 284 | + handleCleanQuota(row) { | ||
| 285 | + const id = row.id | ||
| 286 | + this.$modal.confirm('是否清空生成公众号账号编号为"' + row.name + '"的 API 配额?').then(function () { | ||
| 287 | + return clearAccountQuota(id) | ||
| 288 | + }).then(() => { | ||
| 289 | + this.$modal.msgSuccess('清空 API 配额成功') | ||
| 290 | + }).catch(() => { | ||
| 291 | + }) | ||
| 292 | + }, | ||
| 249 | } | 293 | } |
| 250 | } | 294 | } |
| 251 | </script> | 295 | </script> |