Commit 2ac2af64d4bd0649538f2f951ad01d741ce12cb9

Authored by YunaiV
1 parent f05e086a

mp:实现 user 的 ui 界面

Showing 21 changed files with 505 additions and 476 deletions
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/DefaultDatabaseQueryTest.java
1 package cn.iocoder.yudao.module.infra.service; 1 package cn.iocoder.yudao.module.infra.service;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 -import com.baomidou.mybatisplus.generator.IDatabaseQuery.DefaultDatabaseQuery;  
5 import com.baomidou.mybatisplus.generator.config.DataSourceConfig; 4 import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
6 import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder; 5 import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
7 import com.baomidou.mybatisplus.generator.config.po.TableInfo; 6 import com.baomidou.mybatisplus.generator.config.po.TableInfo;
  7 +import com.baomidou.mybatisplus.generator.query.DefaultQuery;
8 8
9 import java.util.List; 9 import java.util.List;
10 10
@@ -19,7 +19,7 @@ public class DefaultDatabaseQueryTest { @@ -19,7 +19,7 @@ public class DefaultDatabaseQueryTest {
19 19
20 ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, null, null, null, null); 20 ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, null, null, null, null);
21 21
22 - DefaultDatabaseQuery query = new DefaultDatabaseQuery(builder); 22 + DefaultQuery query = new DefaultQuery(builder);
23 23
24 long time = System.currentTimeMillis(); 24 long time = System.currentTimeMillis();
25 List<TableInfo> tableInfos = query.queryTables(); 25 List<TableInfo> tableInfos = query.queryTables();
yudao-module-mp/yudao-module-mp-api/src/main/java/cn/iocoder/yudao/module/mp/enums/ErrorCodeConstants.java
@@ -27,6 +27,10 @@ public interface ErrorCodeConstants { @@ -27,6 +27,10 @@ public interface ErrorCodeConstants {
27 ErrorCode TAG_DELETE_FAIL = new ErrorCode(1006002001, "删除标签失败,原因:{}"); 27 ErrorCode TAG_DELETE_FAIL = new ErrorCode(1006002001, "删除标签失败,原因:{}");
28 ErrorCode TAG_GET_FAIL = new ErrorCode(1006002001, "获得标签失败,原因:{}"); 28 ErrorCode TAG_GET_FAIL = new ErrorCode(1006002001, "获得标签失败,原因:{}");
29 29
  30 + // ========== 公众号标签 1006003000============
  31 + ErrorCode USER_NOT_EXISTS = new ErrorCode(1006003000, "用户不存在");
  32 + ErrorCode USER_UPDATE_TAG_FAIL = new ErrorCode(1006003001, "更新用户标签失败,原因:{}");
  33 +
30 // TODO 要处理下 34 // TODO 要处理下
31 ErrorCode COMMON_NOT_EXISTS = new ErrorCode(1006001002, "用户不存在"); 35 ErrorCode COMMON_NOT_EXISTS = new ErrorCode(1006001002, "用户不存在");
32 36
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/tag/MpTagController.java
@@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.mp.controller.admin.tag; @@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.mp.controller.admin.tag;
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.tag.vo.MpTagCreateReqVO;  
6 -import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagPageReqVO;  
7 -import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagRespVO;  
8 -import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO; 5 +import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.*;
9 import cn.iocoder.yudao.module.mp.convert.tag.MpTagConvert; 6 import cn.iocoder.yudao.module.mp.convert.tag.MpTagConvert;
10 import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO; 7 import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
11 import cn.iocoder.yudao.module.mp.service.tag.MpTagService; 8 import cn.iocoder.yudao.module.mp.service.tag.MpTagService;
@@ -18,6 +15,7 @@ import org.springframework.web.bind.annotation.*; @@ -18,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
18 15
19 import javax.annotation.Resource; 16 import javax.annotation.Resource;
20 import javax.validation.Valid; 17 import javax.validation.Valid;
  18 +import java.util.List;
21 19
22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
23 21
@@ -62,6 +60,14 @@ public class MpTagController { @@ -62,6 +60,14 @@ public class MpTagController {
62 return success(MpTagConvert.INSTANCE.convertPage(pageResult)); 60 return success(MpTagConvert.INSTANCE.convertPage(pageResult));
63 } 61 }
64 62
  63 + @GetMapping("/list-all-simple")
  64 + @ApiOperation(value = "获取公众号账号精简信息列表")
  65 + @PreAuthorize("@ss.hasPermission('mp:account:query')")
  66 + public CommonResult<List<MpTagSimpleRespVO>> getSimpleTags() {
  67 + List<MpTagDO> list = mpTagService.getTagList();
  68 + return success(MpTagConvert.INSTANCE.convertList02(list));
  69 + }
  70 +
65 @PostMapping("/sync") 71 @PostMapping("/sync")
66 @ApiOperation("同步公众号标签") 72 @ApiOperation("同步公众号标签")
67 @ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, dataTypeClass = Long.class) 73 @ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, dataTypeClass = Long.class)
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/tag/vo/MpTagSimpleRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mp.controller.admin.tag.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +@ApiModel("管理后台 - 公众号标签精简信息 Response VO")
  8 +@Data
  9 +public class MpTagSimpleRespVO {
  10 +
  11 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  12 + private Long id;
  13 +
  14 + @ApiModelProperty(value = "公众号的标签编号", required = true, example = "2048")
  15 + private Long tagId;
  16 +
  17 + @ApiModelProperty(value = "标签名称", required = true, example = "快乐")
  18 + private String name;
  19 +
  20 +}
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/MpUserController.http
@@ -3,3 +3,16 @@ POST {{baseUrl}}/mp/user/sync?accountId=1 @@ -3,3 +3,16 @@ POST {{baseUrl}}/mp/user/sync?accountId=1
3 Content-Type: application/json 3 Content-Type: application/json
4 Authorization: Bearer {{token}} 4 Authorization: Bearer {{token}}
5 tenant-id: {{adminTenentId}} 5 tenant-id: {{adminTenentId}}
  6 +
  7 +### 请求 /mp/user/update 接口 => 成功
  8 +PUT {{baseUrl}}/mp/user/update
  9 +Content-Type: application/json
  10 +Authorization: Bearer {{token}}
  11 +tenant-id: {{adminTenentId}}
  12 +
  13 +{
  14 + "id": "3",
  15 + "nickname": "test",
  16 + "remark": "测试备注",
  17 + "tagIds": [103, 104]
  18 +}
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/MpUserController.java
@@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.mp.controller.admin.user; @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.mp.controller.admin.user;
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.user.vo.*; 5 +import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO;
  6 +import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserRespVO;
  7 +import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserUpdateReqVO;
