Browse Source

add(backend) [粉丝消息 1.0]

wangxiao 4 năm trước cách đây
mục cha
commit
60d71cd92e

+ 9 - 1
operation-backend/src/main/java/com/idiot/operationbackend/controller/AccountController.java

@@ -6,6 +6,7 @@ import com.idiot.operationbackend.handler.SyncUserTask;
 import com.idiot.operationbackend.service.facade.AccountService;
 import com.idiot.operationbackend.service.facade.AuthUserService;
 import com.idiot.operationbackend.service.facade.WeChatService;
+import com.idiot.operationbackend.support.CustomException;
 import com.idiot.operationbackend.support.JsonResult;
 import com.idiot.operationbackend.util.JwtTokenUtil;
 import io.swagger.annotations.Api;
@@ -17,6 +18,7 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -44,7 +46,10 @@ public class AccountController {
     public ResponseEntity<JsonResult<List<Account>>> list (@RequestHeader String token) {
         String userId = JwtTokenUtil.getUserId(token);
         logger.info("用户:{}查询公众号列表",userId);
-        List<Account> accounts  = accountService.queryAccountByUserId(userId);;
+        List<Account> accounts  = accountService.queryAccountByUserId(userId);
+        if (null == accounts){
+            accounts = new ArrayList<>();
+        }
         List<AuthUser> authUsers =  userService.querySubAuthUser(userId);
         /**
          * fixme 暂定权限是 用户能够查询所属子账号下所有公众号,即无权限
@@ -54,6 +59,9 @@ public class AccountController {
             List<Account> subAccounts = accountService.queryAccountBuSubUserIds(userIds);
             accounts.addAll(subAccounts);
         }
+        if (CollectionUtils.isEmpty(accounts)){
+            throw new CustomException(502,"当前帐号和子账号下没有认证的公众号,请前往公众号管理中心添加认证公众号");
+        }
         return ResponseEntity.ok(JsonResult.success(accounts));
     }
 

+ 20 - 1
operation-backend/src/main/java/com/idiot/operationbackend/controller/AuthController.java

@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Objects;
 
 /**
+ * 认证 用户
  * @author wang xiao
  * @date Created in 15:06 2020/9/10
  */
@@ -100,7 +101,7 @@ public class AuthController  {
         logger.info("用户:{}创建 子账号",parentUserId);
         AuthUser parentUser = userService.getById(parentUserId);
         if (Objects.isNull(parentUser) || !StringUtils.isEmpty(parentUser.getParentUserId())) {
-            throw new CustomException(500,"您的账号无权是子账号无权创建子账号");
+            throw new CustomException(500,"您的账号是子账号无权创建子账号");
         }
         if (Objects.isNull(authUser) || StringUtils.isEmpty(authUser.getUserCode())
                 || StringUtils.isEmpty(authUser.getPassword())) {
@@ -119,6 +120,24 @@ public class AuthController  {
     }
 
 
+    @PutMapping("/subUpdate")
+    @ApiOperation(value = "子账号更新信息")
+    public ResponseEntity<JsonResult<Boolean>> upSubUser(@RequestParam AuthUser authUser,
+                                                         @RequestHeader String  token) {
+        String parentUserId = JwtTokenUtil.getUserId(token);
+        logger.info("用户:{}更新 子账号",parentUserId);
+        AuthUser targetUser = userService.queryAuthUserByParentIdAndId(parentUserId,authUser.getId());
+        if (Objects.isNull(targetUser)) {
+            throw new CustomException(500,"您的账号无权操作其他人的账号,只能管理自己的子账号");
+        }
+        targetUser.setNikeName(authUser.getNikeName());
+        targetUser.setAvatarUrl(authUser.getAvatarUrl());
+        boolean ifSave = userService.updateById(targetUser);
+        return ResponseEntity.ok(JsonResult.success(ifSave));
+    }
+
+
+
 
 
 

+ 120 - 0
operation-backend/src/main/java/com/idiot/operationbackend/controller/FansMsgController.java

@@ -0,0 +1,120 @@
+package com.idiot.operationbackend.controller;
+
+import com.idiot.operationbackend.entity.AccountFans;
+import com.idiot.operationbackend.entity.FansMsg;
+import com.idiot.operationbackend.service.facade.AccountFansService;
+import com.idiot.operationbackend.service.facade.AccountService;
+import com.idiot.operationbackend.service.facade.FansMsgService;
+import com.idiot.operationbackend.support.CustomException;
+import com.idiot.operationbackend.support.JsonResult;
+import com.idiot.operationbackend.util.JwtTokenUtil;
+
+import com.idiot.operationbackend.vo.AccountMsgData;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 粉丝消息
+ * @author wang xiao
+ * @date Created in 11:20 2020/9/18
+ */
+@RestController
+@RequestMapping("/fansMsg")
+@Api(value = "FansMsgController", tags ="粉丝消息")
+public class FansMsgController {
+
+
+    private final Logger logger = LoggerFactory.getLogger(FansMsgController.class);
+
+
+    @Autowired
+    private FansMsgService msgService;
+
+    @Autowired
+    private AccountService accountService;
+
+
+    @Autowired
+    private AccountFansService fansService;
+
+    @GetMapping("/msgRead")
+    @ApiOperation(value = "查询公众号未读粉丝消息数量")
+    public ResponseEntity<JsonResult<List<AccountMsgData>>> getFansMsgReadNum(@RequestHeader String token,
+                                                                              @RequestParam String accountIds){
+        String userId = JwtTokenUtil.getUserId(token);
+        if (StringUtils.isEmpty(accountIds)){
+            throw new CustomException(500,"请选择公众号");
+        }
+        List<String> accountId = new ArrayList<>(Arrays.asList(accountIds.split(",")));
+        logger.info("用户:{}查询公众号:{}未读粉丝信息数目",userId,accountIds);
+        List<AccountMsgData> accountMsgData = msgService.countFansMsgNumber(accountId);
+        if (!CollectionUtils.isEmpty(accountMsgData)) {
+            accountMsgData.forEach(e->{
+                Optional.ofNullable(accountService.getById(e.getAccountId()))
+                        .map(account -> {
+                            e.setAccountName(account.getNickName());
+                            e.setAccountUrl(account.getHeadImg());
+                            return e;
+                        });
+            });
+        }
+        return ResponseEntity.ok(JsonResult.success(accountMsgData));
+    }
+
+
+
+    @GetMapping("/{accountId}")
+    @ApiOperation(value = "查询公众号未读粉丝信息")
+    public ResponseEntity<JsonResult<List<FansMsg>>> getFansMsg (@RequestParam int page,
+                                                                 @PathVariable String accountId,
+                                                                 @RequestHeader String token) {
+        String userId = JwtTokenUtil.getUserId(token);
+        logger.info("用户:{}查询公众号:{}第{}页未读粉丝信息列表,",userId,accountId,page);
+        List<FansMsg> fansMsgs = msgService.queryFansMsg(accountId,page);
+
+        if (!CollectionUtils.isEmpty(fansMsgs)) {
+            List<String> opedIds = fansMsgs.stream().map(FansMsg::getFromUserName).collect(Collectors.toList());
+            List<AccountFans> fansList = fansService.queryAccountFans(opedIds,accountId);
+            // fixme 设置用户信息  日后想办法优化
+            fansMsgs.forEach(e->{
+                fansList.stream()
+                        .filter(fans-> e.getFromUserName().equals(fans.getOpenId()))
+                        .findFirst()
+                        .map(f->{
+                            e.setNikeName(f.getNickName());
+                            e.setHeadImage(f.getHeadImgUrl());
+                            return e;
+                        });
+            });
+        }
+        return ResponseEntity.ok(JsonResult.success(fansMsgs));
+    }
+
+    @GetMapping("/clearMsg")
+    @ApiOperation(value = "标记已读")
+    public ResponseEntity<JsonResult<Boolean>> clearMsg (@RequestHeader String token,
+                                                         @RequestParam String msgId) {
+        String userId = JwtTokenUtil.getUserId(token);
+        logger.info("用户:{}标记消息:{}为已读,",userId,msgId);
+        boolean ifRead = msgService.updateToRead(msgId);
+        return ResponseEntity.ok(JsonResult.success(ifRead));
+    }
+
+
+
+
+
+}

+ 149 - 0
operation-backend/src/main/java/com/idiot/operationbackend/entity/FansMsg.java

@@ -0,0 +1,149 @@
+package com.idiot.operationbackend.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+/**
+ * 粉丝消息(现在仅支持 文本图片)
+ * @author wang xiao
+ * @date Created in 11:24 2020/9/18
+ */
+@TableName("t_fans_msg")
+public class FansMsg {
+
+    @TableId
+    private String id;
+
+    private String accountId;
+
+    private String toUserName;
+
+    private String fromUserName;
+
+    private Long createTime;
+
+    private String msgType;
+
+    private String content;
+
+    private String mediaId;
+
+    private String picUrl;
+
+    private String msgId;
+
+    private Boolean read;
+
+    @TableField(exist = false)
+    private String nikeName;
+
+    @TableField(exist = false)
+    private String headImage;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(String accountId) {
+        this.accountId = accountId;
+    }
+
+    public String getToUserName() {
+        return toUserName;
+    }
+
+    public void setToUserName(String toUserName) {
+        this.toUserName = toUserName;
+    }
+
+    public String getFromUserName() {
+        return fromUserName;
+    }
+
+    public void setFromUserName(String fromUserName) {
+        this.fromUserName = fromUserName;
+    }
+
+    public Long getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Long createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getMsgType() {
+        return msgType;
+    }
+
+    public void setMsgType(String msgType) {
+        this.msgType = msgType;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public String getMediaId() {
+        return mediaId;
+    }
+
+    public void setMediaId(String mediaId) {
+        this.mediaId = mediaId;
+    }
+
+    public String getPicUrl() {
+        return picUrl;
+    }
+
+    public void setPicUrl(String picUrl) {
+        this.picUrl = picUrl;
+    }
+
+    public String getMsgId() {
+        return msgId;
+    }
+
+    public void setMsgId(String msgId) {
+        this.msgId = msgId;
+    }
+
+    public Boolean getRead() {
+        return read;
+    }
+
+    public void setRead(Boolean read) {
+        this.read = read;
+    }
+
+
+    public String getNikeName() {
+        return nikeName;
+    }
+
+    public void setNikeName(String nikeName) {
+        this.nikeName = nikeName;
+    }
+
+    public String getHeadImage() {
+        return headImage;
+    }
+
+    public void setHeadImage(String headImage) {
+        this.headImage = headImage;
+    }
+}

+ 48 - 0
operation-backend/src/main/java/com/idiot/operationbackend/mappers/FansMsgMapper.java

@@ -0,0 +1,48 @@
+package com.idiot.operationbackend.mappers;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.idiot.operationbackend.entity.FansMsg;
+import com.idiot.operationbackend.vo.AccountMsgData;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.Results;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * @author wang xiao
+ * @date Created in 14:10 2020/9/18
+ */
+public interface FansMsgMapper extends BaseMapper<FansMsg> {
+
+
+    /**
+     *  查询 公众号未读消息
+     * @author wangxiao
+     * @date 14:38 2020/9/18
+     * @param accountIds
+     * @return java.util.List<com.idiot.operationbackend.vo.AccountMsgData>
+     */
+    @Select(value = {"<script>",
+            "SELECT " +
+            " t.account_id AS account_id, " +
+            " COUNT( t.account_id ) AS `no_number`  " +
+            "FROM " +
+            " t_fans_msg t  " +
+            "WHERE " +
+            " t.`read` = 0  " +
+            " AND t.account_id IN   " +
+            " <foreach collection=\"accountIds\" index=\"index\" item=\"item\"  open=\"(\"  separator=\",\" close=\")\"> " +
+            "        #{item}   " +
+            " </foreach>"   +
+            "GROUP BY " +
+            " t.account_id;"
+            ,"</script>"})
+
+    @Results(value = {
+         @Result(column = "account_id",property = "accountId"),
+         @Result(column = "no_number",property = "number")
+    })
+    List<AccountMsgData> countAccountNumber(@Param("accountIds") List<String> accountIds);
+}

+ 12 - 0
operation-backend/src/main/java/com/idiot/operationbackend/service/facade/AccountFansService.java

@@ -111,4 +111,16 @@ public interface AccountFansService extends IService<AccountFans> {
      * @return boolean
      */
     boolean removeItemForTagList(List<String> openIds,String accountId,int wxId);
+
+
+
+    /**
+     *  查询粉丝
+     * @author wangxiao
+     * @date 15:26 2020/9/18
+     * @param openIds
+     * @param accountId
+     * @return java.util.List<com.idiot.operationbackend.entity.AccountFans>
+     */
+    List<AccountFans> queryAccountFans(List<String> openIds,String accountId);
 }

+ 46 - 0
operation-backend/src/main/java/com/idiot/operationbackend/service/facade/FansMsgService.java

@@ -0,0 +1,46 @@
+package com.idiot.operationbackend.service.facade;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.idiot.operationbackend.entity.FansMsg;
+import com.idiot.operationbackend.vo.AccountMsgData;
+
+import java.util.List;
+
+/**
+ * @author wang xiao
+ * @date Created in 14:10 2020/9/18
+ */
+public interface FansMsgService extends IService<FansMsg> {
+
+
+
+    /**
+     *  查询公众号未读粉丝数量
+     * @author wangxiao
+     * @date 14:25 2020/9/18
+     * @param accountIds
+     * @return java.util.List<com.idiot.operationbackend.vo.AccountMsgData>
+     */
+    List<AccountMsgData> countFansMsgNumber(List<String> accountIds);
+
+
+    /**
+     *  查询公众号粉丝信息列表
+     * @author wangxiao
+     * @date 15:07 2020/9/18
+     * @param accountId
+     * @param page
+     * @return java.util.List<com.idiot.operationbackend.entity.FansMsg>
+     */
+    List<FansMsg> queryFansMsg (String accountId,int page);
+
+
+    /**
+     *  更新为已读
+     * @author wangxiao
+     * @date 15:41 2020/9/18
+     * @param msgId
+     * @return boolean
+     */
+    boolean updateToRead (String msgId);
+}

+ 9 - 2
operation-backend/src/main/java/com/idiot/operationbackend/service/impl/AccountFansServiceImpl.java

@@ -160,6 +160,13 @@ public class AccountFansServiceImpl extends ServiceImpl<AccountFansMapper, Accou
         return updateBatchById(fans);
     }
 
-
-
+    @Override
+    public List<AccountFans> queryAccountFans(List<String> openIds, String accountId) {
+        if (CollectionUtils.isEmpty(openIds)){
+            return new ArrayList<>();
+        }
+       return list(Wrappers.<AccountFans>lambdaQuery()
+               .eq(AccountFans::getAccountId,accountId)
+               .in(AccountFans::getOpenId,openIds));
+    }
 }

+ 9 - 8
operation-backend/src/main/java/com/idiot/operationbackend/service/impl/AccountStatServiceImpl.java

@@ -99,14 +99,15 @@ public class AccountStatServiceImpl extends ServiceImpl<AccountStatMapper, Accou
         ydData.setInactiveNum(inactiveNum);
         ydData.setSevenNum(sevenInactiveNum);
         ydData.setFifteenNum(fifteenInactiveNum);
-        statData.stream().filter(e->beforeDay.equals(e.getStatDate())).findFirst().map(e->{
-            ydData.setAddRate(Constants.calcRate(ydData.getAddNum(), e.getAddNum()));
-            ydData.setNewRate(Constants.calcRate(ydData.getNewNum(), e.getNewNum()));
-            ydData.setCancelRate(Constants.calcRate(ydData.getCancelNum(), e.getCancelNum()));
-            ydData.setInactiveRate(Constants.calcRate(ydData.getInactiveNum(), e.getInactiveNum()));
-            ydData.setPageReadRate(Constants.calcRate(ydData.getPageReadNum(),e.getPageReadNum()));
-            ydData.setInactiveRate(Constants.calcRate(ydData.getInactiveNum(),e.getInactiveNum()));
-            return e;
+        statData.stream().filter(e->beforeDay.equals(e.getStatDate())).findFirst()
+                .map(e->{
+                    ydData.setAddRate(Constants.calcRate(ydData.getAddNum(), e.getAddNum()));
+                    ydData.setNewRate(Constants.calcRate(ydData.getNewNum(), e.getNewNum()));
+                    ydData.setCancelRate(Constants.calcRate(ydData.getCancelNum(), e.getCancelNum()));
+                    ydData.setInactiveRate(Constants.calcRate(ydData.getInactiveNum(), e.getInactiveNum()));
+                    ydData.setPageReadRate(Constants.calcRate(ydData.getPageReadNum(),e.getPageReadNum()));
+                    ydData.setInactiveRate(Constants.calcRate(ydData.getInactiveNum(),e.getInactiveNum()));
+                    return ydData;
         });
         saveOrUpdate(ydData);
     }

+ 53 - 0
operation-backend/src/main/java/com/idiot/operationbackend/service/impl/FansMsgServiceImpl.java

@@ -0,0 +1,53 @@
+package com.idiot.operationbackend.service.impl;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.idiot.operationbackend.entity.FansMsg;
+import com.idiot.operationbackend.mappers.FansMsgMapper;
+import com.idiot.operationbackend.service.facade.FansMsgService;
+import com.idiot.operationbackend.vo.AccountMsgData;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * @author wang xiao
+ * @date Created in 14:12 2020/9/18
+ */
+@Service
+public class FansMsgServiceImpl extends ServiceImpl<FansMsgMapper, FansMsg>
+        implements FansMsgService {
+
+    private final int pageSize = 20;
+
+    @Override
+    public List<AccountMsgData> countFansMsgNumber(List<String> accountIds) {
+
+        if (CollectionUtils.isEmpty(accountIds)) {
+            return null;
+        }
+        return baseMapper.countAccountNumber(accountIds);
+    }
+
+
+    @Override
+    public List<FansMsg> queryFansMsg(String accountId, int page) {
+        int limitPre = (page-1)*pageSize;
+        LambdaQueryWrapper<FansMsg> wrapper = Wrappers.<FansMsg>lambdaQuery()
+                .eq(FansMsg::getAccountId,accountId)
+                .eq(FansMsg::getRead,0)
+                .orderByDesc(FansMsg::getCreateTime)
+                .last(" LIMIT "+ limitPre +",20");
+        return list(wrapper);
+    }
+
+
+    @Override
+    public boolean updateToRead(String msgId) {
+        return update(Wrappers.<FansMsg>lambdaUpdate().eq(FansMsg::getId,msgId).set(FansMsg::getRead,1));
+    }
+}

+ 59 - 0
operation-backend/src/main/java/com/idiot/operationbackend/vo/AccountMsgData.java

@@ -0,0 +1,59 @@
+package com.idiot.operationbackend.vo;
+
+/**
+ * 粉丝消息公众号总类 (不想在FansMsg里面创建太多属性)
+ * @author wang xiao
+ * @date Created in 14:15 2020/9/18
+ */
+public class AccountMsgData {
+
+    private String accountId;
+
+    private String accountName;
+
+    private String accountUrl;
+
+    private Long number;
+
+    public String getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(String accountId) {
+        this.accountId = accountId;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public void setAccountName(String accountName) {
+        this.accountName = accountName;
+    }
+
+    public String getAccountUrl() {
+        return accountUrl;
+    }
+
+    public void setAccountUrl(String accountUrl) {
+        this.accountUrl = accountUrl;
+    }
+
+    public Long getNumber() {
+        return number;
+    }
+
+    public void setNumber(Long number) {
+        this.number = number;
+    }
+
+    @Override
+    public String toString() {
+        return "FansMsgData{" +
+                "accountId='" + accountId + '\'' +
+                ", accountName='" + accountName + '\'' +
+                ", accountUrl='" + accountUrl + '\'' +
+                ", number=" + number +
+                '}';
+    }
+}

+ 7 - 0
operation-backend/src/test/java/com/idiot/operationbackend/OperationBackendApplicationTests.java

@@ -1,6 +1,7 @@
 package com.idiot.operationbackend;
 
 import com.idiot.operationbackend.entity.AuthUser;
+import com.idiot.operationbackend.mappers.FansMsgMapper;
 import com.idiot.operationbackend.service.facade.AuthUserService;
 import com.idiot.operationbackend.support.wechat.AesException;
 import com.idiot.operationbackend.support.wechat.WXBizMsgCrypt;
@@ -19,6 +20,8 @@ import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.fail;
@@ -29,8 +32,12 @@ class OperationBackendApplicationTests {
     @Autowired
     private AuthUserService userService;
 
+    @Autowired
+    private FansMsgMapper fansMsgMapper;
+
     @Test
     void contextLoads() {
+
     }
 
     String encodingAesKey = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG";