Browse Source

Merge remote-tracking branch 'remotes/origin/test' into performance-branch

jiequan.bi 5 years ago
parent
commit
f17361ab7d
15 changed files with 1020 additions and 71 deletions
  1. 47 0
      jeecg-boot-base-common/src/main/java/org/jeecg/common/constant/AccountReportConstants.java
  2. 16 8
      jeecg-boot-base-common/src/main/java/org/jeecg/common/util/DateUtils.java
  3. 101 0
      jeecg-boot-base-common/src/main/java/org/jeecg/common/util/JsonResourceUtil.java
  4. 6 1
      jeecg-boot-module-system/src/main/java/org/jeecg/JeecgApplication.java
  5. 37 4
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/controller/ProjectMemberController.java
  6. 3 1
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/service/IProjectMemberService.java
  7. 26 11
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/service/impl/ProjectMemberServiceImpl.java
  8. 158 0
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/controller/BytedanceAccountReportCtrl.java
  9. 44 0
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/mapper/BytedanceAccountReportMapper.java
  10. 193 0
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/mapper/xml/BytedanceAccountReportMapper.xml
  11. 19 0
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/service/IBytedanceAccountReportService.java
  12. 176 0
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/service/impl/BytedanceAccountReportServiceImpl.java
  13. 7 46
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/service/impl/BytedanceHomepageReportServiceImpl.java
  14. 49 0
      module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/utils/LinkUtils.java
  15. 138 0
      module-toutiao/src/main/resources/json_template/bytedance_filed_mapping.json

+ 47 - 0
jeecg-boot-base-common/src/main/java/org/jeecg/common/constant/AccountReportConstants.java

@@ -0,0 +1,47 @@
+package org.jeecg.common.constant;
+
+import org.jeecg.common.util.JsonResourceUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *  Created by JQ.bi on 2020.5.30
+ */
+public class AccountReportConstants {
+
+    /**
+     * 私有构造器
+     */
+    private AccountReportConstants(){
+
+    }
+
+    /** 单体实例 */
+    private static AccountReportConstants instance;
+
+
+    /**
+     * @return 返回 instance
+     */
+    public static AccountReportConstants getInstance() {
+        if (instance == null) {
+            instance = new AccountReportConstants();
+        }
+        return instance;
+    }
+
+    /** 字典数据 */
+    public static Map<String, Map<String,Object>> dicMap = new HashMap<>();
+
+    /**
+     * 初始化字典
+     */
+    public void init(){
+        //加载json文件
+        Object json=JsonResourceUtil.getJsonObjFromResource("/json_template/bytedance_filed_mapping.json");
+        //json 转为map存为静态常量
+        dicMap=JsonResourceUtil.jsonToMap(json);
+    }
+
+}

+ 16 - 8
jeecg-boot-base-common/src/main/java/org/jeecg/common/util/DateUtils.java

@@ -1,5 +1,6 @@
 package org.jeecg.common.util;
 
+import org.jeecg.common.constant.SystemDateConstant;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.util.StringUtils;
@@ -1313,6 +1314,21 @@ public class DateUtils extends PropertyEditorSupport {
         return calendar.getTime();
     }
 
+    /**
+     * 判断两个日期间隔是否大于半年
+     *
+     * @return
+     */
+    public static boolean isMoreSixMonth(String startDate, String endDate) {
+        Calendar c = Calendar.getInstance();
+        c.setTime(Objects.requireNonNull(parseDate(startDate, SystemDateConstant.yyyy_MM_dd)));
+        long time1 = c.getTimeInMillis();
+        c.setTime(Objects.requireNonNull(parseDate(endDate, SystemDateConstant.yyyy_MM_dd)));
+        long time2 = c.getTimeInMillis();
+        long between_days = (time2 - time1) / (1000 * 3600 * 24);
+        int day = Integer.parseInt(String.valueOf(between_days));
+        return day > 180;
+    }
 
     public static List<Date> findDates(Date dBegin, Date dEnd) {
         List<Date> lDate = new ArrayList<Date>();
@@ -1332,14 +1348,6 @@ public class DateUtils extends PropertyEditorSupport {
         return lDate;
     }
 
-
-    public static void main(String[] args) throws ParseException {
-        String nowDate = DateUtils.getNowDate("yyyy-MM-dd");
-        String s = DateUtils.addDay(nowDate, -180);
-        System.err.println(nowDate);
-        System.err.println(s);
-    }
-
 }
 
 

+ 101 - 0
jeecg-boot-base-common/src/main/java/org/jeecg/common/util/JsonResourceUtil.java

