123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- package com.idiot.operationbackend.controller;
- import com.idiot.operationbackend.entity.Account;
- import com.idiot.operationbackend.entity.AccountStat;
- import com.idiot.operationbackend.entity.ArticleStat;
- import com.idiot.operationbackend.entity.FansActionStat;
- import com.idiot.operationbackend.service.facade.*;
- import com.idiot.operationbackend.support.Constants;
- import com.idiot.operationbackend.support.CustomException;
- import com.idiot.operationbackend.support.JsonResult;
- import com.idiot.operationbackend.util.JwtTokenUtil;
- import com.idiot.operationbackend.vo.ArticleStatData;
- import com.idiot.operationbackend.vo.GeneralStatData;
- import com.idiot.operationbackend.vo.NumberStatData;
- import com.idiot.operationbackend.vo.RemainStatData;
- 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.math.BigDecimal;
- import java.time.Instant;
- import java.time.LocalDate;
- import java.time.LocalDateTime;
- import java.util.*;
- import java.util.stream.Collectors;
- import static com.idiot.operationbackend.support.Constants.calcRate;
- /**
- * 运营星 首页
- * @author wang xiao
- * @date Created in 10:55 2020/9/15
- */
- @RestController
- @RequestMapping("/index")
- @Api(value = "IndexController", tags ="首页")
- public class IndexController {
- private final Logger logger = LoggerFactory.getLogger(IndexController.class);
- private final String HOUR = "H";
- private final String WEEK = "W";
- private final String DAY = "D";
- private final String MONTH = "M";
- @Autowired
- private AccountService accountService;
- @Autowired
- private AccountStatService accountStatService;
- @Autowired
- private AccountFansService fansService;
- @Autowired
- private FansActionStatService actionStatService;
- @Autowired
- private ArticleStatService articleStatService;
- @GetMapping("/summary")
- @ApiOperation(value = "查询公众号昨日统计数据概览")
- public ResponseEntity<JsonResult<AccountStat>> getFansStat (@RequestHeader String token) {
- String userId = JwtTokenUtil.getUserId(token);
- logger.info("用户:{}查询首页数据统计概览---start",userId);
- List<Account> accounts = accountService.queryAccountByUserId(userId);
- List<String> accountIds = accounts.stream().map(Account::getId).collect(Collectors.toList());
- // 查询数据 不知道怎么优化
- String yesterdayStr = Constants.DATE_FORMATTER.format(LocalDate.now().plusDays(-1));
- List<AccountStat> ydStatData = accountStatService.queryByDateAndAccIds(accountIds,yesterdayStr);
- String beforeYesterdayStr = Constants.DATE_FORMATTER.format(LocalDate.now().plusDays(-2));
- List<AccountStat> beforeYdStat = accountStatService.queryByDateAndAccIds(accountIds,beforeYesterdayStr);
- logger.info("用户:{}首页概览数据计算中---ing",userId);
- // 所有公众号昨日数据
- long totalNum = ydStatData.stream().mapToLong(AccountStat::getTotalFansNum).sum();
- long addNum = ydStatData.stream().mapToLong(AccountStat::getAddNum).sum();
- long cancelNum = ydStatData.stream().mapToLong(AccountStat::getCancelNum).sum();
- long newNum = ydStatData.stream().mapToLong(AccountStat::getNewNum).sum();
- long inactiveNum = ydStatData.stream().mapToLong(AccountStat::getInactiveNum).sum();
- // 所有公众号前日数据
- long bfCancelNum = beforeYdStat.stream().mapToLong(AccountStat::getCancelNum).sum();
- long bfAddNum = beforeYdStat.stream().mapToLong(AccountStat::getAddNum).sum();
- long bfNewNum = beforeYdStat.stream().mapToLong(AccountStat::getNewNum).sum();
- long bfInactiveNum = beforeYdStat.stream().mapToLong(AccountStat::getInactiveNum).sum();
- long bfTotalNum = beforeYdStat.stream().mapToLong(AccountStat::getTotalFansNum).sum();
- AccountStat result = new AccountStat();
- result.setAddNum(addNum);
- result.setNewNum(newNum);
- result.setCancelNum(cancelNum);
- result.setInactiveNum(inactiveNum);
- result.setTotalFansNum(totalNum);
- result.setAddRate(calcRate(addNum,bfAddNum));
- result.setCancelRate(calcRate(cancelNum,bfCancelNum));
- result.setNewRate(calcRate(newNum,bfNewNum));
- result.setInactiveRate(calcRate(inactiveNum,bfInactiveNum));
- result.setTotalFansRate(calcRate(totalNum,bfTotalNum));
- logger.info("用户:{}查询首页数据统计概览---end",userId);
- return ResponseEntity.ok(JsonResult.success(result));
- }
- @GetMapping("/single/{accountId}")
- @ApiOperation(value = "查询单个公众号昨日统计数据概览")
- public ResponseEntity<JsonResult<AccountStat>> getSingleFansStat (@RequestHeader String token,
- @PathVariable String accountId) {
- String userId = JwtTokenUtil.getUserId(token);
- logger.info("用户:{}查询首页单个公众号:{}数据统计概览---start",userId,accountId);
- String yesterdayStr = Constants.DATE_FORMATTER.format(LocalDate.now().plusDays(-1));
- AccountStat fansStat = accountStatService.queryByDateAndAccountId(accountId,yesterdayStr);
- logger.info("用户:{}查询首页单个公众号:{}数据统计概览---end",userId,accountId);
- return ResponseEntity.ok(JsonResult.success(fansStat));
- }
- @GetMapping("/growth/{accountId}")
- @ApiOperation(value = "查询单个公众号--粉丝增长")
- public ResponseEntity<JsonResult<Map<String,Object>>> getFansGrowthStat (@PathVariable String accountId,
- @RequestHeader String token,
- @RequestParam String type,
- @RequestParam String startDate,
- @RequestParam String endDate) {
- String userId = JwtTokenUtil.getUserId(token);
- if (!checkDate(startDate,endDate)){
- throw new CustomException(500,"请选择开始和结束时间!");
- }
- Map<String,Object> result = new HashMap<>(8);
- logger.info("用户:{}查询首页单个公众号:{}粉丝增长,type:{},startDate:{},endDate:{} --->start",
- userId,accountId,type,startDate,endDate);
- LocalDate start = LocalDate.parse(startDate);
- LocalDate end= LocalDate.parse(endDate);
- long days = end.toEpochDay() - start.toEpochDay();
- List<GeneralStatData> statDataList = statFansGrowthData(accountId, type, start, end);
- long newNum =0;
- long addNum =0;
- long inactiveNum =0;
- long cancelNum =0;
- BigDecimal ave =BigDecimal.ZERO;
- if (CollectionUtils.isEmpty(statDataList)) {
- newNum = statDataList.parallelStream().mapToLong(GeneralStatData::getNewNum).sum();
- addNum = statDataList.parallelStream().mapToLong(GeneralStatData::getAddNum).sum();
- inactiveNum = statDataList.parallelStream().mapToLong(GeneralStatData::getInactiveNum).sum();
- cancelNum = statDataList.parallelStream().mapToLong(GeneralStatData::getCancelNum).sum();
- if (days == 0){
- days = 1;
- }
- ave = new BigDecimal(newNum/days).setScale(0);
- }
- result.put("newNum",newNum);
- result.put("addNum",addNum);
- result.put("inactiveNum",inactiveNum);
- result.put("cancelNum",cancelNum);
- result.put("aveNum",ave);
- result.put("tableData",statDataList);
- logger.info("用户:{}查询首页单个公众号:{}粉丝增长,type:{},startDate:{},endDate:{} --->end",
- userId,accountId,type,startDate,endDate);
- return ResponseEntity.ok(JsonResult.success(result));
- }
- @GetMapping("/property/{accountId}")
- @ApiOperation(value = "查询单个公众号--粉丝属性")
- public ResponseEntity<JsonResult<Map<String,Object>>> getFansPropertyStat(
- @RequestHeader String token,
- @PathVariable String accountId,
- @RequestParam(required = false) String startDate,
- @RequestParam(required = false) String endDate) {
- String userId = JwtTokenUtil.getUserId(token);
- logger.info("用户:{}查询首页单个公众号:{}粉丝属性,startDate:{},endDate:{} --->start",userId,accountId,startDate,endDate);
- Map<String,Object> result = new HashMap<>(4);
- List<NumberStatData> numberStatData = fansService.statByFansProperty(accountId,startDate,endDate);
- statFansProperty(numberStatData,result);
- logger.info("用户:{}查询首页单个公众号:{}粉丝属性,startDate:{},endDate:{} --->end",userId,accountId,startDate,endDate);
- return ResponseEntity.ok(JsonResult.success(result));
- }
- @GetMapping("/inactive/{accountId}")
- @ApiOperation(value = "查询单个公众号--粉丝活跃度")
- public ResponseEntity<JsonResult<List<AccountStat>>> getFansInactiveStat(@RequestHeader String token,
- @PathVariable String accountId,
- @RequestParam String startDate,
- @RequestParam String endDate) {
- String userId = JwtTokenUtil.getUserId(token);
- if (!checkDate(startDate,endDate)){
- throw new CustomException(500,"请选择查询时间范围!");
- }
- logger.info("用户:{}查询首页单个公众号:{}粉丝活跃度,startDate:{},endDate:{} --->start",userId,accountId,startDate,endDate);
- List<AccountStat> accountStats = accountStatService.queryAccountStatByDate(accountId,startDate,endDate);
- logger.info("用户:{}查询首页单个公众号:{}粉丝活跃度,startDate:{},endDate:{} --->end",userId,accountId,startDate,endDate);
- return ResponseEntity.ok(JsonResult.success(accountStats));
- }
- @GetMapping("/remain/{accountId}")
- @ApiOperation(value = "查询单个公众号--粉丝忠诚度")
- public ResponseEntity<JsonResult<List<RemainStatData>>> getFansRemainStat(@RequestHeader String token,
- @PathVariable String accountId,
- @RequestParam String date) {
- String userId = JwtTokenUtil.getUserId(token);
- if (StringUtils.isEmpty(date)){
- throw new CustomException(500,"请选择查询时间!");
- }
- LocalDateTime endDate = Constants.toLocalDateTime(date);
- LocalDateTime startDate = Constants.toLocalDateTime(date).plusDays(-7);
- logger.info("用户:{}查询首页单个公众号:{}粉丝忠诚度,date:{} --->start",userId,accountId,date);
- List<AccountStat> accountStats = accountStatService.queryAccountStatByDate(accountId,startDate,endDate);
- List<RemainStatData> remainStatData = statFansRemainData(accountStats);
- if (Objects.isNull(remainStatData)) {
- remainStatData = new ArrayList<>();
- }
- logger.info("用户:{}查询首页单个公众号:{}粉丝忠诚度,date:{} --->end",userId,accountId,date);
- return ResponseEntity.ok(JsonResult.success(remainStatData));
- }
- @GetMapping("/articles/{accountId}")
- @ApiOperation(value = "查询单个公众号--图文影响力")
- public ResponseEntity<JsonResult<List<ArticleStatData>>> getFansPageStat(@RequestHeader String token,
- @PathVariable String accountId,
- @RequestParam String startDate,
- @RequestParam String endDate) {
- String userId = JwtTokenUtil.getUserId(token);
- if (!checkDate(startDate,endDate)){
- throw new CustomException(500,"请选择查询时间!");
- }
- logger.info("用户:{}查询首页单个公众号:{}图文影响力,startDate:{},endDate:{} --->start",userId,accountId,startDate,endDate);
- List<ArticleStat> articleStats = articleStatService.queryArticleStatByDate(accountId,startDate,endDate);
- List<ArticleStatData> articleStatData = statArticleData(articleStats);
- if (CollectionUtils.isEmpty(articleStatData)){
- articleStatData = new ArrayList<>();
- }
- logger.info("用户:{}查询首页单个公众号:{}图文影响力,startDate:{},endDate:{} --->start",userId,accountId,startDate,endDate);
- return ResponseEntity.ok(JsonResult.success(articleStatData));
- }
- /**
- * 统计粉丝数据 好难受写不出完美的代码
- * @author wangxiao
- * @date 16:00 2020/9/16
- * @param accountId
- * @param type
- * @param startDate
- * @param endDate
- * @return java.util.List<com.idiot.operationbackend.vo.StatData>
- */
- private List<GeneralStatData> statFansGrowthData(String accountId, String type, LocalDate startDate, LocalDate endDate) {
- // 粉丝增长数据 因为能选择今天 需要在 用户动作分析里面取数据。或者一小时分析一次数据
- long disValue = 0;
- if (HOUR.equals(type)) {
- disValue = 7200;
- }else if (DAY.equals(type)){
- disValue = 86400;
- }else if (WEEK.equals(type)){
- disValue = 604800;
- }else if (MONTH.equals(type)){
- // 默认 30 天
- disValue = 2592000;
- }else {
- throw new CustomException(500,"请你选择正确的时间统计类型!");
- }
- LocalDateTime startLocalDate = startDate.atTime(Constants.DEFAULT_TIME);
- LocalDateTime endLocalDate = endDate.plusDays(1).atTime(Constants.DEFAULT_TIME);
- List<FansActionStat> fansActionStats = actionStatService.queryFansActionStat(accountId,startLocalDate,endLocalDate);
- if (CollectionUtils.isEmpty(fansActionStats)) {
- throw new CustomException(500,"暂无数据!");
- }
- long start = startLocalDate.toEpochSecond(Constants.DEFAULT_ZONE);
- long end = endLocalDate.toEpochSecond(Constants.DEFAULT_ZONE);
- List<GeneralStatData> statDataList = new ArrayList<>();
- GeneralStatData statData = null;
- List<FansActionStat> tempStatList = null;
- while (start<=end){
- long finalStart = start;
- long finalDisValue = disValue;
- tempStatList = fansActionStats.stream()
- .filter(e->e.getCreateTime() >= finalStart && e.getCreateTime()<= finalStart + finalDisValue)
- .sorted(Comparator.comparingLong(FansActionStat::getCreateTime))
- .collect(Collectors.toList());
- statData = countStatData(tempStatList,finalStart,finalStart+finalDisValue,type);
- statDataList.add(statData);
- start += finalDisValue;
- }
- return statDataList;
- }
- /**
- * 校验日期
- * @author wangxiao
- * @date 11:58 2020/9/17
- * @param start
- * @param end
- * @return boolean
- */
- private boolean checkDate (String start, String end) {
- return !(StringUtils.isEmpty(start) | StringUtils.isEmpty(end));
- }
- /**
- * 统计 粉丝增长 时间段
- * @author wangxiao
- * @date 16:45 2020/9/16
- * @param fansActionStats
- * @param start
- * @param end
- * @param type
- * @return com.idiot.operationbackend.vo.StatData
- */
- private GeneralStatData countStatData (List<FansActionStat> fansActionStats, long start, long end, String type) {
- LocalDateTime startDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(start),Constants.DEFAULT_ZONE);
- LocalDateTime endDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(end),Constants.DEFAULT_ZONE);
- GeneralStatData statData = new GeneralStatData();
- long newNum = 0;
- long cancelNum = 0;
- long inactiveNum = 0;
- if (!CollectionUtils.isEmpty(fansActionStats)) {
- newNum = fansActionStats.parallelStream().filter(e->Constants.NEW == e.getAction()).count();
- cancelNum = fansActionStats.parallelStream().filter(e->Constants.CANCEL == e.getAction()).count();
- inactiveNum = fansActionStats.parallelStream().filter(e->Constants.NEW != e.getAction() && Constants.CANCEL != e.getAction()).count();
- }
- String label = "";
- if (HOUR.equals(type)) {
- label = String.format("%s %s:%s-%s:%s",startDateTime.toLocalDate(),startDateTime.getHour(),"00",endDateTime.getHour(),"00");
- }else if (DAY.equals(type)){
- label = String.format("%s",startDateTime.toLocalDate());
- }else if (WEEK.equals(type)){
- label = String.format("%s/%s-%s/%s",startDateTime.getMonthValue(),startDateTime.getDayOfMonth()
- ,endDateTime.getMonthValue(),endDateTime.getDayOfMonth());
- }else if (MONTH.equals(type)){
- label = String.format("%s-%s",startDateTime.getYear(),startDateTime.getMonthValue());
- }
- statData.setDateLabel(label);
- statData.setAddNum(newNum-cancelNum);
- statData.setCancelNum(cancelNum);
- statData.setNewNum(newNum);
- statData.setInactiveNum(inactiveNum);
- return statData;
- }
- /**
- * 统计粉丝属性
- * @author wangxiao
- * @date 18:57 2020/9/16
- * @param fansData
- * @param map
- * @return void
- */
- private void statFansProperty(List<NumberStatData> fansData,Map<String,Object> map) {
- if (!CollectionUtils.isEmpty(fansData)) {
- Map<String,List<NumberStatData>> numData = fansData.stream().collect(Collectors.groupingBy(NumberStatData::getType));
- map.putAll(numData);
- }
- }
- /**
- * 统计留存粉丝
- * @author wangxiao
- * @date 14:22 2020/9/17
- * @param accountStats
- * @return java.util.List<com.idiot.operationbackend.vo.RemainStatData>
- */
- private List<RemainStatData> statFansRemainData(List<AccountStat> accountStats) {
- if (CollectionUtils.isEmpty(accountStats)) {
- return null;
- }
- int size = accountStats.size();
- List<RemainStatData> remainStatDataList = new ArrayList<>(size);
- String statDate = null;
- Long newNum = null;
- Long totalNum = null;
- RemainStatData remain = null;
- for (AccountStat temp : accountStats) {
- statDate = temp.getStatDate();
- newNum = temp.getNewNum();
- totalNum = temp.getTotalFansNum();
- remain = new RemainStatData(statDate,newNum);
- remain.setDay1Num(calcRemain(accountStats,totalNum,statDate,1));
- remain.setDay2Num(calcRemain(accountStats,totalNum,statDate,2));
- remain.setDay3Num(calcRemain(accountStats,totalNum,statDate,3));
- remain.setDay4Num(calcRemain(accountStats,totalNum,statDate,4));
- remain.setDay5Num(calcRemain(accountStats,totalNum,statDate,5));
- remain.setDay6Num(calcRemain(accountStats,totalNum,statDate,6));
- remain.setDay7Num(calcRemain(accountStats,totalNum,statDate,7));
- remainStatDataList.add(remain);
- }
- return remainStatDataList;
- }
- /**
- * 计算留存数
- * @author wangxiao
- * @date 14:35 2020/9/17
- * @param accountStats 数组
- * @param nowTotal 当前总数
- * @param targetIndex 几天前下表
- * @param nowStatDate 当前统计日期
- * @return long
- */
- private long calcRemain (List<AccountStat> accountStats,long nowTotal,String nowStatDate,int targetIndex) {
- long remainNum;
- LocalDate nowDate = LocalDate.parse(nowStatDate,Constants.DATE_FORMATTER);
- String targetStatDate = nowDate.plusDays(-targetIndex).format(Constants.DATE_FORMATTER);
- remainNum = accountStats.stream()
- .filter(e->targetStatDate.equals(e.getStatDate()))
- .findAny().map(e->e.getTotalFansNum()-nowTotal)
- .orElse(0L);
- return remainNum;
- }
- /**
- * 统计图文影响力
- * @author wangxiao
- * @date 16:06 2020/9/17
- * @param articleStats
- * @return java.util.List<com.idiot.operationbackend.vo.ArticleStatData>
- */
- private List<ArticleStatData> statArticleData (List<ArticleStat> articleStats) {
- if (CollectionUtils.isEmpty(articleStats)){
- return null;
- }
- Map<String,List<ArticleStat>> temp = articleStats.stream().collect(Collectors.groupingBy(ArticleStat::getStatDate));
- List<ArticleStatData> articleStatData = new ArrayList<>(temp.size());
- List<ArticleStat> var = null;
- ArticleStatData result = null;
- for (Map.Entry<String,List<ArticleStat>> entry : temp.entrySet()) {
- var = entry.getValue();
- result = new ArticleStatData(entry.getKey(),var);
- result.setShareUser(var.stream().mapToLong(ArticleStat::getShareUser).sum());
- result.setShareCount(var.stream().mapToLong(ArticleStat::getShareCount).sum());
- result.setAddToFavCount(var.stream().mapToLong(ArticleStat::getAddToFavCount).sum());
- result.setAddToFavUser(var.stream().mapToLong(ArticleStat::getAddToFavUser).sum());
- result.setIntPageReadCount(var.stream().mapToLong(ArticleStat::getIntPageReadCount).sum());
- result.setIntPageReadUser(var.stream().mapToLong(ArticleStat::getIntPageReadUser).sum());
- result.setOriPageReadCount(var.stream().mapToLong(ArticleStat::getOriPageReadCount).sum());
- result.setOriPageReadUser(var.stream().mapToLong(ArticleStat::getOriPageReadUser).sum());
- articleStatData.add(result);
- }
- return articleStatData;
- }
- }
|