6 import cn.iocoder.yudao.module.mp.convert.user.MpUserConvert; 8 import cn.iocoder.yudao.module.mp.convert.user.MpUserConvert;
7 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO; 9 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
8 import cn.iocoder.yudao.module.mp.service.user.MpUserService; 10 import cn.iocoder.yudao.module.mp.service.user.MpUserService;
@@ -18,7 +20,7 @@ import javax.validation.Valid; @@ -18,7 +20,7 @@ import javax.validation.Valid;
18 20
19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
20 22
21 -@Api(tags = "管理后台 - 微信公众号粉丝") 23 +@Api(tags = "管理后台 - 公众号粉丝")
22 @RestController 24 @RestController
23 @RequestMapping("/mp/user") 25 @RequestMapping("/mp/user")
24 @Validated 26 @Validated
@@ -28,13 +30,29 @@ public class MpUserController { @@ -28,13 +30,29 @@ public class MpUserController {
28 private MpUserService mpUserService; 30 private MpUserService mpUserService;
29 31
30 @GetMapping("/page") 32 @GetMapping("/page")
31 - @ApiOperation("获得微信公众号粉丝分页") 33 + @ApiOperation("获得公众号粉丝分页")
32 @PreAuthorize("@ss.hasPermission('mp:user:query')") 34 @PreAuthorize("@ss.hasPermission('mp:user:query')")
33 public CommonResult<PageResult<MpUserRespVO>> getUserPage(@Valid MpUserPageReqVO pageVO) { 35 public CommonResult<PageResult<MpUserRespVO>> getUserPage(@Valid MpUserPageReqVO pageVO) {
34 PageResult<MpUserDO> pageResult = mpUserService.getUserPage(pageVO); 36 PageResult<MpUserDO> pageResult = mpUserService.getUserPage(pageVO);
35 return success(MpUserConvert.INSTANCE.convertPage(pageResult)); 37 return success(MpUserConvert.INSTANCE.convertPage(pageResult));
36 } 38 }
37 39
  40 + @GetMapping("/get")
  41 + @ApiOperation("获得公众号粉丝")
  42 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  43 + @PreAuthorize("@ss.hasPermission('mp:user:query')")
  44 + public CommonResult<MpUserRespVO> getUser(@RequestParam("id") Long id) {
  45 + return success(MpUserConvert.INSTANCE.convert(mpUserService.getUser(id)));
  46 + }
  47 +
  48 + @PutMapping("/update")
  49 + @ApiOperation("更新公众号粉丝")
  50 + @PreAuthorize("@ss.hasPermission('mp:user:update')")
  51 + public CommonResult<Boolean> updateUser(@Valid @RequestBody MpUserUpdateReqVO updateReqVO) {
  52 + mpUserService.updateUser(updateReqVO);
  53 + return success(true);
  54 + }
  55 +
38 @PostMapping("/sync") 56 @PostMapping("/sync")
39 @ApiOperation("同步公众号粉丝") 57 @ApiOperation("同步公众号粉丝")
40 @ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, dataTypeClass = Long.class) 58 @ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, dataTypeClass = Long.class)
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserBaseVO.java deleted
1 -package cn.iocoder.yudao.module.mp.controller.admin.user.vo;  
2 -  
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.annotations.*;  
6 -import org.springframework.format.annotation.DateTimeFormat;  
7 -  
8 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
9 -  
10 -/**  
11 -* 微信公众号粉丝 Base VO,提供给添加、修改、详细的子 VO 使用  
12 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成  
13 -*/  
14 -@Data  
15 -public class MpUserBaseVO {  
16 -  
17 - @ApiModelProperty(value = "用户标识")  
18 - private String openid;  
19 -  
20 - @ApiModelProperty(value = "订阅状态,0未关注,1已关注")  
21 - private Integer subscribeStatus;  
22 -  
23 - @ApiModelProperty(value = "订阅时间")  
24 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
25 - private Date subscribeTime;  
26 -  
27 - @ApiModelProperty(value = "订阅时间")  
28 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
29 - private Date unsubscribeTime;  
30 -  
31 - @ApiModelProperty(value = "昵称")  
32 - private String nickname;  
33 -  
34 - @ApiModelProperty(value = "语言")  
35 - private String language;  
36 -  
37 - @ApiModelProperty(value = "国家")  
38 - private String country;  
39 -  
40 - @ApiModelProperty(value = "省份")  
41 - private String province;  
42 -  
43 - @ApiModelProperty(value = "城市")  
44 - private String city;  
45 -  
46 - @ApiModelProperty(value = "头像地址")  
47 - private String headImageUrl;  
48 -  
49 - @ApiModelProperty(value = "备注")  
50 - private String remark;  
51 -  
52 - @ApiModelProperty(value = "微信公众号ID")  
53 - private Long accountId;  
54 -  
55 - @ApiModelProperty(value = "微信公众号appid")  
56 - private String appId;  
57 -  
58 -}  
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserPageReqVO.java
1 package cn.iocoder.yudao.module.mp.controller.admin.user.vo; 1 package cn.iocoder.yudao.module.mp.controller.admin.user.vo;
2 2
3 -import lombok.*;  
4 -import io.swagger.annotations.*;  
5 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
6 9
7 -@ApiModel("管理后台 - 微信公众号粉丝分页 Request VO") 10 +import javax.validation.constraints.NotNull;
  11 +
  12 +@ApiModel("管理后台 - 公众号粉丝分页 Request VO")