@@ -0,0 +1,101 @@
+package org.jeecg.common.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.jeecg.common.constant.AccountReportConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
+ * Created by JQ.bi on 2020.06.03
+ */
+public class JsonResourceUtil {
+
+    private static Logger logger = LoggerFactory.getLogger(JsonResourceUtil.class);
+
+    private JsonResourceUtil() {
+
+    }
+
+    //filename 为文件名字 如 “/json/app_version_info.json”
+    public static JSONObject getJsonObjFromResource(String filename) {
+        JSONObject json = null;
+        if (!filename.contains(".json")) {
+            filename += ".json";
+        }
+        try {
+            ClassPathResource classPathResource = new ClassPathResource(filename);
+            if (classPathResource.exists()) {
+                InputStream inputStream = classPathResource.getInputStream();
+                String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+                json = JSON.parseObject(content);
+            } else {
+                logger.info("file not exist!");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.info("readFileToString" + e.getMessage());
+        }
+        return json;
+    }
+
+    public static Map<String, Map<String, Object>> jsonToMap(Object jsonObj) {
+        JSONObject jsonObject = JSONObject.parseObject(jsonObj.toString());
+        Map<String, Map<String, Object>> mapMap = new HashMap<>();
+        jsonObject.forEach((key, value) -> {
+            mapMap.put(key, JSONObject.parseObject(value.toString()));
+        });
+        return mapMap;
+    }
+
+    /**
+     * 拼接字段
+     */
+    public static String joinFiled(JSONArray array) {
+        StringBuilder sb = new StringBuilder();
+        array.forEach(it -> {
+            if (AccountReportConstants.dicMap.get(it.toString()).isEmpty()) {
+                sb.append(it).append(",");
+            } else {
+                sb.append(AccountReportConstants.dicMap.get(it.toString()).get("filed")).append(",");
+            }
+        });
+        return sb.deleteCharAt(sb.length() - 1).toString();
+    }
+
+    /**
+     * 拼接title
+     */
+    public static List<String> joinTitle(JSONArray array) {
+        List<String> titles = new ArrayList<>(20);
+        array.forEach(it -> {
+            if (AccountReportConstants.dicMap.get(it.toString()).isEmpty()) {
+                titles.add(it.toString());
+            } else {
+                titles.add(AccountReportConstants.dicMap.get(it.toString()).get("comment").toString());
+            }
+        });
+        return titles;
+    }
+
+    /**
+     * 拼接字段
+     */
+    public static String joinAllFiled() {
+        StringBuilder sb = new StringBuilder();
+        AccountReportConstants.dicMap.forEach((k, v) -> {
+            sb.append(v.get("filed")).append(",");
+        });
+        return sb.deleteCharAt(sb.length() - 1).toString();
+    }
+}

+ 6 - 1
jeecg-boot-module-system/src/main/java/org/jeecg/JeecgApplication.java

@@ -3,6 +3,7 @@ package org.jeecg;
 import cn.com.ctop.common.module.utils.SpringUtils;
 import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
 import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.constant.AccountReportConstants;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.ConfigurableApplicationContext;
@@ -48,6 +49,10 @@ public class JeecgApplication {
     public PaginationInterceptor paginationInterceptor() {
         return new PaginationInterceptor();
     }
-
+    //加载数据字典
+    @Bean
+    public void instanceFiledDic(){
+        AccountReportConstants.getInstance().init();
+    }
 
 }

+ 37 - 4
jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/controller/ProjectMemberController.java

@@ -1,8 +1,8 @@
 package org.jeecg.modules.ctop.controller;
 
-import cn.com.ctop.common.module.constant.CtopRoleCodeConstant;
 import cn.com.ctop.common.module.service.ISysRoleService;
 import cn.com.ctop.common.module.utils.Check;
+import cn.com.ctop.common.module.utils.CtopAdConstant;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -78,6 +78,7 @@ public class ProjectMemberController {
         return map;
     }
 
+
     /**
      * 我参与项目
      *
@@ -92,7 +93,7 @@ public class ProjectMemberController {
         try {
             QueryWrapper<ProjectMember> queryWrapper = new QueryWrapper<>();
             String roleCode = sysRoleService.getRoleCodeByUserId(userId);
-            if (!CtopRoleCodeConstant.COMMON_ROLE_CODE_ADMIN.equals(roleCode) && !"sale".equals(roleCode) && !"saleDirector".equals(roleCode)) {
+            if (!"admin".equals(roleCode) && !"sale".equals(roleCode) && !"saleDirector".equals(roleCode)) {
                 queryWrapper.eq("user_id", userId);
             }
             queryWrapper.groupBy("project_id");
@@ -327,7 +328,7 @@ public class ProjectMemberController {
     @AutoLog(value = "头条视频报表-参与项目列表")
     @ApiOperation(value = "头条视频报表-参与项目列表", notes = "头条视频报表-参与项目列表")
     @GetMapping(value = "/bytedanceProjectParticipateInList")
-    public  Result<List<ProjectMember>> bytedanceProjectParticipateInList() {
+    public Result<List<ProjectMember>> bytedanceProjectParticipateInList() {
         Result<List<ProjectMember>> result = new Result<>();
         List<Integer> mediaIds = new ArrayList<>();
         mediaIds.add(1);
@@ -343,7 +344,39 @@ public class ProjectMemberController {
 
     }
 
-
+    /**
+     * 查询当前账户下的
+     *
+     * @return
+     */
+    @GetMapping(value = "/getProjectAccountByUserId")
+    public Result<List<Map<String, Object>>> getProjectAccountBy() {
+        Result<List<Map<String, Object>>> resultBody = new Result<>();
+        try {
+            List<Integer> mediaList = new ArrayList<>();
+            mediaList.add(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE_INT);
+            mediaList.add(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE_INSIDE_INT);
+            //查询登录账号下的项目
+            List<ProjectMember> projectMemberList = projectMemberService.getProjects(mediaList);
+            if (projectMemberList.isEmpty()) {
+                resultBody.error500("账户下未找到项目");
+                return resultBody;
+            }
+            List<Map<String, Object>> result = new ArrayList<>();
+            projectMemberList.forEach(ProjectMember -> {
+                Map<String, Object> temp=projectMemberService.queryAccountByProjectId(ProjectMember);
+                if(temp!=null){
+                    result.add(temp);
+                }
+            });
+            resultBody.setSuccess(true);
+            resultBody.setResult(result);
+        } catch (Exception e) {
+            resultBody.setSuccess(false);
+            resultBody.success("查询失败");
+        }
+        return resultBody;
+    }
 
 
 }

+ 3 - 1
jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/service/IProjectMemberService.java

@@ -6,6 +6,7 @@ import org.jeecg.modules.ctop.entity.ProjectMember;
 import org.jeecg.modules.system.entity.SysUser;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 项目成员
@@ -17,8 +18,9 @@ import java.util.List;
 public interface IProjectMemberService extends IService<ProjectMember> {
     void addMember(SysUser sysUser, Project project);
 
-
     List<Long> selectProjectsByUserId(String userId);
 
     List<ProjectMember> getProjects(List<Integer> mediaIds);
+
+    Map<String,Object> queryAccountByProjectId(ProjectMember projectMember);
 }

+ 26 - 11
jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/service/impl/ProjectMemberServiceImpl.java

@@ -1,8 +1,10 @@
 package org.jeecg.modules.ctop.service.impl;
 
-import cn.com.ctop.common.module.constant.CtopRoleCodeConstant;
+import cn.com.ctop.common.module.entity.UserAllocation;
+import cn.com.ctop.common.module.mapper.UserAllocationMapper;
 import cn.com.ctop.common.module.service.ISysRoleService;
 import cn.com.ctop.common.module.utils.Check;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.system.vo.LoginUser;
@@ -14,6 +16,7 @@ import org.jeecg.modules.system.entity.SysUser;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -27,10 +30,13 @@ import java.util.Map;
  */
 @Service
 public class ProjectMemberServiceImpl extends ServiceImpl<ProjectMemberMapper, ProjectMember> implements IProjectMemberService {
+
     @Autowired
     private ProjectMemberMapper memberMapper;
     @Autowired
     private ISysRoleService sysRoleService;
+    @Autowired
+    private UserAllocationMapper userAllocationMapper;
 
     @Override
     public void addMember(SysUser sysUser, Project project) {
@@ -63,30 +69,39 @@ public class ProjectMemberServiceImpl extends ServiceImpl<ProjectMemberMapper, P
     }
 
     //视频报表
-    public List<ProjectMember> getProjects(List<Integer> mediaIds){
+    public List<ProjectMember> getProjects(List<Integer> mediaIds) {
         LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
         String userId = sysUser.getId();
         String roleCode = memberMapper.getRoleCodeByUserId(userId);
         String companyId = memberMapper.getCompanyIdByUserId(userId);
 
-        //List<Integer> mediaIds = new ArrayList<>();
-        //mediaIds.add(1);
-        //mediaIds.add(3);
         //角色权限判断
         List<ProjectMember> projectMemberList = null;
-        if(roleCode.equals("plan") || roleCode.equals("clip") || roleCode.equals("shot") || roleCode.equals("plane")|| roleCode.equals("planeLeader")){
+        if (roleCode.equals("plan") || roleCode.equals("clip") || roleCode.equals("shot") || roleCode.equals("plane") || roleCode.equals("planeLeader")) {
             projectMemberList = memberMapper.designProjects(userId, mediaIds);
-        }else if( roleCode.equals("designTeamLeader")){
+        } else if (roleCode.equals("designTeamLeader")) {
             projectMemberList = memberMapper.designLeaderProjects(companyId, mediaIds);
-        }else if(roleCode.equals(CtopRoleCodeConstant.COMMON_ROLE_CODE_ADMIN)){
+        } else if (roleCode.equals("admin")) {
             projectMemberList = memberMapper.adminProjects(mediaIds);
-        }else if(roleCode.equals("operator") || roleCode.equals("operationAssistant") || roleCode.equals("touTiaoOperationManager")){
+        } else if (roleCode.equals("operator") || roleCode.equals("operationAssistant") || roleCode.equals("touTiaoOperationManager")) {
             projectMemberList = memberMapper.operationProjects(userId, mediaIds);
         }
 
         return projectMemberList;
     }
 
-
-
+    public Map<String, Object> queryAccountByProjectId(ProjectMember projectMember) {
+        Map<String, Object> temp = new HashMap<>();
+        temp.put("project", projectMember);
+        QueryWrapper<UserAllocation> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("project_id", projectMember.getProjectId());
+        queryWrapper.isNotNull("account_id");
+        List<UserAllocation> userAllocations = userAllocationMapper.selectList(queryWrapper);
+        if(userAllocations.isEmpty()){
+            temp=null;
+        }else {
+            temp.put("account", userAllocations);
+        }
+        return temp;
+    }
 }

+ 158 - 0
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/controller/BytedanceAccountReportCtrl.java

@@ -0,0 +1,158 @@
+package cn.com.ctop.toutiao.modules.report.controller;
+
+import cn.com.ctop.common.module.utils.ExportExcelUtils;
+import cn.com.ctop.common.module.utils.HttpUtils;
+import cn.com.ctop.toutiao.modules.report.service.IBytedanceAccountReportService;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.util.JsonResourceUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by JQ.bi on 2020.6.5
+ */
+@Slf4j
+@RestController
+@RequestMapping("/ctop/byteDance/dailyPage")
+public class BytedanceAccountReportCtrl {
+
+    @Autowired
+    IBytedanceAccountReportService bytedanceAccountReportService;
+
+    /**
+     * 查询素材报表chart数据
+     * @param requestBody
+     * @return
+     */
+    @PostMapping("/report/chart")
+    public Result<Map<String, Object>> getAccountChartReport(@RequestBody JSONObject requestBody) {
+        Result<Map<String, Object>> resultBody = new Result<>();
+        Map<String, Object> result = new HashMap<>();
+        if (requestBody.isEmpty()) {
+            log.error("request body is empty");
+            resultBody.setSuccess(false);
+        }
+        String mediaId = requestBody.getString("mediaId");
+        BigDecimal discount = requestBody.getBigDecimal("discount");
+        JSONArray accounts = requestBody.getJSONArray("accountIds");
+        String startDate = requestBody.getString("startDate");
+        String endDate = requestBody.getString("endDate");
+        try {
+            Map<String, Object> sumData = bytedanceAccountReportService.getSumDataBy(mediaId, discount, accounts, startDate, endDate);
+            List<JSONObject> chartData = bytedanceAccountReportService.getChartDataBy(mediaId, discount, accounts, startDate, endDate);
+            result.put("sumData",sumData);
+            result.put("chartData",chartData);
+            resultBody.setResult(result);
+            resultBody.setSuccess(true);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            resultBody.setSuccess(false);
+        }
+        return resultBody;
+    }
+
+    /**
+     * 查询素材报表表格数据
+     * @param requestBody
+     * @return
+     */
+    @PostMapping("/report/list")
+    public Result<List<JSONObject>> getListReport(@RequestBody JSONObject requestBody) {
+        Result<List<JSONObject>> result = new Result<>();
+        if (requestBody.isEmpty()) {
+            log.error("request body is empty");
+            result.setSuccess(false);
+        }
+        String mediaId = requestBody.getString("mediaId");
+        BigDecimal discount = requestBody.getBigDecimal("discount");
+        JSONArray accounts = requestBody.getJSONArray("accountIds");
+        String startDate = requestBody.getString("startDate");
+        String endDate = requestBody.getString("endDate");
+        int hour= requestBody.getInteger("hour");
+        String target= requestBody.getString("target");
+        String order= requestBody.getString("order");
+        try {
+            List<JSONObject> listData= bytedanceAccountReportService.getListDataBy(mediaId,discount,accounts,startDate,endDate,hour,target,order);
+            result.setResult(listData);
+            result.setSuccess(true);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            result.setSuccess(false);
+        }
+        return result;
+    }
+
+    /**
+     *  导出数据
+     * @param requestBody
+     * @param request
+     * @param response
+     */
+    @PostMapping("/report/excel")
+    public void getExcelReport(@RequestBody JSONObject requestBody,
+                               HttpServletRequest request,
+                               HttpServletResponse response) {
+        JSONArray columns=requestBody.getJSONArray("columns");
+        if(columns.isEmpty()){
+            log.error("请选择需要导出的字段");
+        }
+        String filed= JsonResourceUtil.joinFiled(columns);
+        List<String> titles= new ArrayList<>();
+        titles.add("账户Id");
+        titles.add("账户名称");
+        titles.addAll(JsonResourceUtil.joinTitle(columns));
+        //此处增加两个元素是为了保证数据有序
+        columns.add(0,"accountId");
+        columns.add(1,"authName");
+        String mediaId = requestBody.getString("mediaId");
+        JSONArray accounts = requestBody.getJSONArray("accountIds");
+        String startDate = requestBody.getString("startDate");
+        String endDate = requestBody.getString("endDate");
+        String target= requestBody.getString("target");
+        String order= requestBody.getString("order");
+        int hour= requestBody.getInteger("hour");
+        List<JSONObject> excelData= bytedanceAccountReportService.getExcelDataBy(filed,mediaId,accounts,startDate,endDate,hour,target,order);
+        if(excelData.isEmpty()){
+            return;
+        }
+        List<List<Object>> excelList= new ArrayList<>();
+        excelData.forEach(data->{
+            List<Object> temp= new ArrayList<>();
+            columns.forEach(k->{
+                temp.add(data.get(k.toString()));
+            });
+            excelList.add(temp);
+        });
+        try{
+            String[] headers = titles.toArray(new String[titles.size()]);
+            OutputStream os = response.getOutputStream();
+            ExportExcelUtils eeu = new ExportExcelUtils();
+            XSSFWorkbook workbook = new XSSFWorkbook();
+            eeu.exportExcel(workbook, 0, "头条素材报表", headers, excelList);
+            HttpUtils.setResponseHeader(response, "头条素材报表.xlsx");
+            workbook.write(os);
+            os.flush();
+            os.close();
+        }catch (IOException e){
+            log.error(e.getMessage());
+        }
+    }
+
+}

+ 44 - 0
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/mapper/BytedanceAccountReportMapper.java

@@ -0,0 +1,44 @@
+package cn.com.ctop.toutiao.modules.report.mapper;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface BytedanceAccountReportMapper {
+
+    //今日汇总数据
+    JSONObject queryTodaySumReportBy(@Param("statDate") String statDate,@Param("accountIds")  JSONArray accountIds);
+
+    //根据小时区间查询今日汇总数据
+    List<JSONObject> queryTodaySumByHourGroupAccount(@Param("filed") String filed,@Param("statDate") String statDate,@Param("hour") int hour,@Param("accountIds") JSONArray accountIds, String target, String order);
+
+    //根据小时区间查询今日汇总数据
+    JSONObject queryTodaySumByHour(@Param("statDate") String statDate,@Param("hour") int hour,@Param("accountIds") JSONArray accountIds);
+
+    //根据小时区间查询今日汇总数据
+    JSONObject querySumByHour(@Param("filed") String filed,@Param("statDate") String statDate,@Param("hour") int hour,@Param("accountIds") JSONArray accountIds);
+
+    //今日明细数据
+    List<JSONObject> queryTodayDetailReportBy(@Param("filed") String filed,@Param("statDate") String statDate,@Param("accountIds") JSONArray accountIds);
+
+    //根据开始、结束时间 查询汇总数据
+    JSONObject querySumByStartEndDate(@Param("endDate") String endDate, @Param("startDate") String startDate,@Param("accountIds") JSONArray accountIds);
+
+    //根据开始、结束时间 查询汇总数据
+    JSONObject queryAllSumByStartEndDate(@Param("filed") String filed,@Param("endDate") String endDate, @Param("startDate") String startDate,@Param("accountIds") JSONArray accountIds);
+
+    //根据时间查询数据按账户分组
+    List<JSONObject> querySumByDateGroupAccount(@Param("filed") String filed,@Param("endDate") String endDate, @Param("startDate") String startDate,@Param("accountIds") JSONArray accountIds,String target, String order);
+
+    //根据开始、结束时间 查询明细数据
+    List<JSONObject> queryDetailByStartEndDate(@Param("endDate") String endDate, @Param("startDate") String startDate,@Param("accountIds") JSONArray accountIds);
+
+    //按月分组查询明细数据
+    List<JSONObject> queryDetailGroupMonthByDate(@Param("endDate") String endDate, @Param("startDate") String startDate,@Param("accountIds") JSONArray accountIds);
+
+    //查询固定月的明细数据
+    List<JSONObject> queryDetailGroupDayByMonth(@Param("month") String month);
+
+}

+ 193 - 0
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/mapper/xml/BytedanceAccountReportMapper.xml

@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.com.ctop.toutiao.modules.report.mapper.BytedanceAccountReportMapper">
+
+    <select id="queryTodaySumReportBy" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          ROUND(sum(cost),2) cost,
+          sum(show_num) showNum,
+          sum(click) click,
+          sum(convert_num) as convertNum,
+          max(stat_hour) maxHour
+        FROM
+          ctop_bytedance_report_advertiser_hourly
+        WHERE
+          stat_datetime = #{statDate}
+        AND advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="queryTodaySumByHourGroupAccount" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          t2.account_id as accountId,
+          t2.auth_name as authName,
+          ${filed}
+        FROM ctop_bytedance_report_advertiser_hourly t1
+        left join ctop_user_allocation t2 on t1.advertiser_id=t2.account_id
+        WHERE t1.stat_datetime = #{statDate}
+          and t1.stat_hour &lt;= #{hour}
+        AND t1.advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        group by t1.advertiser_id
+        order by ${target} ${order}
+    </select>
+
+    <select id="queryTodaySumByHour" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          ROUND(sum(cost),2) cost,
+          sum(show_num) showNum,
+          sum(click) click,
+          sum(convert_num) as convertNum
+        FROM
+          ctop_bytedance_report_advertiser_hourly
+        WHERE
+          stat_datetime = #{statDate}
+        and stat_hour &lt;= #{hour}
+        AND advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="querySumByHour" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          ${filed}
+        FROM
+          ctop_bytedance_report_advertiser_hourly t1
+        WHERE
+          t1.stat_datetime = #{statDate}
+        and t1.stat_hour &lt;= #{hour}
+        AND t1.advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="queryTodayDetailReportBy" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          ROUND(sum(cost),2) cost,
+          sum(show_num) showNum,
+          sum(click) click,
+          sum(convert_num) as convertNum,
+          stat_hour as statHour
+        FROM
+            ctop_bytedance_report_advertiser_hourly
+        WHERE
+            stat_datetime = #{statDate}
+        AND advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        GROUP BY
+            stat_hour
+        ORDER BY
+            stat_hour ASC
+    </select>
+
+    <select id="queryAllSumByStartEndDate" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          ${filed}
+        FROM ctop_bytedance_report_advertiser_daily t1
+        WHERE t1.stat_datetime &lt;= #{endDate} '00:00:00'
+        AND t1.stat_datetime &gt;= #{startDate}
+        AND t1.advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="querySumByStartEndDate" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT ROUND(sum(cost), 2) cost,
+        sum(show_num)       showNum,
+        sum(click)          click,
+        sum(convert_num) as convertNum
+        FROM ctop_bytedance_report_advertiser_daily t1
+        WHERE t1.stat_datetime &lt;= #{endDate} '00:00:00'
+        AND t1.stat_datetime &gt;= #{startDate}
+        AND advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="querySumByDateGroupAccount" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          t2.account_id as accountId,
+          t2.auth_name as authName,
+          ${filed}
+        FROM
+        ctop_bytedance_report_advertiser_daily t1
+        left join ctop_user_allocation t2 on t1.advertiser_id=t2.account_id
+        WHERE
+            t1.stat_datetime &lt;= #{endDate} '00:00:00'
+        AND t1.stat_datetime &gt;= #{startDate}
+        AND t1.advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        group by t1.advertiser_id
+        order by ${target} ${order}
+    </select>
+
+    <select id="queryDetailByStartEndDate" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          ROUND(sum(cost),2) cost,
+          sum(show_num) showNum,
+          sum(click) click,
+          sum(convert_num) convertNum,
+          DATE_FORMAT(stat_datetime, '%Y-%m-%d') statDate
+        FROM
+           ctop_bytedance_report_advertiser_daily
+        WHERE stat_datetime &lt;= #{endDate} '00:00:00'
+          AND stat_datetime &gt;= #{startDate}
+          AND advertiser_id in
+          <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+          </foreach>
+        group by stat_datetime
+        order by stat_datetime asc
+    </select>
+
+    <select id="queryDetailGroupMonthByDate" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+          ROUND(sum(cost),2) cost,
+          sum(show_num) showNum,
+          sum(click) click,
+          sum(convert_num) convertNum,
+          DATE_FORMAT(t1.stat_datetime, '%Y-%m') statDate
+        FROM ctop_bytedance_report_advertiser_daily t1
+        WHERE t1.stat_datetime &lt;= #{endDate} '00:00:00'
+          AND t1.stat_datetime &gt;= #{startDate}
+          AND t1.advertiser_id in
+        <foreach item="item" index="index" collection="accountIds"
+                 open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        group by DATE_FORMAT(t1.stat_datetime, '%Y-%m')
+        order by t1.stat_datetime asc
+    </select>
+
+    <select id="queryDetailGroupDayByMonth" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+               DATE_FORMAT(stat_datetime, '%Y-%m-%d')                      statDate,
+               SUBSTR(DATE_FORMAT(stat_datetime, '%Y-%m-%d') FROM 9 FOR 2) day
+        FROM ctop_bytedance_report_advertiser_daily
+        WHERE stat_datetime like '${month}%'
+        group by DATE_FORMAT(stat_datetime, '%Y-%m-%d')
+        order by stat_datetime asc
+    </select>
+
+</mapper>

+ 19 - 0
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/service/IBytedanceAccountReportService.java

@@ -0,0 +1,19 @@
+package cn.com.ctop.toutiao.modules.report.service;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+public interface IBytedanceAccountReportService {
+
+    Map<String,Object> getSumDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate , String endDate);
+
+    List<JSONObject> getChartDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate , String endDate);
+
+    List<JSONObject> getListDataBy(String mediaId,BigDecimal discount, JSONArray accounts,String startDate ,String endDate, int hour, String target, String order);
+
+    List<JSONObject> getExcelDataBy(String filed, String mediaId, JSONArray accounts,String startDate ,String endDate, int hour, String target, String order);
+}