8 @Data 13 @Data
9 @EqualsAndHashCode(callSuper = true) 14 @EqualsAndHashCode(callSuper = true)
10 @ToString(callSuper = true) 15 @ToString(callSuper = true)
11 public class MpUserPageReqVO extends PageParam { 16 public class MpUserPageReqVO extends PageParam {
12 17
13 - @ApiModelProperty(value = "用户标识") 18 + @ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
  19 + @NotNull(message = "公众号账号的编号不能为空")
  20 + private Long accountId;
  21 +
  22 + @ApiModelProperty(value = "公众号用户标识", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", notes = "模糊匹配")
14 private String openid; 23 private String openid;
15 24
16 - @ApiModelProperty(value = "昵称") 25 + @ApiModelProperty(value = "公众号用户昵称", example = "芋艿", notes = "模糊匹配")
17 private String nickname; 26 private String nickname;
18 27
19 - @ApiModelProperty(value = "微信公众号 ID")  
20 - private Long accountId;  
21 -  
22 } 28 }
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserRespVO.java
1 package cn.iocoder.yudao.module.mp.controller.admin.user.vo; 1 package cn.iocoder.yudao.module.mp.controller.admin.user.vo;
2 2
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.annotations.*; 3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
6 6
7 -@ApiModel("管理后台 - 微信公众号粉丝 Response VO") 7 +import java.time.LocalDateTime;
  8 +import java.util.Date;
  9 +import java.util.List;
  10 +
  11 +@ApiModel("管理后台 - 公众号粉丝 Response VO")
8 @Data 12 @Data
9 -@EqualsAndHashCode(callSuper = true)  
10 -@ToString(callSuper = true)  
11 -public class MpUserRespVO extends MpUserBaseVO { 13 +public class MpUserRespVO {
12 14
13 - @ApiModelProperty(value = "编号", required = true) 15 + @ApiModelProperty(value = "编号", required = true, example = "1024")
14 private Long id; 16 private Long id;
15 17
  18 + @ApiModelProperty(value = "公众号用户标识", required = true, example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M")
  19 + private String openid;
  20 +
  21 + @ApiModelProperty(value = "关注状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
  22 + private Integer subscribeStatus;
  23 + @ApiModelProperty(value = "关注时间", required = true)
  24 + private LocalDateTime subscribeTime;
  25 + @ApiModelProperty(value = "取消关注时间")
  26 + private LocalDateTime unsubscribeTime;
  27 +
  28 + @ApiModelProperty(value = "昵称", example = "芋道")
  29 + private String nickname;
  30 + @ApiModelProperty(value = "头像地址", example = "https://www.iocoder.cn/1.png")
  31 + private String headImageUrl;
  32 + @ApiModelProperty(value = "语言", example = "zh_CN")
  33 + private String language;
  34 + @ApiModelProperty(value = "国家", example = "中国")
  35 + private String country;
  36 + @ApiModelProperty(value = "省份", example = "广东省")
  37 + private String province;
  38 + @ApiModelProperty(value = "城市", example = "广州市")
  39 + private String city;
  40 + @ApiModelProperty(value = "备注", example = "你是一个芋头嘛")
  41 + private String remark;
  42 +
  43 + @ApiModelProperty(value = "标签编号数组", example = "1,2,3")
  44 + private List<Long> tagIds;
  45 +
  46 + @ApiModelProperty(value = "公众号账号的编号", required = true, example = "1")
  47 + private Long accountId;
  48 + @ApiModelProperty(value = "公众号账号的 appId", required = true, example = "wx1234567890")
  49 + private String appId;
  50 +
16 @ApiModelProperty(value = "创建时间", required = true) 51 @ApiModelProperty(value = "创建时间", required = true)
17 private Date createTime; 52 private Date createTime;
18 53
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/user/vo/MpUserUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mp.controller.admin.user.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +import java.util.List;
  9 +
  10 +@ApiModel("管理后台 - 公众号粉丝更新 Request VO")
  11 +@Data
  12 +public class MpUserUpdateReqVO {
  13 +
  14 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  15 + @NotNull(message = "编号不能为空")
  16 + private Long id;
  17 +
  18 + @ApiModelProperty(value = "昵称", example = "芋道")
  19 + private String nickname;
  20 +
  21 + @ApiModelProperty(value = "备注", example = "你是一个芋头嘛")
  22 + private String remark;
  23 +
  24 + @ApiModelProperty(value = "标签编号数组", example = "1,2,3")
  25 + private List<Long> tagIds;
  26 +
  27 +}
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/convert/tag/MpTagConvert.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mp.convert.tag; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mp.convert.tag;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagRespVO; 4 import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagRespVO;
  5 +import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagSimpleRespVO;
5 import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO; 6 import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO;
6 import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; 7 import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
7 import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO; 8 import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
@@ -36,4 +37,6 @@ public interface MpTagConvert { @@ -36,4 +37,6 @@ public interface MpTagConvert {
36 }) 37 })
37 MpTagDO convert(WxUserTag tag, MpAccountDO account); 38 MpTagDO convert(WxUserTag tag, MpAccountDO account);
38 39
  40 + List<MpTagSimpleRespVO> convertList02(List<MpTagDO> list);
  41 +
39 } 42 }
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/convert/user/MpUserConvert.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
7 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserRespVO; 7 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserRespVO;
  8 +import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserUpdateReqVO;
8 import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; 9 import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
9 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO; 10 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
10 import me.chanjar.weixin.mp.bean.result.WxMpUser; 11 import me.chanjar.weixin.mp.bean.result.WxMpUser;
@@ -49,4 +50,6 @@ public interface MpUserConvert { @@ -49,4 +50,6 @@ public interface MpUserConvert {
49 return CollectionUtils.convertList(wxUsers, wxUser -> convert(account, wxUser)); 50 return CollectionUtils.convertList(wxUsers, wxUser -> convert(account, wxUser));
50 } 51 }
51 52
  53 + MpUserDO convert(MpUserUpdateReqVO bean);
  54 +
52 } 55 }
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/tag/MpTagService.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO; @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.mp.controller.admin.tag.vo.MpTagUpdateReqVO;
7 import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO; 7 import cn.iocoder.yudao.module.mp.dal.dataobject.tag.MpTagDO;
8 8
9 import javax.validation.Valid; 9 import javax.validation.Valid;
  10 +import java.util.List;
10 11
11 /** 12 /**
12 * 公众号标签 Service 接口 13 * 公众号标签 Service 接口
@@ -45,6 +46,8 @@ public interface MpTagService { @@ -45,6 +46,8 @@ public interface MpTagService {
45 */ 46 */
46 PageResult<MpTagDO> getTagPage(MpTagPageReqVO pageReqVO); 47 PageResult<MpTagDO> getTagPage(MpTagPageReqVO pageReqVO);
47 48
  49 + List<MpTagDO> getTagList();
  50 +