+ 176 - 0
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/service/impl/BytedanceAccountReportServiceImpl.java

@@ -0,0 +1,176 @@
+package cn.com.ctop.toutiao.modules.report.service.impl;
+
+import cn.com.ctop.common.module.utils.CtopAdConstant;
+import cn.com.ctop.toutiao.modules.report.mapper.BytedanceAccountReportMapper;
+import cn.com.ctop.toutiao.modules.report.service.IBytedanceAccountReportService;
+import cn.com.ctop.toutiao.modules.utils.LinkUtils;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.jeecg.common.constant.SystemDateConstant;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.JsonResourceUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by JQ.bi on 2020.06.05
+ */
+@Service
+public class BytedanceAccountReportServiceImpl implements IBytedanceAccountReportService {
+
+    @Autowired
+    BytedanceAccountReportMapper bytedanceAccountReportMapper;
+
+    @Override
+    public Map<String, Object> getSumDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate, String endDate) {
+        Map<String, Object> result = new HashMap<>();
+        JSONObject after;
+        JSONObject before;
+        if (startDate.equals(endDate)) {
+            after = bytedanceAccountReportMapper.queryTodaySumReportBy(startDate, accounts);
+            if (after == null) {
+                return result;
+            }
+            before = bytedanceAccountReportMapper.queryTodaySumByHour(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, startDate, -1), after.getInteger("maxHour"), accounts);
+        } else {
+            after = bytedanceAccountReportMapper.querySumByStartEndDate(endDate, startDate, accounts);
+            if(after==null){
+                return result;
+            }
+            before = after;
+        }
+        result.put("Sum", getSumLink(mediaId, discount, after, before));
+        return result;
+    }
+
+    @Override
+    public List<JSONObject> getChartDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate, String endDate) {
+        List<JSONObject> result=new ArrayList<>();
+        String filedAll = JsonResourceUtil.joinAllFiled();
+        if (startDate.equals(endDate)) {
+            List<JSONObject> after = bytedanceAccountReportMapper.queryTodayDetailReportBy(filedAll, startDate, accounts);
+            if(after==null){
+                return result;
+            }
+            List<JSONObject> afterDis = this.countDiscountCost(mediaId, discount, after);
+            List<JSONObject> before = bytedanceAccountReportMapper.queryTodayDetailReportBy(filedAll, DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, startDate, -1), accounts);
+            List<JSONObject> beforeDis = this.countDiscountCost(mediaId, discount, before);
+            result = LinkUtils.getCompareDate(beforeDis, afterDis, "statHour");
+        } else {
+            List<JSONObject> after;
+            //判断是不是日期间隔大于半年
+            if(DateUtils.isMoreSixMonth(startDate,endDate)){
+                after = bytedanceAccountReportMapper.queryDetailGroupMonthByDate(endDate, startDate, accounts);
+            }
+            else {
+                after = bytedanceAccountReportMapper.queryDetailByStartEndDate(endDate, startDate, accounts);
+            }
+            if(after==null){
+                return result;
+            }
+            result = this.countDiscountCost(mediaId, discount, after);
+        }
+        return result;
+    }
+
+    @Override
+    public List<JSONObject> getListDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate, String endDate, int hour, String target, String order) {
+        List<JSONObject> result;
+        String filedAll = JsonResourceUtil.joinAllFiled();
+        if (startDate.equals(endDate)) {
+            result = bytedanceAccountReportMapper.queryTodaySumByHourGroupAccount(filedAll, startDate, hour, accounts, target, order);
+            JSONObject afterSum = bytedanceAccountReportMapper.querySumByHour(filedAll, startDate, hour, accounts);
+            JSONObject beforeSum = bytedanceAccountReportMapper.querySumByHour(filedAll, DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, startDate, -1), hour, accounts);
+            result.add(afterSum);
+            result.add(beforeSum);
+            result.add(countTotal(afterSum, beforeSum));
+        } else {
+            result = bytedanceAccountReportMapper.querySumByDateGroupAccount(filedAll, endDate, startDate, accounts, target, order);
+            result.add(bytedanceAccountReportMapper.queryAllSumByStartEndDate(filedAll, endDate, startDate, accounts));
+        }
+        return result;
+    }
+
+    @Override
+    public List<JSONObject> getExcelDataBy(String filed, String mediaId, JSONArray accounts, String startDate, String endDate, int hour, String target, String order) {
+        List<JSONObject> result;
+        if (startDate.equals(endDate)) {
+            result = bytedanceAccountReportMapper.queryTodaySumByHourGroupAccount(filed, startDate, hour, accounts, target, order);
+        } else {
+            result = bytedanceAccountReportMapper.querySumByDateGroupAccount(filed, endDate, startDate, accounts, target, order);
+        }
+        return result;
+    }
+
+    //计算汇总数据环比
+    private Map<String, Object> getSumLink(String mediaId, BigDecimal discount, JSONObject after, JSONObject before) {
+
+        Map<String, Object> result = new HashMap<>();
+
+        JSONObject costLink = new JSONObject();
+        JSONObject discountCostLink = new JSONObject();
+        JSONObject clickLink = new JSONObject();
+        JSONObject showNumLink = new JSONObject();
+        JSONObject convertNumLink = new JSONObject();
+
+        costLink.put("cost", after.getBigDecimal("cost"));
+        costLink.put("CostSumLink", LinkUtils.countLink(after.getBigDecimal("cost"), before.getBigDecimal("cost")));
+        if (mediaId.equals(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE)) {
+            discountCostLink.put("discountCost", after.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP));
+            discountCostLink.put("discountCostLink", LinkUtils.countLink(after.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP), before.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP)));
+        } else {
+            discountCostLink.put("discountCost", after.getBigDecimal("cost").multiply(discount));
+            discountCostLink.put("discountCostLink", LinkUtils.countLink(after.getBigDecimal("cost").multiply(discount), before.getBigDecimal("cost").multiply(discount)));
+        }
+        clickLink.put("click", after.getBigDecimal("click"));
+        clickLink.put("clickLink", LinkUtils.countLink(after.getBigDecimal("click"), before.getBigDecimal("click")));
+        showNumLink.put("showNum", after.getBigDecimal("showNum"));
+        showNumLink.put("showNumLink", LinkUtils.countLink(after.getBigDecimal("showNum"), before.getBigDecimal("showNum")));
+        convertNumLink.put("convertNum", after.getBigDecimal("convertNum"));
+        convertNumLink.put("convertNumLink", LinkUtils.countLink(after.getBigDecimal("convertNum"), before.getBigDecimal("convertNum")));
+        result.put("costLink", costLink);
+        result.put("discountCostLink", discountCostLink);
+        result.put("clickLink", clickLink);
+        result.put("showNumLink", showNumLink);
+        result.put("convertNumLink", convertNumLink);
+        return result;
+    }
+
+    //计算折后消耗
+    private List<JSONObject> countDiscountCost(String mediaId, BigDecimal discount, List<JSONObject> data) {
+        if (data.isEmpty()) {
+            return data;
+        }
+        if (mediaId.equals(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE)) {
+            data.forEach(it -> {
+                it.put("discountCost", it.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP));
+            });
+        } else {
+            data.forEach(it -> {
+                it.put("discountCost", it.getBigDecimal("cost").multiply(discount));
+            });
+        }
+        return data;
+    }
+
+    //计算总计环比
+    private JSONObject countTotal(JSONObject after, JSONObject before) {
+        JSONObject jsonObject = new JSONObject();
+        after.forEach((k, v) -> {
+            //去除没法计算的字段
+            if (k.equals("accountId") || k.equals("authName") || v.toString().contains("%")) {
+                jsonObject.put(k, "-");
+            } else {
+                jsonObject.put(k, LinkUtils.countLink(after.getBigDecimal(k), before.getBigDecimal(k)));
+            }
+        });
+        return jsonObject;
+    }
+}

+ 7 - 46
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/service/impl/BytedanceHomepageReportServiceImpl.java

@@ -2,6 +2,7 @@ package cn.com.ctop.toutiao.modules.report.service.impl;
 
 import cn.com.ctop.toutiao.modules.report.mapper.BytedanceHomepageMapper;
 import cn.com.ctop.toutiao.modules.report.service.IBytedanceHomepageReportService;
+import cn.com.ctop.toutiao.modules.utils.LinkUtils;
 import com.alibaba.fastjson.JSONObject;
 import org.jeecg.common.constant.SystemDateConstant;
 import org.jeecg.common.util.DateUtils;
@@ -9,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -64,11 +64,11 @@ public class BytedanceHomepageReportServiceImpl implements IBytedanceHomepageRep
             showNumWeekData.add(showNum);
         });
         costWeekLink.put("weekCostSum", weekSumData.get("cost"));
-        costWeekLink.put("weekCostSumLink", countLink(weekSumData.getBigDecimal("cost"), weekBeforeSumData.getBigDecimal("cost")));
+        costWeekLink.put("weekCostSumLink", LinkUtils.countLink(weekSumData.getBigDecimal("cost"), weekBeforeSumData.getBigDecimal("cost")));
         clickWeekLink.put("weekClickSum", weekSumData.get("click"));