48 /** 51 /**
49 * 同步公众号标签 52 * 同步公众号标签
50 * 53 *
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/tag/MpTagServiceImpl.java
@@ -117,6 +117,11 @@ public class MpTagServiceImpl implements MpTagService { @@ -117,6 +117,11 @@ public class MpTagServiceImpl implements MpTagService {
117 } 117 }
118 118
119 @Override 119 @Override
  120 + public List<MpTagDO> getTagList() {
  121 + return mpTagMapper.selectList();
  122 + }
  123 +
  124 + @Override
120 @Transactional(rollbackFor = Exception.class) 125 @Transactional(rollbackFor = Exception.class)
121 public void syncTag(Long accountId) { 126 public void syncTag(Long accountId) {
122 MpAccountDO account = mpAccountService.getRequiredAccount(accountId); 127 MpAccountDO account = mpAccountService.getRequiredAccount(accountId);
@@ -127,7 +132,7 @@ public class MpTagServiceImpl implements MpTagService { @@ -127,7 +132,7 @@ public class MpTagServiceImpl implements MpTagService {
127 try { 132 try {
128 wxTags = mpService.getUserTagService().tagGet(); 133 wxTags = mpService.getUserTagService().tagGet();
129 } catch (WxErrorException e) { 134 } catch (WxErrorException e) {
130 - throw new RuntimeException(e); 135 + throw exception(TAG_GET_FAIL, e.getError().getErrorMsg());
131 } 136 }
132 137
133 // 第二步,合并更新回自己的数据库;由于标签只有 100 个,所以直接 for 循环操作 138 // 第二步,合并更新回自己的数据库;由于标签只有 100 个,所以直接 for 循环操作
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/user/MpUserService.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mp.service.user; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mp.service.user;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO; 4 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO;
  5 +import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserUpdateReqVO;
5 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO; 6 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
6 import me.chanjar.weixin.mp.bean.result.WxMpUser; 7 import me.chanjar.weixin.mp.bean.result.WxMpUser;
7 8
@@ -74,4 +75,11 @@ public interface MpUserService { @@ -74,4 +75,11 @@ public interface MpUserService {
74 */ 75 */
75 void updateUserUnsubscribe(String appId, String openId); 76 void updateUserUnsubscribe(String appId, String openId);
76 77
  78 + /**
  79 + * 更新公众号粉丝
  80 + *
  81 + * @param updateReqVO 更新信息
  82 + */
  83 + void updateUser(MpUserUpdateReqVO updateReqVO);
  84 +
77 } 85 }
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/user/MpUserServiceImpl.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
8 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO; 8 import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserPageReqVO;
  9 +import cn.iocoder.yudao.module.mp.controller.admin.user.vo.MpUserUpdateReqVO;
9 import cn.iocoder.yudao.module.mp.convert.user.MpUserConvert; 10 import cn.iocoder.yudao.module.mp.convert.user.MpUserConvert;
10 import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO; 11 import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
11 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO; 12 import cn.iocoder.yudao.module.mp.dal.dataobject.user.MpUserDO;
@@ -29,6 +30,10 @@ import java.util.Collection; @@ -29,6 +30,10 @@ import java.util.Collection;
29 import java.util.List; 30 import java.util.List;
30 import java.util.Map; 31 import java.util.Map;
31 32
  33 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  34 +import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.USER_NOT_EXISTS;
  35 +import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.USER_UPDATE_TAG_FAIL;
  36 +