-        clickWeekLink.put("weekClickSumLink", countLink(BigDecimal.valueOf(weekSumData.getLongValue("click")), BigDecimal.valueOf(weekBeforeSumData.getLong("click"))));
+        clickWeekLink.put("weekClickSumLink", LinkUtils.countLink(BigDecimal.valueOf(weekSumData.getLongValue("click")), BigDecimal.valueOf(weekBeforeSumData.getLong("click"))));
         showNumWeekLink.put("weekShowNumSum", weekSumData.get("showNum"));
-        showNumWeekLink.put("weekShowNumSumLink", countLink(BigDecimal.valueOf(weekSumData.getLongValue("showNum")), BigDecimal.valueOf(weekBeforeSumData.getLong("showNum"))));
+        showNumWeekLink.put("weekShowNumSumLink", LinkUtils.countLink(BigDecimal.valueOf(weekSumData.getLongValue("showNum")), BigDecimal.valueOf(weekBeforeSumData.getLong("showNum"))));
 
         result.put("costWeek", costWeekData);
         result.put("costWeekLink", costWeekLink);
@@ -208,20 +208,11 @@ public class BytedanceHomepageReportServiceImpl implements IBytedanceHomepageRep
         if(result.size()>1){
             for(int i=1;i<result.size();i++){
                 if(i==1){result.get(i).put("costProportion",BigDecimal.ZERO);}
-                result.get(i).put("costProportion",countLink((BigDecimal) result.get(i).get("cost"),(BigDecimal) result.get(i-1).get("cost")));
+                result.get(i).put("costProportion",LinkUtils.countLink((BigDecimal) result.get(i).get("cost"),(BigDecimal) result.get(i-1).get("cost")));
             }
         }
         return result;
     }
-    /*private JSONObject getCompareSum(String sign, String smallDate, String bigDate){
-        JSONObject result = new JSONObject();
-        if (!sign.isEmpty() && sign.equals("month")) {
-            bytedanceHomepageMapper.querySumByStartEndDate()
-        } else if (!sign.isEmpty() && sign.equals("day")) {
-            result = this.getCompareGroupByHour(bigDate, smallDate);
-        }
-        return result;
-    }*/
 
     //两个月份的数据对比
     private List<JSONObject> getCompareGroupByDay(String smallDate, String bigDate) {
@@ -230,44 +221,14 @@ public class BytedanceHomepageReportServiceImpl implements IBytedanceHomepageRep
         //小月份数据
         List<JSONObject> beforeDetail = bytedanceHomepageMapper.queryDetailGroupDayByMonth(smallDate);
 
-        return this.getCompareDate(beforeDetail,afterDetail,"day");
+        return LinkUtils.getCompareDate(beforeDetail,afterDetail,"day");
     }
 
     //今天昨天数据对比
     private List<JSONObject> getCompareGroupByHour(String nowDate, String anotherDay) {
         List<JSONObject> afterDetail = bytedanceHomepageMapper.queryTodayDetailReportBy(nowDate);
         List<JSONObject> beforeDetail = bytedanceHomepageMapper.queryTodayDetailReportBy(anotherDay);
-        return this.getCompareDate(beforeDetail, afterDetail, "statHour");
-    }
-
-    //数据对比,环比计算
-    private List<JSONObject> getCompareDate(List<JSONObject> beforeData, List<JSONObject> AfterData, String standard) {
-        List<JSONObject> result = new ArrayList<>();
-        beforeData.forEach(before -> {
-            String yesStat = String.valueOf(before.get(standard));
-            AfterData.forEach(after -> {
-                if ((String.valueOf(after.get(standard))).equals(yesStat)) {
-                    //消耗较昨日环比
-                    after.put("costProportion", countLink(after.getBigDecimal("cost"), before.getBigDecimal("cost")));
-                    //展示量较昨日环比
-                    after.put("showProportion", countLink(BigDecimal.valueOf(after.getLong("showNum")), BigDecimal.valueOf(before.getLong("showNum"))));
-                    //点击量较昨日环比
-                    after.put("photoClickProportion", countLink(BigDecimal.valueOf(after.getLong("click")), BigDecimal.valueOf(before.getLong("click"))));
-                    before.put("afterData", after);
-                }
-            });
-            result.add(before);
-        });
-        return result;
-    }
-
-    //环比计算
-    private BigDecimal countLink(BigDecimal numA, BigDecimal numB) {
-        BigDecimal link = new BigDecimal(0);
-        if (!BigDecimal.ZERO.equals(numB)) {
-            link = (numA.subtract(numB)).divide(numB, 4, RoundingMode.HALF_UP);
-        }
-        return link;
+        return LinkUtils.getCompareDate(beforeDetail, afterDetail, "statHour");
     }
 
 }

+ 49 - 0
module-toutiao/src/main/java/cn/com/ctop/toutiao/modules/report/utils/LinkUtils.java

@@ -0,0 +1,49 @@
+package cn.com.ctop.toutiao.modules.utils;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *  Created by JQ.bi on 2020.6.5
+ */
+public class LinkUtils {
+
+
+    //数据对比,环比计算
+    public static List<JSONObject> getCompareDate(List<JSONObject> beforeData, List<JSONObject> AfterData, String standard) {
+        List<JSONObject> result = new ArrayList<>();
+        beforeData.forEach(before -> {
+            String yesStat = String.valueOf(before.get(standard));
+            AfterData.forEach(after -> {
+                if ((String.valueOf(after.get(standard))).equals(yesStat)) {
+                    //消耗较昨日环比
+                    after.put("costProportion", countLink(after.getBigDecimal("cost"), before.getBigDecimal("cost")));
+                    //展示量较昨日环比
+                    after.put("showProportion", countLink(BigDecimal.valueOf(after.getLong("showNum")), BigDecimal.valueOf(before.getLong("showNum"))));
+                    //点击量较昨日环比
+                    after.put("photoClickProportion", countLink(BigDecimal.valueOf(after.getLong("click")), BigDecimal.valueOf(before.getLong("click"))));
+                    if(after.getLong("convertNum")!=null){
+                        after.put("convertNumProportion", countLink(BigDecimal.valueOf(after.getLong("convertNum")), BigDecimal.valueOf(before.getLong("convertNum"))));
+                    }
+                    before.put("afterData", after);
+                }
+            });
+            result.add(before);
+        });
+        return result;
+    }
+
+    //环比计算
+    public static BigDecimal countLink(BigDecimal numA, BigDecimal numB) {
+        BigDecimal link = new BigDecimal(0);
+        if (!(numB.compareTo(BigDecimal.ZERO)==0)) {
+            link = (numA.subtract(numB)).divide(numB, 4, RoundingMode.HALF_UP);
+        }
+        return link;
+    }
+
+}

+ 138 - 0
module-toutiao/src/main/resources/json_template/bytedance_filed_mapping.json