32 /** 37 /**
33 * 微信公众号粉丝 Service 实现类 38 * 微信公众号粉丝 Service 实现类
34 * 39 *
@@ -156,14 +161,55 @@ public class MpUserServiceImpl implements MpUserService { @@ -156,14 +161,55 @@ public class MpUserServiceImpl implements MpUserService {
156 } 161 }
157 162
158 @Override 163 @Override
159 - public void updateUserUnsubscribe(String appId, String openId) {  
160 - MpUserDO dbUser = mpUserMapper.selectByAppIdAndOpenid(appId, openId); 164 + public void updateUserUnsubscribe(String appId, String openid) {
  165 + MpUserDO dbUser = mpUserMapper.selectByAppIdAndOpenid(appId, openid);
161 if (dbUser == null) { 166 if (dbUser == null) {
162 - log.error("[updateUserUnsubscribe][微信公众号粉丝 appId({}) openId({}) 不存在]", appId, openId); 167 + log.error("[updateUserUnsubscribe][微信公众号粉丝 appId({}) openid({}) 不存在]", appId, openid);
163 return; 168 return;
164 } 169 }
165 mpUserMapper.updateById(new MpUserDO().setId(dbUser.getId()).setSubscribeStatus(CommonStatusEnum.DISABLE.getStatus()) 170 mpUserMapper.updateById(new MpUserDO().setId(dbUser.getId()).setSubscribeStatus(CommonStatusEnum.DISABLE.getStatus())
166 - .setSubscribeTime(LocalDateTime.now())); 171 + .setUnsubscribeTime(LocalDateTime.now()));
  172 + }
  173 +
  174 + @Override
  175 + public void updateUser(MpUserUpdateReqVO updateReqVO) {
  176 + // 校验存在
  177 + MpUserDO user = validateUserExists(updateReqVO.getId());
  178 +
  179 + // 第一步,更新标签到公众号
  180 + updateUserTag(user.getAppId(), user.getOpenid(), updateReqVO.getTagIds());
  181 +
  182 + // 第二步,更新基本信息到数据库
  183 + MpUserDO updateObj = MpUserConvert.INSTANCE.convert(updateReqVO).setId(user.getId());
  184 + mpUserMapper.updateById(updateObj);
  185 + }
  186 +
  187 + private MpUserDO validateUserExists(Long id) {
  188 + MpUserDO user = mpUserMapper.selectById(id);
  189 + if (user == null) {
  190 + throw exception(USER_NOT_EXISTS);
  191 + }
  192 + return user;
  193 + }
  194 +
  195 + private void updateUserTag(String appId, String openid, List<Long> tagIds) {
  196 + WxMpService mpService = mpServiceFactory.getRequiredMpService(appId);
  197 + try {
  198 + // 第一步,先取消原来的标签
  199 + List<Long> oldTagIds = mpService.getUserTagService().userTagList(openid);
  200 + for (Long tagId : oldTagIds) {
  201 + mpService.getUserTagService().batchUntagging(tagId, new String[]{openid});
  202 + }
  203 + // 第二步,再设置新的标签
  204 + if (CollUtil.isEmpty(tagIds)) {
  205 + return;
  206 + }
  207 + for (Long tagId: tagIds) {
  208 + mpService.getUserTagService().batchTagging(tagId, new String[]{openid});
  209 + }
  210 + } catch (WxErrorException e) {
  211 + throw exception(USER_UPDATE_TAG_FAIL, e.getError().getErrorMsg());
  212 + }
167 } 213 }
168 214
169 } 215 }
yudao-ui-admin/src/api/mp/tag.js
@@ -43,6 +43,14 @@ export function getTagPage(query) { @@ -43,6 +43,14 @@ export function getTagPage(query) {
43 }) 43 })
44 } 44 }
45 45
  46 +// 获取公众号标签精简信息列表
  47 +export function getSimpleTags() {
  48 + return request({
  49 + url: '/mp/tag/list-all-simple',
  50 + method: 'get',
  51 + })
  52 +}
  53 +
46 // 同步公众号标签 54 // 同步公众号标签
47 export function syncTag(accountId) { 55 export function syncTag(accountId) {
48 return request({ 56 return request({
yudao-ui-admin/src/api/mp/user.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 更新公众号粉丝
  4 +export function updateUser(data) {
  5 + return request({
  6 + url: '/mp/user/update',
  7 + method: 'put',
  8 + data: data
  9 + })
  10 +}
  11 +
  12 +// 获得公众号粉丝
  13 +export function getUser(id) {
  14 + return request({
  15 + url: '/mp/user/get?id=' + id,
  16 + method: 'get'
  17 + })
  18 +}
  19 +
  20 +// 获得公众号粉丝分页
  21 +export function getUserPage(query) {
  22 + return request({
  23 + url: '/mp/user/page',
  24 + method: 'get',
  25 + params: query
  26 + })
  27 +}
  28 +
  29 +// 同步公众号粉丝
  30 +export function syncUser(accountId) {
  31 + return request({
  32 + url: '/mp/tag/sync?accountId=' + accountId,
  33 + method: 'post'
  34 + })
  35 +}
yudao-ui-admin/src/api/wechatMp/wxAccountFans.js deleted
1 -import request from '@/utils/request'  
2 -  
3 -// 创建微信公众号粉丝  
4 -export function createWxAccountFans(data) {  
5 - return request({  
6 - url: '/wechatMp/wx-account-fans/create',  
7 - method: 'post',  
8 - data: data  
9 - })  
10 -}  
11 -  
12 -// 更新微信公众号粉丝  
13 -export function updateWxAccountFans(data) {  
14 - return request({  
15 - url: '/wechatMp/wx-account-fans/update',  
16 - method: 'put',  
17 - data: data  
18 - })  
19 -}  
20 -  
21 -// 删除微信公众号粉丝  
22 -export function deleteWxAccountFans(id) {  
23 - return request({  
24 - url: '/wechatMp/wx-account-fans/delete?id=' + id,  
25 - method: 'delete'  
26 - })  
27 -}  
28 -  
29 -// 获得微信公众号粉丝  
30 -export function getWxAccountFans(id) {  
31 - return request({  
32 - url: '/wechatMp/wx-account-fans/get?id=' + id,  
33 - method: 'get'  
34 - })  
35 -}  
36 -  
37 -// 获得微信公众号粉丝分页  
38 -export function getWxAccountFansPage(query) {  
39 - return request({  
40 - url: '/wechatMp/wx-account-fans/page',  
41 - method: 'get',  
42 - params: query  
43 - })  
44 -}  
45 -  
46 -// 导出微信公众号粉丝 Excel  
47 -export function exportWxAccountFansExcel(query) {  
48 - return request({  
49 - url: '/wechatMp/wx-account-fans/export-excel',  
50 - method: 'get',  
51 - params: query,  
52 - responseType: 'blob'  
53 - })  
54 -}  
yudao-ui-admin/src/views/mp/user/index.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="公众号" prop="accountId">
  7 + <el-select v-model="queryParams.accountId" placeholder="请选择公众号">
  8 + <el-option v-for="item in accounts" :key="parseInt(item.id)" :label="item.name" :value="parseInt(item.id)" />
  9 + </el-select>
  10 + </el-form-item>
  11 + <el-form-item label="用户标识" prop="openid">
  12 + <el-input v-model="queryParams.openid" placeholder="请输入用户标识" clearable @keyup.enter.native="handleQuery"/>
  13 + </el-form-item>
  14 + <el-form-item label="昵称" prop="nickname">
  15 + <el-input v-model="queryParams.nickname" placeholder="请输入昵称" clearable @keyup.enter.native="handleQuery"/>
  16 + </el-form-item>
  17 + <el-form-item>
  18 + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
  19 + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
  20 + </el-form-item>
  21 + </el-form>
  22 +
  23 + <!-- 操作工具栏 -->
  24 + <el-row :gutter="10" class="mb8">
  25 + <el-col :span="1.5">
  26 + <el-button type="info" plain icon="el-icon-refresh" size="mini" @click="handleSync"
  27 + v-hasPermi="['mp:user:sync']">同步
  28 + </el-button>
  29 + </el-col>
  30 + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  31 + </el-row>
  32 +
  33 + <!-- 列表 -->
  34 + <el-table v-loading="loading" :data="list">
  35 + <el-table-column label="编号" align="center" prop="id" />
  36 + <el-table-column label="用户标识" align="center" prop="openid" width="260" />
  37 + <el-table-column label="昵称" align="center" prop="nickname" />
  38 + <el-table-column label="备注" align="center" prop="remark" />
  39 + <el-table-column label="标签" align="center" prop="tagIds" width="200">
  40 + <template slot-scope="scope">
  41 + <span v-for="(tagId, index) in scope.row.tagIds" :key="index">
  42 + <el-tag>{{ tags.find(tag => tag.tagId === tagId)?.name }} </el-tag>&nbsp;
  43 + </span>
  44 + </template>
  45 + </el-table-column>
  46 + <el-table-column label="订阅状态" align="center" prop="subscribeStatus">
  47 + <template slot-scope="scope">
  48 + <el-tag v-if="scope.row.subscribeStatus === 0" type="success">已订阅</el-tag>
  49 + <el-tag v-else type="danger">未订阅</el-tag>
  50 + </template>
  51 + </el-table-column>
  52 + <el-table-column label="订阅时间" align="center" prop="subscribeTime" width="180">
  53 + <template slot-scope="scope">
  54 + <span>{{ parseTime(scope.row.subscribeTime) }}</span>
  55 + </template>
  56 + </el-table-column>
  57 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  58 + <template slot-scope="scope">
  59 + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
  60 + v-hasPermi="['mp:user:update']">修改</el-button>
  61 + </template>
  62 + </el-table-column>
  63 + </el-table>
  64 + <!-- 分页组件 -->
  65 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  66 + @pagination="getList"/>
  67 +
  68 + <!-- 对话框(添加 / 修改) -->
  69 + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
  70 + <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  71 + <el-form-item label="昵称" prop="nickname">
  72 + <el-input v-model="form.nickname" placeholder="请输入昵称" />
  73 + </el-form-item>
  74 + <el-form-item label="备注" prop="remark">
  75 + <el-input v-model="form.remark" placeholder="请输入备注" />
  76 + </el-form-item>
  77 + <el-form-item label="标签" prop="tagIds">
  78 + <el-select v-model="form.tagIds" multiple clearable placeholder="请选择标签">
  79 + <el-option v-for="item in tags" :key="parseInt(item.tagId)" :label="item.name" :value="parseInt(item.tagId)" />
  80 + </el-select>
  81 + </el-form-item>
  82 + </el-form>
  83 + <div slot="footer" class="dialog-footer">
  84 + <el-button type="primary" @click="submitForm">确 定</el-button>
  85 + <el-button @click="cancel">取 消</el-button>
  86 + </div>
  87 + </el-dialog>
  88 + </div>
  89 +</template>
  90 +
  91 +<script>
  92 +import { updateUser, getUser, getUserPage, syncUser } from "@/api/mp/user";
  93 +import { getSimpleAccounts } from "@/api/mp/account";
  94 +import { getSimpleTags } from "@/api/mp/tag";
  95 +
  96 +export default {
  97 + name: "WxAccountFans",
  98 + components: {
  99 + },
  100 + data() {
  101 + return {
  102 + // 遮罩层
  103 + loading: true,
  104 + // 显示搜索条件
  105 + showSearch: true,
  106 + // 总条数
  107 + total: 0,
  108 + // 微信公众号粉丝列表
  109 + list: [],
  110 + // 弹出层标题
  111 + title: "",
  112 + // 是否显示弹出层
  113 + open: false,
  114 + // 查询参数
  115 + queryParams: {
  116 + pageNo: 1,
  117 + pageSize: 10,
  118 + accountId: null,
  119 + openid: null,
  120 + nickname: null,
  121 + },
  122 + // 表单参数
  123 + form: {},
  124 + // 表单校验
  125 + rules: {},
  126 +
  127 + // 公众号账号列表
  128 + accounts: [],
  129 + // 公众号标签列表
  130 + tags: [],
  131 + };
  132 + },
  133 + created() {
  134 + getSimpleAccounts().then(response => {
  135 + this.accounts = response.data;
  136 + // 默认选中第一个
  137 + if (this.accounts.length > 0) {
  138 + this.queryParams.accountId = this.accounts[0].id;
  139 + }
  140 + // 加载数据
  141 + this.getList();
  142 + })
  143 +
  144 + // 加载标签
  145 + getSimpleTags().then(response => {
  146 + this.tags = response.data;
  147 + })
  148 + },
  149 + methods: {
  150 + /** 查询列表 */
  151 + getList() {
  152 + // 如果没有选中公众号账号,则进行提示。
  153 + if (!this.queryParams.accountId) {
  154 + this.$message.error('未选中公众号,无法查询用户')
  155 + return false
  156 + }
  157 +
  158 + this.loading = true;
  159 + // 处理查询参数
  160 + let params = {...this.queryParams};
  161 + // 执行查询
  162 + getUserPage(params).then(response => {
  163 + this.list = response.data.list;
  164 + this.total = response.data.total;
  165 + this.loading = false;
  166 + });
  167 + },
  168 + /** 取消按钮 */
  169 + cancel() {
  170 + this.open = false;
  171 + this.reset();
  172 + },
  173 + /** 表单重置 */
  174 + reset() {
  175 + this.form = {
  176 + id: undefined,
  177 + nickname: undefined,
  178 + remark: undefined,
  179 + tagIds: [],
  180 + };
  181 + this.resetForm("form");
  182 + },
  183 + /** 搜索按钮操作 */
  184 + handleQuery() {
  185 + this.queryParams.pageNo = 1;
  186 + this.getList();
  187 + },
  188 + /** 重置按钮操作 */
  189 + resetQuery() {
  190 + this.resetForm("queryForm");
  191 + // 默认选中第一个
  192 + if (this.accounts.length > 0) {
  193 + this.queryParams.accountId = this.accounts[0].id;
  194 + }
  195 + this.handleQuery();
  196 + },
  197 + /** 修改按钮操作 */
  198 + handleUpdate(row) {
  199 + this.reset();
  200 + const id = row.id;
  201 + getUser(id).then(response => {
  202 + this.form = response.data;
  203 + this.open = true;
  204 + this.title = "修改公众号粉丝";
  205 + });
  206 + },
  207 + /** 提交按钮 */
  208 + submitForm() {
  209 + this.$refs["form"].validate(valid => {
  210 + if (!valid) {
  211 + return;
  212 + }
  213 + // 修改的提交
  214 + if (this.form.id != null) {
  215 + updateUser(this.form).then(response => {
  216 + this.$modal.msgSuccess("修改成功");
  217 + this.open = false;
  218 + this.getList();
  219 + });
  220 + }
  221 + });
  222 + },
  223 + /** 同步标签 */
  224 + handleSync() {
  225 + const accountId = this.queryParams.accountId
  226 + this.$modal.confirm('是否确认同步粉丝?').then(function () {
  227 + return syncUser(accountId)
  228 + }).then(() => {
  229 + this.$modal.msgSuccess('开始从微信公众号同步粉丝信息,同步需要一段时间,建议稍后再查询')
  230 + }).catch(() => {
  231 + })
  232 + },
  233 + }
  234 +};
  235 +</script>