@@ -0,0 +1,138 @@
+{
+  "cost": {
+    "filed": "sum(t1.cost) as cost ",
+    "comment": "消耗"
+  },
+  "showMaterial": {
+    "filed": "sum(t1.show_num) as showMaterial ",
+    "comment": "展示数"
+  },
+  "cpm": {
+    "filed": "CASE WHEN sum(t1.cost) / sum(t1.show_num) IS NULL THEN 0 ELSE ROUND((sum(t1.cost) / sum(t1.show_num)) * 1000, 2 ) END AS cpm ",
+    "comment": "平均千次展现费用"
+  },
+  "clickMaterial": {
+    "filed": "sum(t1.click) as clickMaterial ",
+    "comment": "点击数"
+  },
+  "ctr": {
+    "filed": "CASE WHEN sum(t1.click) / sum(t1.show_num) IS NULL THEN 0 ELSE CONCAT( ROUND((sum(t1.click) / sum(t1.show_num)) * 100,2),'%') END AS ctr ",
+    "comment": "点击率"
+  },
+  "cpc": {
+    "filed": "CASE WHEN sum(t1.click) / sum(t1.cost) IS NULL THEN 0 ELSE ROUND((sum(t1.cost) / sum(t1.click)), 2) END AS cpc ",
+    "comment": "平均点击单价"
+  },
+  "convertMaterial": {
+    "filed": "sum(t1.convert_num) as convertMaterial ",
+    "comment": "转化数"
+  },
+  "convertRate": {
+    "filed": "CASE WHEN sum(t1.convert_num) / sum(t1.cost) IS NULL THEN 0 ELSE concat(round(sum(t1.convert_num) / sum(t1.cost)*100,2),'%') end AS convertRate ",
+    "comment": "转化率"
+  },
+  "downloadStart": {
+    "filed": "sum(download_start) as downloadStart ",
+    "comment": "安卓开始下载数"
+  },
+  "downloadStartCost": {
+    "filed": "CASE WHEN sum(t1.cost) / (t1.download_start) IS NULL THEN 0 ELSE sum(t1.cost) / sum(t1.download_start) end AS downloadStartCost ",
+    "comment": "安卓开始下载成本"
+  },
+  "downloadStartRate": {
+    "filed": "CASE WHEN sum(t1.download_start) / sum(t1.click) IS NULL THEN 0 ELSE concat(round(sum(t1.download_start) / sum(t1.click)*100,2),'%') end AS downloadStartRate ",
+    "comment": "安卓开始下载率"
+  },
+  "downloadFinish": {
+    "filed": "sum(download_finish) as downloadFinish ",
+    "comment": "安卓下载完成数"
+  },
+  "downloadFinishCost": {
+    "filed": "CASE WHEN sum(t1.cost) / sum(t1.download_finish) IS NULL THEN 0 ELSE  sum(t1.cost) / sum(t1.download_finish) end AS downloadFinishCost ",
+    "comment": "安卓下载完成成本"
+  },
+  "downloadFinishRate": {
+    "filed": "CASE WHEN sum(t1.install_finish) / sum(t1.download_finish) IS NULL THEN 0 ELSE  concat(round(sum(t1.install_finish) / sum(t1.download_finish)*100,2),'%') end AS downloadFinishRate ",
+    "comment": "安卓下载完成率"
+  },
+  "active": {
+    "filed": "sum(active) as active ",
+    "comment": "激活数"
+  },
+  "activeCost": {
+    "filed": "CASE WHEN sum(t1.cost) / sum(t1.active) IS NULL THEN 0 ELSE sum(t1.cost) / sum(t1.active) end AS activeCost ",
+    "comment": "激活成本"
+  },
+  "activeRate": {
+    "filed": "CASE WHEN sum(t1.active) / sum(t1.click) IS NULL THEN 0 ELSE concat(round(sum(t1.active) / sum(t1.click)*100,2),'%') end as activeRate ",
+    "comment": "激活率"
+  },
+  "register": {
+    "filed": "sum(t1.register) as register  ",
+    "comment": "注册数"
+  },
+  "activeRegisterCost": {
+    "filed": "CASE WHEN sum(t1.cost) / sum(t1.register) IS NULL THEN 0 ELSE round(sum(t1.cost)/sum(t1.register),3) end as activeRegisterCost ",
+    "comment": "注册成本"
+  },
+  "activeRegisterRate": {
+    "filed": " CASE WHEN sum(t1.register) / sum(t1.active) IS NULL THEN 0 ELSE concat(round(sum(t1.register) / sum(t1.active)*100,2),'%') end as activeRegisterRate ",
+    "comment": "注册率"
+  },
+  "nextDayOpen": {
+    "filed": "sum(t1.next_day_open) as nextDayOpen ",
+    "comment": "次留数"
+  },
+  "nextDayOpenCost": {
+    "filed": "CASE WHEN sum(t1.cost) / sum(t1.next_day_open) IS NULL THEN 0 ELSE round(sum(t1.cost)/sum(t1.next_day_open),3) end as nextDayOpenCost ",
+    "comment": "次留成本"
+  },
+  "nextDayOpenRate": {
+    "filed": "CASE WHEN sum(t1.next_day_open) / sum(t1.active) IS NULL THEN 0 ELSE concat(round(sum(t1.next_day_open) / sum(t1.active)*100,2),'%') end as nextDayOpenRate ",
+    "comment": "次留率"
+  },
+  "activePayAmount": {
+    "filed": "sum(pay_count) as activePayAmount ",
+    "comment": "付费数"
+  },
+  "activePayCost": {
+    "filed": "CASE WHEN sum(t1.cost) / sum(t1.pay_count) IS NULL THEN 0 ELSE round(sum(t1.cost)/sum(t1.pay_count),3) end as activePayCost ",
+    "comment": "付费成本"
+  },
+  "form": {
+    "filed": "sum(t1.form) as form ",
+    "comment": "表单提交"
+  },
+  "validPlayCost": {
+    "filed": "CASE WHEN sum(t1.cost) / sum(t1.valid_play) IS NULL THEN 0 ELSE round(sum(t1.cost)/sum(t1.valid_play),3) end as validPlayCost ",
+    "comment": "有效播放成本"
+  },
+  "play25FeedBreak": {
+    "filed": "sum(t1.play25_feed_break) as play25FeedBreak ",
+    "comment": "25%进度播放数"
+  },
+  "play50FeedBreak": {
+    "filed": "sum(t1.play50_feed_break) as play50FeedBreak",
+    "comment": "50%进度播放数"
+  },
+  "play75FeedBreak": {
+    "filed": "sum(t1.play75_feed_break) as play75FeedBreak",
+    "comment": "75%进度播放数"
+  },
+  "play100FeedBreak": {
+    "filed": "sum(t1.play100_feed_break) as play100FeedBreak",
+    "comment": "100%进度播放数"
+  },
+  "follow": {
+    "filed": "sum(t1.follow) as follow ",
+    "comment": "新增关注数"
+  },
+  "likeMaterial": {
+    "filed": "sum(t1.like_num) as likeMaterial ",
+    "comment": "点赞数"
+  },
+  "shareMaterial": {
+    "filed": "sum(t1.share) as shareMaterial ",
+    "comment": "分享数"
+  }
+}