yudao-ui-admin/src/views/wechatMp/wxAccountFans/index.vue deleted
1 -<template>  
2 - <div class="app-container">  
3 -  
4 - <!-- 搜索工作栏 -->  
5 - <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">  
6 - <el-form-item label="用户标识" prop="openid">  
7 - <el-input v-model="queryParams.openid" placeholder="请输入用户标识" clearable @keyup.enter.native="handleQuery"/>  
8 - </el-form-item>  
9 - <el-form-item label="订阅状态,0未关注,1已关注" prop="subscribeStatus">  
10 - <el-select v-model="queryParams.subscribeStatus" placeholder="请选择订阅状态,0未关注,1已关注" clearable size="small">  
11 - <el-option label="请选择字典生成" value="" />  
12 - </el-select>  
13 - </el-form-item>  
14 - <el-form-item label="订阅时间">  
15 - <el-date-picker v-model="dateRangeSubscribeTime" style="width: 240px" value-format="yyyy-MM-dd"  
16 - type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />  
17 - </el-form-item>  
18 - <el-form-item label="昵称" prop="nickname">  
19 - <el-input v-model="queryParams.nickname" placeholder="请输入昵称" clearable @keyup.enter.native="handleQuery"/>  
20 - </el-form-item>  
21 - <el-form-item label="性别,1男,2女,0未知" prop="gender">  
22 - <el-input v-model="queryParams.gender" placeholder="请输入性别,1男,2女,0未知" clearable @keyup.enter.native="handleQuery"/>  
23 - </el-form-item>  
24 - <el-form-item label="语言" prop="language">  
25 - <el-input v-model="queryParams.language" placeholder="请输入语言" clearable @keyup.enter.native="handleQuery"/>  
26 - </el-form-item>  
27 - <el-form-item label="国家" prop="country">  
28 - <el-input v-model="queryParams.country" placeholder="请输入国家" clearable @keyup.enter.native="handleQuery"/>  
29 - </el-form-item>  
30 - <el-form-item label="省份" prop="province">  
31 - <el-input v-model="queryParams.province" placeholder="请输入省份" clearable @keyup.enter.native="handleQuery"/>  
32 - </el-form-item>  
33 - <el-form-item label="城市" prop="city">  
34 - <el-input v-model="queryParams.city" placeholder="请输入城市" clearable @keyup.enter.native="handleQuery"/>  
35 - </el-form-item>  
36 - <el-form-item label="头像地址" prop="headimgUrl">  
37 - <el-input v-model="queryParams.headimgUrl" placeholder="请输入头像地址" clearable @keyup.enter.native="handleQuery"/>  
38 - </el-form-item>  
39 - <el-form-item label="备注" prop="remark">  
40 - <el-input v-model="queryParams.remark" placeholder="请输入备注" clearable @keyup.enter.native="handleQuery"/>  
41 - </el-form-item>  
42 - <el-form-item label="微信公众号ID" prop="wxAccountId">  
43 - <el-input v-model="queryParams.wxAccountId" placeholder="请输入微信公众号ID" clearable @keyup.enter.native="handleQuery"/>  
44 - </el-form-item>  
45 - <el-form-item label="微信公众号appid" prop="wxAccountAppid">  
46 - <el-input v-model="queryParams.wxAccountAppid" placeholder="请输入微信公众号appid" clearable @keyup.enter.native="handleQuery"/>  
47 - </el-form-item>  
48 - <el-form-item label="创建时间">  
49 - <el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd"  
50 - type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />  
51 - </el-form-item>  
52 - <el-form-item>  
53 - <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>  
54 - <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>  
55 - </el-form-item>  
56 - </el-form>  
57 -  
58 - <!-- 操作工具栏 -->  
59 - <el-row :gutter="10" class="mb8">  
60 - <el-col :span="1.5">  
61 - <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"  
62 - v-hasPermi="['wechatMp:wx-account-fans:create']">新增</el-button>  
63 - </el-col>  
64 - <el-col :span="1.5">  
65 - <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading"  
66 - v-hasPermi="['wechatMp:wx-account-fans:export']">导出</el-button>  
67 - </el-col>  
68 - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>  
69 - </el-row>  
70 -  
71 - <!-- 列表 -->  
72 - <el-table v-loading="loading" :data="list">  
73 - <el-table-column label="编号" align="center" prop="id" />  
74 - <el-table-column label="用户标识" align="center" prop="openid" />  
75 - <el-table-column label="订阅状态,0未关注,1已关注" align="center" prop="subscribeStatus" />  
76 - <el-table-column label="订阅时间" align="center" prop="subscribeTime" width="180">  
77 - <template slot-scope="scope">  
78 - <span>{{ parseTime(scope.row.subscribeTime) }}</span>  
79 - </template>  
80 - </el-table-column>  
81 - <el-table-column label="昵称" align="center" prop="nickname" />  
82 - <el-table-column label="性别,1男,2女,0未知" align="center" prop="gender" />  
83 - <el-table-column label="语言" align="center" prop="language" />  
84 - <el-table-column label="国家" align="center" prop="country" />  
85 - <el-table-column label="省份" align="center" prop="province" />  
86 - <el-table-column label="城市" align="center" prop="city" />  
87 - <el-table-column label="头像地址" align="center" prop="headimgUrl" />  
88 - <el-table-column label="备注" align="center" prop="remark" />  
89 - <el-table-column label="微信公众号ID" align="center" prop="wxAccountId" />  
90 - <el-table-column label="微信公众号appid" align="center" prop="wxAccountAppid" />  
91 - <el-table-column label="创建时间" align="center" prop="createTime" width="180">  
92 - <template slot-scope="scope">  
93 - <span>{{ parseTime(scope.row.createTime) }}</span>  
94 - </template>  
95 - </el-table-column>  
96 - <el-table-column label="操作" align="center" class-name="small-padding fixed-width">  
97 - <template slot-scope="scope">  
98 - <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"  
99 - v-hasPermi="['wechatMp:wx-account-fans:update']">修改</el-button>  
100 - <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"  
101 - v-hasPermi="['wechatMp:wx-account-fans:delete']">删除</el-button>  
102 - </template>  
103 - </el-table-column>  
104 - </el-table>  
105 - <!-- 分页组件 -->  
106 - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"  
107 - @pagination="getList"/>  
108 -  
109 - <!-- 对话框(添加 / 修改) -->  
110 - <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>  
111 - <el-form ref="form" :model="form" :rules="rules" label-width="80px">  
112 - <el-form-item label="用户标识" prop="openid">  
113 - <el-input v-model="form.openid" placeholder="请输入用户标识" />  
114 - </el-form-item>  
115 - <el-form-item label="订阅状态,0未关注,1已关注" prop="subscribeStatus">  
116 - <el-radio-group v-model="form.subscribeStatus">  
117 - <el-radio label="1">请选择字典生成</el-radio>  
118 - </el-radio-group>  
119 - </el-form-item>  
120 - <el-form-item label="订阅时间" prop="subscribeTime">  
121 - <el-date-picker clearable v-model="form.subscribeTime" type="date" value-format="timestamp" placeholder="选择订阅时间" />  
122 - </el-form-item>  
123 - <el-form-item label="昵称" prop="nickname">  
124 - <el-input v-model="form.nickname" placeholder="请输入昵称" />  
125 - </el-form-item>  
126 - <el-form-item label="性别,1男,2女,0未知" prop="gender">  
127 - <el-input v-model="form.gender" placeholder="请输入性别,1男,2女,0未知" />  
128 - </el-form-item>  
129 - <el-form-item label="语言" prop="language">  
130 - <el-input v-model="form.language" placeholder="请输入语言" />  
131 - </el-form-item>  
132 - <el-form-item label="国家" prop="country">  
133 - <el-input v-model="form.country" placeholder="请输入国家" />  
134 - </el-form-item>  
135 - <el-form-item label="省份" prop="province">  
136 - <el-input v-model="form.province" placeholder="请输入省份" />  
137 - </el-form-item>  
138 - <el-form-item label="城市" prop="city">  
139 - <el-input v-model="form.city" placeholder="请输入城市" />  
140 - </el-form-item>  
141 - <el-form-item label="头像地址" prop="headimgUrl">  
142 - <el-input v-model="form.headimgUrl" placeholder="请输入头像地址" />  
143 - </el-form-item>  
144 - <el-form-item label="备注" prop="remark">  
145 - <el-input v-model="form.remark" placeholder="请输入备注" />  
146 - </el-form-item>  
147 - <el-form-item label="微信公众号ID" prop="wxAccountId">  
148 - <el-input v-model="form.wxAccountId" placeholder="请输入微信公众号ID" />  
149 - </el-form-item>  
150 - <el-form-item label="微信公众号appid" prop="wxAccountAppid">  
151 - <el-input v-model="form.wxAccountAppid" placeholder="请输入微信公众号appid" />  
152 - </el-form-item>  
153 - </el-form>  
154 - <div slot="footer" class="dialog-footer">  
155 - <el-button type="primary" @click="submitForm">确 定</el-button>  
156 - <el-button @click="cancel">取 消</el-button>  
157 - </div>  
158 - </el-dialog>  
159 - </div>  
160 -</template>  
161 -  
162 -<script>  
163 -import { createWxAccountFans, updateWxAccountFans, deleteWxAccountFans, getWxAccountFans, getWxAccountFansPage, exportWxAccountFansExcel } from "@/api/wechatMp/wxAccountFans";  
164 -  
165 -export default {  
166 - name: "WxAccountFans",  
167 - components: {  
168 - },  
169 - data() {  
170 - return {  
171 - // 遮罩层  
172 - loading: true,  
173 - // 导出遮罩层  
174 - exportLoading: false,  
175 - // 显示搜索条件  
176 - showSearch: true,  
177 - // 总条数  
178 - total: 0,  
179 - // 微信公众号粉丝列表  
180 - list: [],  
181 - // 弹出层标题  
182 - title: "",  
183 - // 是否显示弹出层  
184 - open: false,  
185 - dateRangeSubscribeTime: [],  
186 - dateRangeCreateTime: [],  
187 - // 查询参数  
188 - queryParams: {  
189 - pageNo: 1,  
190 - pageSize: 10,  
191 - openid: null,  
192 - subscribeStatus: null,  
193 - nickname: null,  
194 - gender: null,  
195 - language: null,  
196 - country: null,  
197 - province: null,  
198 - city: null,  
199 - headimgUrl: null,  
200 - remark: null,  
201 - wxAccountId: null,  
202 - wxAccountAppid: null,  
203 - },  
204 - // 表单参数  
205 - form: {},  
206 - // 表单校验  
207 - rules: {  
208 - }  
209 - };  
210 - },  
211 - created() {  
212 - this.getList();  
213 - },  
214 - methods: {  
215 - /** 查询列表 */  
216 - getList() {  
217 - this.loading = true;  
218 - // 处理查询参数  
219 - let params = {...this.queryParams};  
220 - this.addBeginAndEndTime(params, this.dateRangeSubscribeTime, 'subscribeTime');  
221 - this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');  
222 - // 执行查询  
223 - getWxAccountFansPage(params).then(response => {  
224 - this.list = response.data.list;  
225 - this.total = response.data.total;  
226 - this.loading = false;  
227 - });  
228 - },  
229 - /** 取消按钮 */  
230 - cancel() {  
231 - this.open = false;  
232 - this.reset();  
233 - },  
234 - /** 表单重置 */  
235 - reset() {  
236 - this.form = {  
237 - id: undefined,  
238 - openid: undefined,  
239 - subscribeStatus: undefined,  
240 - subscribeTime: undefined,  
241 - nickname: undefined,  
242 - gender: undefined,  
243 - language: undefined,  
244 - country: undefined,  
245 - province: undefined,  
246 - city: undefined,  
247 - headimgUrl: undefined,  
248 - remark: undefined,  
249 - wxAccountId: undefined,  
250 - wxAccountAppid: undefined,  
251 - };  
252 - this.resetForm("form");  
253 - },  
254 - /** 搜索按钮操作 */  
255 - handleQuery() {  
256 - this.queryParams.pageNo = 1;  
257 - this.getList();  
258 - },  
259 - /** 重置按钮操作 */  
260 - resetQuery() {  
261 - this.dateRangeSubscribeTime = [];  
262 - this.dateRangeCreateTime = [];  
263 - this.resetForm("queryForm");  
264 - this.handleQuery();  
265 - },  
266 - /** 新增按钮操作 */  
267 - handleAdd() {  
268 - this.reset();  
269 - this.open = true;  
270 - this.title = "添加微信公众号粉丝";  
271 - },  
272 - /** 修改按钮操作 */  
273 - handleUpdate(row) {  
274 - this.reset();  
275 - const id = row.id;  
276 - getWxAccountFans(id).then(response => {  
277 - this.form = response.data;  
278 - this.open = true;  
279 - this.title = "修改微信公众号粉丝";  
280 - });  
281 - },  
282 - /** 提交按钮 */  
283 - submitForm() {  
284 - this.$refs["form"].validate(valid => {  
285 - if (!valid) {  
286 - return;  
287 - }  
288 - // 修改的提交  
289 - if (this.form.id != null) {  
290 - updateWxAccountFans(this.form).then(response => {  
291 - this.$modal.msgSuccess("修改成功");  
292 - this.open = false;  
293 - this.getList();  
294 - });  
295 - return;  
296 - }  
297 - // 添加的提交  
298 - createWxAccountFans(this.form).then(response => {  
299 - this.$modal.msgSuccess("新增成功");  
300 - this.open = false;  
301 - this.getList();  
302 - });  
303 - });  
304 - },  
305 - /** 删除按钮操作 */  
306 - handleDelete(row) {  
307 - const id = row.id;  
308 - this.$modal.confirm('是否确认删除微信公众号粉丝编号为"' + id + '"的数据项?').then(function() {  
309 - return deleteWxAccountFans(id);  
310 - }).then(() => {  
311 - this.getList();  
312 - this.$modal.msgSuccess("删除成功");  
313 - }).catch(() => {});  
314 - },  
315 - /** 导出按钮操作 */  
316 - handleExport() {  
317 - // 处理查询参数  
318 - let params = {...this.queryParams};  
319 - params.pageNo = undefined;  
320 - params.pageSize = undefined;  
321 - this.addBeginAndEndTime(params, this.dateRangeSubscribeTime, 'subscribeTime');  
322 - this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');  
323 - // 执行导出  
324 - this.$modal.confirm('是否确认导出所有微信公众号粉丝数据项?').then(() => {  
325 - this.exportLoading = true;  
326 - return exportWxAccountFansExcel(params);  
327 - }).then(response => {  
328 - this.$download.excel(response, '微信公众号粉丝.xls');  
329 - this.exportLoading = false;  
330 - }).catch(() => {});  
331 - }  
332 - }  
333 -};  
334 -</script>