Explorar o código

磁力金牛 初版1

zhaoxian %!s(int64=2) %!d(string=hai) anos
pai
achega
05b1b7fefd
Modificáronse 20 ficheiros con 2518 adicións e 1 borrados
  1. 14 0
      ruixuan-common/src/main/java/com/ruixuan/common/utils/http/HttpUtils.java
  2. 1 0
      ruixuan-framework/src/main/java/com/ruixuan/framework/config/SecurityConfig.java
  3. 10 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/controller/KuaishouProjectController.java
  4. 2 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/mapper/KuaishouAccountMapper.java
  5. 5 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/mapper/KuaishouProjectMapper.java
  6. 2 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/IKuaishouAccountService.java
  7. 2 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/IKuaishouProjectService.java
  8. 5 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/impl/KuaishouAccountServiceImpl.java
  9. 26 1
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/impl/KuaishouProjectServiceImpl.java
  10. 157 0
      ruixuan-live/src/main/java/com/ruixuan/report/controller/KuaishouLiveAccountReportController.java
  11. 629 0
      ruixuan-live/src/main/java/com/ruixuan/report/entity/KuaishouLiveAccountReport.java
  12. 73 0
      ruixuan-live/src/main/java/com/ruixuan/report/mapper/KuaishouLiveAccountReportMapper.java
  13. 36 0
      ruixuan-live/src/main/java/com/ruixuan/report/service/IKuaishouLiveAccountReportService.java
  14. 390 0
      ruixuan-live/src/main/java/com/ruixuan/report/service/impl/KuaishouLiveAccountReportServiceImpl.java
  15. 295 0
      ruixuan-live/src/main/java/com/ruixuan/report/utils/AccountReportConstants.java
  16. 122 0
      ruixuan-live/src/main/java/com/ruixuan/report/utils/JsonResourceUtil.java
  17. 19 0
      ruixuan-live/src/main/java/com/ruixuan/report/utils/ListPageUtil.java
  18. 8 0
      ruixuan-live/src/main/resources/mapper/jinniu/KuaishouAccountMapper.xml
  19. 38 0
      ruixuan-live/src/main/resources/mapper/jinniu/KuaishouProjectMapper.xml
  20. 684 0
      ruixuan-live/src/main/resources/mapper/report/KuaishouLiveAccountReportMapper.xml

+ 14 - 0
ruixuan-common/src/main/java/com/ruixuan/common/utils/http/HttpUtils.java

@@ -17,6 +17,7 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
+import javax.servlet.http.HttpServletResponse;
 
 import com.ruixuan.common.constant.Constants;
 import org.slf4j.Logger;
@@ -273,7 +274,20 @@ public class HttpUtils
         }
     }
 
+    //发送响应流方法
+    public static void setResponseHeader(HttpServletResponse response, String fileName) {
+        try {
+            fileName = new String(fileName.getBytes(), StandardCharsets.UTF_8);
+            //response.setContentType("application/octet-stream;charset=ISO8859-1");
+            response.setContentType("application/vnd.ms-excel;charset=gb2312");
 
+            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
+            response.addHeader("Pargam", "no-cache");
+            response.addHeader("Cache-Control", "no-cache");
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
 
 
 }

+ 1 - 0
ruixuan-framework/src/main/java/com/ruixuan/framework/config/SecurityConfig.java

@@ -125,6 +125,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/kuaishou/promoter/*").permitAll()
                 .antMatchers("/kuaishou/**").permitAll()
                 .antMatchers("/agent/account/**").permitAll()
+                .antMatchers("/report/**").permitAll()
 
                 // 除上面外的所有请求全部需要鉴权认证
                 .anyRequest().authenticated()

+ 10 - 0
ruixuan-live/src/main/java/com/ruixuan/jinniu/controller/KuaishouProjectController.java

@@ -130,4 +130,14 @@ public class KuaishouProjectController extends BaseController {
                                              @ApiParam("成员Id") @RequestParam(value = "userId", required = true) Long userId) {
         return kuaishouProjectMemberService.deleteProjectUsers(projectId, userId);
     }
+
+    /**
+     * 项目&账户树形关系数据
+     */
+    @ApiOperation(value = "项目&账户树形关系数据")
+    @GetMapping("/getProjectAndAccountByUserId")
+    public Result<Object> getProjectAndAccountByUserId(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId,
+                                                       @ApiParam("mediaCode") @RequestParam(value = "mediaCode", required = false) String mediaCode) {
+        return KuaishouProjectService.getProjectAndAccountByUserId(userId, mediaCode);
+    }
 }

+ 2 - 0
ruixuan-live/src/main/java/com/ruixuan/jinniu/mapper/KuaishouAccountMapper.java

@@ -70,4 +70,6 @@ public interface KuaishouAccountMapper {
     List<KuaishouAccount> getAccountByProjectId(@Param("projectId") Long projectId);
 
     void insertRecord(JSONObject o);
+
+    List<JSONObject> getAccountNameByProjectId(@Param("projectId") Long projectId);
 }

+ 5 - 0
ruixuan-live/src/main/java/com/ruixuan/jinniu/mapper/KuaishouProjectMapper.java

@@ -2,6 +2,7 @@ package com.ruixuan.jinniu.mapper;
 
 import com.alibaba.fastjson.JSONObject;
 import com.ruixuan.jinniu.entity.KuaishouProject;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -55,4 +56,8 @@ public interface KuaishouProjectMapper {
     List<JSONObject> getOcpxActionType();
 
     List<KuaishouProject> getMyProjects(KuaishouProject kuaishouProject);
+
+    List<Long> getMyProjectIdsByUserIds(@Param("userList") List<Long> userList);
+
+    List<JSONObject> getProjectsByMedia(@Param("userList") List<Long> userList, @Param("mediaCode") String mediaCode);
 }

+ 2 - 0
ruixuan-live/src/main/java/com/ruixuan/jinniu/service/IKuaishouAccountService.java

@@ -61,4 +61,6 @@ public interface IKuaishouAccountService {
     Result<Object> deleteClaimAccount(Long accountId, Long userId);
 
     Result<Object> edit(KuaishouAccount kuaishouAccount);
+
+    List<JSONObject> getAccountNameByProjectId(Long projectId);
 }

+ 2 - 0
ruixuan-live/src/main/java/com/ruixuan/jinniu/service/IKuaishouProjectService.java

@@ -56,4 +56,6 @@ public interface IKuaishouProjectService {
     Result<Object> getOcpxActionType();
 
     List<KuaishouProject> getMyProjects(KuaishouProject kuaishouProject);
+
+    Result<Object> getProjectAndAccountByUserId(Long userId, String mediaCode);
 }

+ 5 - 0
ruixuan-live/src/main/java/com/ruixuan/jinniu/service/impl/KuaishouAccountServiceImpl.java

@@ -171,6 +171,11 @@ public class KuaishouAccountServiceImpl implements IKuaishouAccountService {
         return Result.success();
     }
 
+    @Override
+    public List<JSONObject> getAccountNameByProjectId(Long projectId) {
+        return kuaishouAccountMapper.getAccountNameByProjectId(projectId);
+    }
+
     private void insertAccountRecord(KuaishouAccount account, Long userId, int type) {
         JSONObject o = new JSONObject();
         o.put("accountId", account.getAccountId());

+ 26 - 1
ruixuan-live/src/main/java/com/ruixuan/jinniu/service/impl/KuaishouProjectServiceImpl.java

@@ -162,7 +162,32 @@ public class KuaishouProjectServiceImpl implements IKuaishouProjectService {
 
     @Override
     public List<KuaishouProject> getMyProjects(KuaishouProject kuaishouProject) {
-
         return projectMapper.getMyProjects(kuaishouProject);
     }
+
+    @Override
+    public Result<Object> getProjectAndAccountByUserId(Long userId, String mediaCode) {
+        String roleKey = sysUserService.getRoleKeyByUserId(userId);
+        List<Long> userList;
+        if ("admin".equals(roleKey) || "directorOperations".equals(roleKey)) {
+            userList = null;
+            if ("admin".equals(roleKey)) {
+                mediaCode = null;
+            }
+        } else if ("operationsManager".equals(roleKey)) {
+            //运营经理 可以看自己部门所有人的(自己和下属的)
+            Long deptId = deptService.getDeptIdByUserId(userId);
+            userList = deptService.getDeptUserListByDeptId(deptId);
+        } else {
+            userList = Arrays.asList(userId);
+        }
+        //查询项目
+        List<JSONObject> projectList = projectMapper.getProjectsByMedia(userList, mediaCode);
+        for (JSONObject object : projectList) {
+            Long projectId = object.getLong("projectId");
+            object.put("accountList", kuaishouAccountService.getAccountNameByProjectId(projectId));
+        }
+        return Result.success(projectList);
+    }
+
 }

+ 157 - 0
ruixuan-live/src/main/java/com/ruixuan/report/controller/KuaishouLiveAccountReportController.java

@@ -0,0 +1,157 @@
+package com.ruixuan.report.controller;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.ruixuan.common.core.controller.BaseController;
+import com.ruixuan.common.core.page.TableDataInfo;
+import com.ruixuan.common.utils.Result;
+import com.ruixuan.common.utils.http.HttpUtils;
+import com.ruixuan.data.utils.ExportExcelUtils;
+import com.ruixuan.report.service.IKuaishouLiveAccountReportService;
+import com.ruixuan.report.utils.AccountReportConstants;
+import com.ruixuan.report.utils.JsonResourceUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+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.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Controller
+ *
+ * @author ruoyi
+ * @date 2023-03-22
+ */
+@Api(tags = "------账户报表")
+@Slf4j
+@RestController
+@RequestMapping("/report/account")
+public class KuaishouLiveAccountReportController extends BaseController {
+    @Autowired
+    private IKuaishouLiveAccountReportService KuaishouLiveAccountReportService;
+
+    @ApiOperation(value = "今日数据题头")
+    @GetMapping("/operateHomePageHead")
+    public Result operateHomePageHead(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId) {
+        JSONObject result = KuaishouLiveAccountReportService.operateHomePageHead(userId);
+        return Result.success(result);
+    }
+
+    @ApiOperation(value = "项目维度数据")
+    @GetMapping("/getProjectCostList")
+    public Result getProjectCostList(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId,
+                                     @ApiParam("startDate") @RequestParam(value = "startDate", required = true) String startDate,
+                                     @ApiParam("endDate") @RequestParam(value = "endDate", required = true) String endDate) {
+        List<JSONObject> result = KuaishouLiveAccountReportService.getProjectCostList(userId, startDate, endDate);
+        return Result.success(result);
+    }
+
+    @ApiOperation(value = "运营组维度数据")
+    @GetMapping("/getOperationsGroupCostList")
+    public Result getOperationsGroupCostList(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId,
+                                             @ApiParam("startDate") @RequestParam(value = "startDate", required = true) String startDate,
+                                             @ApiParam("endDate") @RequestParam(value = "endDate", required = true) String endDate,
+                                             @ApiParam("pageNum") @RequestParam(value = "pageNum", required = false) Integer pageNum,
+                                             @ApiParam("pageSize") @RequestParam(value = "pageSize", required = false) Integer pageSize) {
+        return KuaishouLiveAccountReportService.getOperationsGroupCostList(userId, startDate, endDate, pageNum, pageSize);
+    }
+
+    @ApiOperation(value = "运营数据")
+    @GetMapping("/getOperateCostList")
+    public Result getOperateCostList(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId,
+                                     @ApiParam("startDate") @RequestParam(value = "startDate", required = true) String startDate,
+                                     @ApiParam("endDate") @RequestParam(value = "endDate", required = true) String endDate) {
+        List<JSONObject> result = KuaishouLiveAccountReportService.getOperateCostList(userId, startDate, endDate);
+        return Result.success(result);
+    }
+
+    @ApiOperation(value = "运营数据趋势图")
+    @GetMapping("/getOperateCostTrendChartList")
+    public Result getOperateCostTrendChartList(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId,
+                                               @ApiParam("startDate") @RequestParam(value = "startDate", required = true) String startDate,
+                                               @ApiParam("endDate") @RequestParam(value = "endDate", required = true) String endDate) {
+        JSONObject result = KuaishouLiveAccountReportService.getOperateCostTrendChartList(userId, startDate, endDate);
+        return Result.success(result);
+
+    }
+
+    @ApiOperation(value = "获取统计报表题头")
+    @PostMapping("/getStatisticalReportHead")
+    public Result getStatisticalReportHead(@RequestBody JSONObject request) {
+        JSONObject result = KuaishouLiveAccountReportService.getStatisticalReportHead(request);
+        return Result.success(result);
+    }
+
+    @ApiOperation(value = "访问量统计趋势图")
+    @PostMapping("/getvisitorStatisticsTrendChartList")
+    public Result getvisitorStatisticsTrendChartList(@RequestBody JSONObject request) {
+        List<JSONObject> result = KuaishouLiveAccountReportService.getvisitorStatisticsTrendChartList(request);
+        return Result.success(result);
+    }
+
+    @ApiOperation(value = "趋势图节点账户消耗")
+    @PostMapping("/nodeAccountCost")
+    public Result nodeAccountCost(@RequestBody JSONObject request) {
+        List<JSONObject> result = KuaishouLiveAccountReportService.nodeAccountCost(request);
+        return Result.success(result);
+    }
+
+
+    @ApiOperation(value = "账户数据报表")
+    @PostMapping("/getAccountDataReport")
+    public TableDataInfo getAccountDataReport(@RequestBody JSONObject request) {
+        List<JSONObject> list = KuaishouLiveAccountReportService.getAccountDataReport(request);
+        return getDataTable(list);
+    }
+
+    @ApiOperation(value = "导出账户数据报表")
+    @PostMapping("/exportAccountDataReport")
+    public void exportAccountDataReport(@RequestBody JSONObject request, HttpServletResponse response) {
+        JSONArray columns = request.getJSONArray("columns");
+        if (columns.isEmpty()) {
+            log.error("请选择需要导出的字段");
+            return;
+        }
+        List<String> titles = new ArrayList<>();
+        titles.add("时间");
+        titles.addAll(JsonResourceUtil.joinTitle(AccountReportConstants.getKuaishouAccountReport(), columns));
+
+        //此处增加一个元素是为了保证数据有序
+        columns.add(0, "time");
+        List<JSONObject> list = KuaishouLiveAccountReportService.exportAccountDataReport(request);
+
+        List<List<Object>> excelList = new ArrayList<>();
+        list.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) {
+            e.printStackTrace();
+        }
+    }
+}

+ 629 - 0
ruixuan-live/src/main/java/com/ruixuan/report/entity/KuaishouLiveAccountReport.java

@@ -0,0 +1,629 @@
+package com.ruixuan.report.entity;
+
+
+import com.ruixuan.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 对象 kuaishou_live_account_report_daily_dw
+ *
+ * @author ruoyi
+ * @date 2023-03-22
+ */
+@Data
+@ApiModel(value = "kuaishou_live_account_report_daily_dw", description = "广告账户报表")
+public class KuaishouLiveAccountReport extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 账户ID
+     */
+    private Long accountId;
+
+    /**
+     * 账户名称
+     */
+    @ApiModelProperty(name = "账户名称")
+    private String accountName;
+
+    /**
+     * 项目ID
+     */
+    @ApiModelProperty(name = "项目ID")
+    private Long projectId;
+
+    /**
+     * 项目名称
+     */
+    @ApiModelProperty(name = "项目名称")
+    private String projectName;
+
+    /**
+     * 时间分区
+     */
+    private Long reportDate;
+
+    /**
+     * 时间分区
+     */
+    private Integer hour;
+
+    /**
+     * 快手ID
+     */
+    @ApiModelProperty(name = "快手ID")
+    private Long ksId;
+
+    /**
+     * 快手昵称
+     */
+    @ApiModelProperty(name = "快手昵称")
+    private String ksName;
+
+    /**
+     * 账户类型 自运营,代运营
+     */
+    @ApiModelProperty(name = "账户类型 自运营,代运营")
+    private Long accountType;
+
+    /**
+     * 运营ID
+     */
+    @ApiModelProperty(name = "运营ID")
+    private String userId;
+
+    /**
+     * 运营名称
+     */
+    @ApiModelProperty(name = "运营名称")
+    private String userName;
+
+    /**
+     * 运营负责人
+     */
+    @ApiModelProperty(name = "运营负责人")
+    private String leadName;
+
+    /**
+     * 项目负责人ID
+     */
+    @ApiModelProperty(name = "项目负责人ID")
+    private String proUserId;
+
+    /**
+     * 项目负责人名称
+     */
+    @ApiModelProperty(name = "项目负责人名称")
+    private String proUserName;
+
+    /**
+     * 销售ID
+     */
+    @ApiModelProperty(name = "销售ID")
+    private String saleId;
+
+    /**
+     * 销售名称
+     */
+    @ApiModelProperty(name = "销售名称")
+    private String saleName;
+
+    /**
+     * 花费
+     */
+    @ApiModelProperty(name = "花费")
+    private BigDecimal costTotal;
+
+    /**
+     * 曝光数
+     */
+    @ApiModelProperty(name = "曝光数")
+    private Long adShow;
+
+    /**
+     * 平均千次广告曝光花费
+     */
+    @ApiModelProperty(name = "平均千次广告曝光花费")
+    private BigDecimal adShow1kCost;
+
+    /**
+     * 封面曝光数
+     */
+    @ApiModelProperty(name = "封面曝光数")
+    private Long impression;
+
+    /**
+     * 封面点击数
+     */
+    @ApiModelProperty(name = "封面点击数")
+    private Long photoClick;
+
+    /**
+     * 封面点击率
+     */
+    @ApiModelProperty(name = "封面点击率")
+    private BigDecimal photoClickRatio;
+
+    /**
+     * 素材曝光数
+     */
+    @ApiModelProperty(name = "素材曝光数")
+    private Long click;
+
+    /**
+     * 行为数
+     */
+    @ApiModelProperty(name = "行为数")
+    private Long actionbarClick;
+
+    /**
+     * 行为成本
+     */
+    @ApiModelProperty(name = "行为成本")
+    private BigDecimal actionbarClickCost;
+
+    /**
+     * 行为率
+     */
+    @ApiModelProperty(name = "行为率")
+    private BigDecimal espClickRatio;
+
+    /**
+     * 素材点击率
+     */
+    @ApiModelProperty(name = "素材点击率")
+    private BigDecimal actionRatio;
+
+    /**
+     * 组件点击数
+     */
+    @ApiModelProperty(name = "组件点击数")
+    private Long adItemClickCount;
+
+    /**
+     * 直播平均观看时长
+     */
+    @ApiModelProperty(name = "直播平均观看时长")
+    private Long espLivePlayedSeconds;
+
+    /**
+     * 作品3秒播放数
+     */
+    @ApiModelProperty(name = "作品3秒播放数")
+    private Long playedThreeSeconds;
+
+    /**
+     * 作品3秒播放率
+     */
+    @ApiModelProperty(name = "作品3秒播放率")
+    private BigDecimal play3sRatio;
+
+    /**
+     * 作品5秒播放数
+     */
+    @ApiModelProperty(name = "作品5秒播放数")
+    private Long playedFiveSeconds;
+
+    /**
+     * 作品5秒播放率
+     */
+    @ApiModelProperty(name = "作品5秒播放率")
+    private BigDecimal play5sRatio;
+
+    /**
+     * 作品完播数
+     */
+    @ApiModelProperty(name = "作品完播数")
+    private Long playedEnd;
+
+    /**
+     * 作品完播率
+     */
+    @ApiModelProperty(name = "作品完播率")
+    private BigDecimal playEndRatio;
+
+    /**
+     * 作品分享数
+     */
+    @ApiModelProperty(name = "作品分享数")
+    private Long share;
+
+    /**
+     * 作品评论数
+     */
+    @ApiModelProperty(name = "作品评论数")
+    private Long comment;
+
+    /**
+     * 作品点赞数
+     */
+    @ApiModelProperty(name = "作品点赞数")
+    private Long likes;
+
+    /**
+     * 作品举报数
+     */
+    @ApiModelProperty(name = "作品举报数")
+    private Long report;
+
+    /**
+     * 作品拉黑数
+     */
+    @ApiModelProperty(name = "作品拉黑数")
+    private Long block;
+
+    /**
+     * 详情页减少此类作品数
+     */
+    @ApiModelProperty(name = "详情页减少此类作品数")
+    private Long itemNegative;
+
+    /**
+     * 直播间分享数
+     */
+    @ApiModelProperty(name = "直播间分享数")
+    private Long liveShare;
+
+    /**
+     * 直播间评论数
+     */
+    @ApiModelProperty(name = "直播间评论数")
+    private Long liveComment;
+
+    /**
+     * 直播间送礼数
+     */
+    @ApiModelProperty(name = "直播间送礼数")
+    private Long liveReward;
+
+    /**
+     * 有效播放数
+     */
+    @ApiModelProperty(name = "有效播放数")
+    private Long effectivePlayCount;
+
+    /**
+     * 有效播放率
+     */
+    @ApiModelProperty(name = "有效播放率")
+    private BigDecimal effectivePlayRatio;
+
+    /**
+     * 直播间停留1min
+     */
+    @ApiModelProperty(name = "直播间停留1min")
+    private Long adLivePlayed1mNum;
+
+    /**
+     * 转化数
+     */
+    @ApiModelProperty(name = "转化数")
+    private Long conversionNum;
+
+    /**
+     * 转化成本
+     */
+    @ApiModelProperty(name = "转化成本")
+    private BigDecimal conversionCostEsp;
+
+    /**
+     * 直接GMV
+     */
+    @ApiModelProperty(name = "直接GMV")
+    private BigDecimal gmv;
+
+    /**
+     * 当日累计GMV
+     */
+    @ApiModelProperty(name = "当日累计GMV")
+    private BigDecimal t0Gmv;
+
+    /**
+     * 次日累计GMV
+     */
+    @ApiModelProperty(name = "次日累计GMV")
+    private BigDecimal t1Gmv;
+
+    /**
+     * 7日累计GMV
+     */
+    @ApiModelProperty(name = "7日累计GMV")
+    private BigDecimal t7Gmv;
+
+    /**
+     * 15日累计GMV
+     */
+    @ApiModelProperty(name = "15日累计GMV")
+    private BigDecimal t15Gmv;
+
+    /**
+     * 30日累计GMV
+     */
+    @ApiModelProperty(name = "30日累计GMV")
+    private BigDecimal t30Gmv;
+
+    /**
+     * 直接ROI
+     */
+    @ApiModelProperty(name = "直接ROI")
+    private BigDecimal roi;
+
+    /**
+     * 当日累计ROI
+     */
+    @ApiModelProperty(name = "当日累计ROI")
+    private BigDecimal t0Roi;
+
+    /**
+     * 次日累计ROI
+     */
+    @ApiModelProperty(name = "次日累计ROI")
+    private BigDecimal t1Roi;
+
+    /**
+     * 7日累计ROI
+     */
+    @ApiModelProperty(name = "7日累计ROI")
+    private BigDecimal t7Roi;
+
+    /**
+     * 15日累计ROI
+     */
+    @ApiModelProperty(name = "15日累计ROI")
+    private BigDecimal t15Roi;
+
+    /**
+     * 30日累计ROI
+     */
+    @ApiModelProperty(name = "30日累计ROI")
+    private BigDecimal t30Roi;
+
+    /**
+     * 直接订单数
+     */
+    @ApiModelProperty(name = "直接订单数")
+    private Long paiedOrder;
+
+    /**
+     * 直接下单率
+     */
+    @ApiModelProperty(name = "直接下单率")
+    private BigDecimal orderRatio;
+
+    /**
+     * 当日累计订单数
+     */
+    @ApiModelProperty(name = "当日累计订单数")
+    private Long t0OrderCnt;
+
+    /**
+     * 当日累计订单成本
+     */
+    @ApiModelProperty(name = "当日累计订单成本")
+    private BigDecimal t0OrderCntCost;
+
+    /**
+     * 累计订单下单率
+     */
+    @ApiModelProperty(name = "累计订单下单率")
+    private BigDecimal t0OrderCntRatio;
+
+    /**
+     * 次日累计订单数
+     */
+    @ApiModelProperty(name = "次日累计订单数")
+    private Long t1OrderCnt;
+
+    /**
+     * 7日累计订单数
+     */
+    @ApiModelProperty(name = "7日累计订单数")
+    private Long t7OrderCnt;
+
+    /**
+     * 15日累计订单数
+     */
+    @ApiModelProperty(name = "15日累计订单数")
+    private Long t15OrderCnt;
+
+    /**
+     * 30日累计订单数
+     */
+    @ApiModelProperty(name = "30日累计订单数")
+    private Long t30OrderCnt;
+
+    /**
+     * 涨粉数
+     */
+    @ApiModelProperty(name = "涨粉数")
+    private Long merchantRecoFans;
+
+    /**
+     * 次日涨粉留存数
+     */
+    @ApiModelProperty(name = "次日涨粉留存数")
+    private Long t1Retention;
+
+    /**
+     * 7日涨粉留存数
+     */
+    @ApiModelProperty(name = "7日涨粉留存数")
+    private Long t7Retention;
+
+    /**
+     * 15日涨粉留存数
+     */
+    @ApiModelProperty(name = "15日涨粉留存数")
+    private Long t15Retention;
+
+    /**
+     * 30日涨粉留存数
+     */
+    @ApiModelProperty(name = "30日涨粉留存数")
+    private Long t30Retention;
+
+    /**
+     * 次日涨粉留存率
+     */
+    @ApiModelProperty(name = "次日涨粉留存率")
+    private BigDecimal t1RetentionRatio;
+
+    /**
+     * 7日涨粉留存率
+     */
+    @ApiModelProperty(name = "7日涨粉留存率")
+    private BigDecimal t7RetentionRatio;
+
+    /**
+     * 15日涨粉留存率
+     */
+    @ApiModelProperty(name = "15日涨粉留存率")
+    private BigDecimal t15RetentionRatio;
+
+    /**
+     * 30日涨粉留存率
+     */
+    @ApiModelProperty(name = "30日涨粉留存率")
+    private BigDecimal t30RetentionRatio;
+
+    /**
+     * 预约成功数
+     */
+    @ApiModelProperty(name = "预约成功数")
+    private Long reservationSuccess;
+
+    /**
+     * 预约成功成本
+     */
+    @ApiModelProperty(name = "预约成功成本")
+    private BigDecimal reservationCost;
+
+    /**
+     * 直播观看数
+     */
+    @ApiModelProperty(name = "直播观看数")
+    private Long standardLivePlayedStarted;
+
+    /**
+     * 直播观看成本
+     */
+    @ApiModelProperty(name = "直播观看成本")
+    private BigDecimal liveAudienceCost;
+
+    /**
+     * 直播间商品点击数
+     */
+    @ApiModelProperty(name = "直播间商品点击数")
+    private Long liveEventGoodsView;
+
+    /**
+     * 直播间商品点击率
+     */
+    @ApiModelProperty(name = "直播间商品点击率")
+    private BigDecimal goodsClickRatio;
+
+    /**
+     * 直接平台新客
+     */
+    @ApiModelProperty(name = "直接平台新客")
+    private Long directAttrPlatNewBuyerCnt;
+
+    /**
+     * 30日累计平台新客
+     */
+    @ApiModelProperty(name = "30日累计平台新客")
+    private Long t30AttrPlatTotalBuyerCnt;
+
+    /**
+     * 直接店铺新客
+     */
+    @ApiModelProperty(name = "直接店铺新客")
+    private Long directAttrSellerNewBuyerCnt;
+
+    /**
+     * 30日累计店铺新客
+     */
+    @ApiModelProperty(name = "30日累计店铺新客")
+    private Long t30AttrSellerTotalBuyerCnt;
+
+    /**
+     * 涨粉当日GMV
+     */
+    @ApiModelProperty(name = "涨粉当日GMV")
+    private BigDecimal fansT0Gmv;
+
+    /**
+     * 涨粉次日GMV
+     */
+    @ApiModelProperty(name = "涨粉次日GMV")
+    private BigDecimal fansT1Gmv;
+
+    /**
+     * 涨粉7日GMV
+     */
+    @ApiModelProperty(name = "涨粉7日GMV")
+    private BigDecimal fansT7Gmv;
+
+    /**
+     * 涨粉15日GMV
+     */
+    @ApiModelProperty(name = "涨粉15日GMV")
+    private BigDecimal fansT15Gmv;
+
+    /**
+     * 涨粉30日GMV
+     */
+    @ApiModelProperty(name = "涨粉30日GMV")
+    private BigDecimal fansT30Gmv;
+
+    /**
+     * 涨粉当日ROI
+     */
+    @ApiModelProperty(name = "涨粉当日ROI")
+    private BigDecimal fansT0Roi;
+
+    /**
+     * 涨粉次日ROI
+     */
+    @ApiModelProperty(name = "涨粉次日ROI")
+    private BigDecimal fansT1Roi;
+
+    /**
+     * 涨粉7日ROI
+     */
+    @ApiModelProperty(name = "涨粉7日ROI")
+    private BigDecimal fansT7Roi;
+
+    /**
+     * 涨粉15日ROI
+     */
+    @ApiModelProperty(name = "涨粉15日ROI")
+    private BigDecimal fansT15Roi;
+
+    /**
+     * 涨粉30日ROI
+     */
+    @ApiModelProperty(name = "涨粉30日ROI")
+    private BigDecimal fansT30Roi;
+
+    /**
+     * $column.columnComment
+     */
+    private BigDecimal orderCost;
+
+    /**
+     * $column.columnComment
+     */
+    private BigDecimal recoFansCost;
+
+    /**
+     * $column.columnComment
+     */
+    private BigDecimal conversionLiveEventGoodsViewCost;
+
+
+}

+ 73 - 0
ruixuan-live/src/main/java/com/ruixuan/report/mapper/KuaishouLiveAccountReportMapper.java

@@ -0,0 +1,73 @@
+package com.ruixuan.report.mapper;
+
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 账户报表Mapper接口
+ *
+ * @author ruoyi
+ * @date 2023-03-22
+ */
+public interface KuaishouLiveAccountReportMapper {
+
+    JSONObject operateHomePageHead(Map<String, Object> map);
+
+    Integer getCustomersNum(Map<String, Object> map);
+
+
+    /*项目维度数据 日报&时报*/
+    List<JSONObject> getProjectCostListByDaily(Map<String, Object> map);
+
+    List<JSONObject> getProjectCostListByHourly(Map<String, Object> map);
+
+
+    /*运营组维度数据 日报&时报 */
+    JSONObject getOperationsGroupCostByHourly(Map<String, Object> map);
+
+    JSONObject getOperationsGroupCostByDaily(Map<String, Object> map);
+
+
+    /*运营数据 日报&时报 */
+    List<JSONObject> getOperateCostListByHourly(Map<String, Object> map);
+
+    List<JSONObject> getOperateCostListByDaily(Map<String, Object> map);
+
+    /*运营数据 汇总查询 日报&时报 */
+    JSONObject getOperateCostTotalByHourly(Map<String, Object> map);
+
+    JSONObject getOperateCostTotalByDaily(Map<String, Object> map);
+
+
+    /*运营数据趋势图 日报&时报 */
+    List<JSONObject> getOperateCostTrendChartListByHourly(Map<String, Object> map);
+
+    List<JSONObject> getOperateCostTrendChartListByDaily(Map<String, Object> map);
+
+
+    /*统计报表 汇总数据 日报&时报*/
+    JSONObject getStatisticalReportHeadByHourly(Map<String, Object> map);
+
+    JSONObject getStatisticalReportHeadByDaily(Map<String, Object> map);
+
+
+    /*访问量统计趋势图 日报&时报 */
+    List<JSONObject> getvisitorStatisticsTrendChartListByHourly(Map<String, Object> map);
+
+    List<JSONObject> getvisitorStatisticsTrendChartListByDaily(Map<String, Object> map);
+
+
+    /*趋势图节点账户消耗 日报&时报 */
+    List<JSONObject> getNodeAccountsCostByHourly(Map<String, Object> map);
+
+    List<JSONObject> getNodeAccountsCostByDaily(Map<String, Object> map);
+
+
+    /*账户数据报表 日报&时报 */
+    List<JSONObject> getAccountDataReportByHourly(Map<String, Object> map);
+
+    List<JSONObject> getAccountDataReportByDaily(Map<String, Object> map);
+}

+ 36 - 0
ruixuan-live/src/main/java/com/ruixuan/report/service/IKuaishouLiveAccountReportService.java

@@ -0,0 +1,36 @@
+package com.ruixuan.report.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.JSONPObject;
+import com.ruixuan.common.utils.Result;
+
+import java.util.List;
+
+/**
+ * 账户报表Service接口
+ *
+ * @author ruoyi
+ * @date 2023-03-22
+ */
+public interface IKuaishouLiveAccountReportService {
+
+    JSONObject operateHomePageHead(Long userId);
+
+    List<JSONObject> getProjectCostList(Long userId, String startDate, String endDate);
+
+    Result getOperationsGroupCostList(Long userId, String startDate, String endDate, Integer pageNum, Integer pageSize);
+
+    List<JSONObject> getOperateCostList(Long userId, String startDate, String endDate);
+
+    JSONObject getOperateCostTrendChartList(Long userId, String startDate, String endDate);
+
+    JSONObject getStatisticalReportHead(JSONObject request);
+
+    List<JSONObject> getvisitorStatisticsTrendChartList(JSONObject request);
+
+    List<JSONObject> nodeAccountCost(JSONObject request);
+
+    List<JSONObject> getAccountDataReport(JSONObject request);
+
+    List<JSONObject> exportAccountDataReport(JSONObject request);
+}

+ 390 - 0
ruixuan-live/src/main/java/com/ruixuan/report/service/impl/KuaishouLiveAccountReportServiceImpl.java

@@ -0,0 +1,390 @@
+package com.ruixuan.report.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ruixuan.common.core.domain.entity.SysUser;
+import com.ruixuan.common.utils.Check;
+import com.ruixuan.common.utils.DateUtils;
+import com.ruixuan.common.utils.PageUtils;
+import com.ruixuan.common.utils.Result;
+import com.ruixuan.jinniu.mapper.KuaishouProjectMapper;
+import com.ruixuan.report.mapper.KuaishouLiveAccountReportMapper;
+import com.ruixuan.report.service.IKuaishouLiveAccountReportService;
+import com.ruixuan.report.utils.AccountReportConstants;
+import com.ruixuan.report.utils.JsonResourceUtil;
+import com.ruixuan.system.service.ISysDeptService;
+import com.ruixuan.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 账户报表Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2023-03-22
+ */
+@Service
+public class KuaishouLiveAccountReportServiceImpl implements IKuaishouLiveAccountReportService {
+    @Autowired
+    private KuaishouLiveAccountReportMapper mapper;
+    @Autowired
+    private ISysUserService sysUserService;
+    @Autowired
+    private KuaishouProjectMapper projectMapper;
+    @Autowired
+    private ISysDeptService deptService;
+
+    @Override
+    public JSONObject operateHomePageHead(Long userId) {
+        String roleKey = sysUserService.getRoleKeyByUserId(userId);
+        List<Long> userList;
+        if ("admin".equals(roleKey) || "directorOperations".equals(roleKey)) {
+            //查看所有
+            userList = null;
+        } else if ("operationsManager".equals(roleKey)) {
+            //运营经理 可以看自己部门所有人的(自己和下属的)
+            Long deptId = deptService.getDeptIdByUserId(userId);
+            userList = deptService.getDeptUserListByDeptId(deptId);
+        } else {
+            userList = Arrays.asList(userId);
+        }
+        //当前小时
+        Integer hour = DateUtils.getNowHour();
+        String yesterday = DateUtils.getSubtractTime(new Date(), 1);
+        String today = DateUtils.getDate();
+        Map<String, Object> map = new HashMap<>();
+        map.put("userList", userList);
+        map.put("hour", hour);
+        map.put("today", today.replace("-", ""));
+        map.put("yesterday", yesterday.replace("-", ""));
+        JSONObject result = mapper.operateHomePageHead(map);
+        result.put("customersNum", mapper.getCustomersNum(map));
+        return result;
+    }
+
+    @Override
+    public List<JSONObject> getProjectCostList(Long userId, String startDate, String endDate) {
+        String roleKey = sysUserService.getRoleKeyByUserId(userId);
+        List<Long> userList;
+        if ("admin".equals(roleKey) || "directorOperations".equals(roleKey)) {
+            //查看所有
+            userList = null;
+        } else if ("operationsManager".equals(roleKey)) {
+            //运营经理 可以看自己部门所有人的(自己和下属的)
+            Long deptId = deptService.getDeptIdByUserId(userId);
+            userList = deptService.getDeptUserListByDeptId(deptId);
+        } else {
+            userList = Arrays.asList(userId);
+        }
+        List<Long> projectIds = null;
+        if (Check.isNotNull(userList)) {
+            //人员参与的项目集
+            projectIds = projectMapper.getMyProjectIdsByUserIds(userList);
+        }
+
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        map.put("projectIds", projectIds);
+
+        String type = map.get("type").toString();
+        if ("hourly".equals(type)) {
+            PageUtils.startPage();
+            return mapper.getProjectCostListByHourly(map);
+        } else {
+            PageUtils.startPage();
+            return mapper.getProjectCostListByDaily(map);
+        }
+    }
+
+    @Override
+    public Result getOperationsGroupCostList(Long userId, String startDate, String endDate, Integer pageNum, Integer pageSize) {
+        String roleKey = sysUserService.getRoleKeyByUserId(userId);
+        List<Long> managerIds;
+        if ("admin".equals(roleKey) || "directorOperations".equals(roleKey)) {
+            //查看所有
+            managerIds = sysUserService.getUserIdByRoleKey("operationsManager");
+        } else if ("operationsManager".equals(roleKey)) {
+            //运营经理 可以看自己部门所有人的(自己和下属的)
+            managerIds = Arrays.asList(userId);
+        } else {
+            return Result.success();
+        }
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        String type = map.get("type").toString();
+        List<JSONObject> list = new ArrayList<>();
+        for (Long managerId : managerIds) {
+            Long deptId = deptService.getDeptIdByUserId(managerId);
+            List<Long> userList = deptService.getDeptUserListByDeptId(deptId);
+            map.put("userList", userList);
+            //人员参与的项目集
+            SysUser sysUser = sysUserService.selectUserById(managerId);
+            map.put("operateNum", userList.size());
+            JSONObject result = new JSONObject();
+            List<Long> projectIds = projectMapper.getMyProjectIdsByUserIds(userList);
+            result.put("userId", managerId);
+            result.put("userName", sysUser.getNickName());
+            result.put("operateNum", userList.size());
+            result.put("projectNum", projectIds.size());
+            JSONObject data = new JSONObject();
+            if ("hourly".equals(type)) {
+                data = mapper.getOperationsGroupCostByHourly(map);
+            } else {
+                data = mapper.getOperationsGroupCostByDaily(map);
+            }
+            result.put("costTotal", data.getBigDecimal("costTotal"));
+            result.put("perCost", data.getBigDecimal("perCost"));
+            result.put("roi", data.getBigDecimal("roi"));
+            result.put("yesCostTotal", data.getBigDecimal("yesCostTotal"));
+            list.add(result);
+        }
+        JSONObject all = new JSONObject();
+        all.put("userName", "汇总");
+        all.put("projectNum", "-");
+        Double operateNum = list.stream().mapToDouble(value -> value.getDouble("operateNum")).reduce(Double::sum).getAsDouble();
+        all.put("operateNum", new BigDecimal(operateNum).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
+        Double costTotal = list.stream().mapToDouble(value -> value.getDouble("costTotal")).reduce(Double::sum).getAsDouble();
+        all.put("costTotal", new BigDecimal(costTotal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
+        Double yesCostTotal = list.stream().mapToDouble(value -> value.getDouble("yesCostTotal")).reduce(Double::sum).getAsDouble();
+        all.put("yesCostTotal", new BigDecimal(yesCostTotal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
+
+        Integer days = (Integer) map.get("days");
+        //人均消耗 总花费/天数/人数
+        Double avePeople = costTotal == 0 ? 0 : costTotal / days / operateNum;
+        all.put("perCost", new BigDecimal(avePeople).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
+        if (Check.isNotNull(yesCostTotal) && new BigDecimal(yesCostTotal).compareTo(new BigDecimal("0")) > 0) {
+            DecimalFormat decimalFormat = new DecimalFormat("0.00%");
+            Double yearOnYearD = (costTotal - yesCostTotal) / yesCostTotal;
+            all.put("roi", new BigDecimal(yearOnYearD).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
+        } else {
+            all.put("roi", "0.0");
+        }
+        list.add(all);
+        return Result.success(list);
+
+    }
+
+    @Override
+    public List<JSONObject> getOperateCostList(Long userId, String startDate, String endDate) {
+        String roleKey = sysUserService.getRoleKeyByUserId(userId);
+        List<Long> userList;
+        if ("admin".equals(roleKey) || "directorOperations".equals(roleKey)) {
+            //查看所有
+            userList = null;
+        } else if ("operationsManager".equals(roleKey)) {
+            //运营经理 可以看自己部门所有人的(自己和下属的)
+            Long deptId = deptService.getDeptIdByUserId(userId);
+            userList = deptService.getDeptUserListByDeptId(deptId);
+        } else {
+            userList = Arrays.asList(userId);
+        }
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        map.put("userList", userList);
+
+        List<JSONObject> result;
+        String type = map.get("type").toString();
+        if ("hourly".equals(type)) {
+//            PageUtils.startPage();
+            result = mapper.getOperateCostListByHourly(map);
+            result.add(mapper.getOperateCostTotalByHourly(map));
+        } else {
+//            PageUtils.startPage();
+            result = mapper.getOperateCostListByDaily(map);
+            result.add(mapper.getOperateCostTotalByDaily(map));
+        }
+        return result;
+    }
+
+    @Override
+    public JSONObject getOperateCostTrendChartList(Long userId, String startDate, String endDate) {
+        String roleKey = sysUserService.getRoleKeyByUserId(userId);
+        List<Long> userList;
+        if ("admin".equals(roleKey) || "directorOperations".equals(roleKey)) {
+            //查看所有
+            userList = null;
+        } else if ("operationsManager".equals(roleKey)) {
+            //运营经理 可以看自己部门所有人的(自己和下属的)
+            Long deptId = deptService.getDeptIdByUserId(userId);
+            userList = deptService.getDeptUserListByDeptId(deptId);
+        } else {
+            userList = Arrays.asList(userId);
+        }
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        map.put("userList", userList);
+
+        JSONObject result = new JSONObject();
+        String type = map.get("type").toString();
+        if (startDate.equals(endDate)) {
+            result.put("todayInfo", mapper.getOperateCostTrendChartListByHourly(map));
+            map.put("today", map.get("yesterday"));
+            result.put("yesterdayInfo", mapper.getOperateCostTrendChartListByHourly(map));
+        } else {
+            List<JSONObject> dailyData = mapper.getOperateCostTrendChartListByDaily(map);
+            List<String> allDates = DateUtils.getAllDatesOfTwoTimes(startDate, endDate);
+            if (Check.isNull(dailyData) || allDates.size() != dailyData.size()) {
+                completeDate(dailyData, allDates);
+            }
+            result.put("info", dailyData);
+        }
+        return result;
+    }
+
+    @Override
+    public JSONObject getStatisticalReportHead(JSONObject request) {
+        //整理入参时间
+        Map<String, Object> map = getDateTime(request.getString("startDate"), request.getString("endDate"));
+        map.put("accountIdList", request.getJSONArray("accountIdList"));
+
+        String type = map.get("type").toString();
+        if ("hourly".equals(type)) {
+            return mapper.getStatisticalReportHeadByHourly(map);
+        } else {
+            return mapper.getStatisticalReportHeadByDaily(map);
+        }
+    }
+
+    @Override
+    public List<JSONObject> getvisitorStatisticsTrendChartList(JSONObject request) {
+        String startDate = request.getString("startDate");
+        String endDate = request.getString("endDate");
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        map.put("accountIdList", request.getJSONArray("accountIdList"));
+        if (startDate.equals(endDate)) {
+            return mapper.getvisitorStatisticsTrendChartListByHourly(map);
+        } else {
+            List<JSONObject> list = mapper.getvisitorStatisticsTrendChartListByDaily(map);
+            List<String> allDates = DateUtils.getAllDatesOfTwoTimes(startDate, endDate);
+            if (Check.isNull(list) || allDates.size() != list.size()) {
+                completeDate(list, allDates);
+            }
+            return list;
+        }
+    }
+
+    @Override
+    public List<JSONObject> nodeAccountCost(JSONObject request) {
+        Integer hour = request.getInteger("hour");
+        Map<String, Object> map = new HashMap<>();
+        map.put("date", request.getString("date").replace("-", ""));
+        map.put("accountIdList", request.getJSONArray("accountIdList"));
+        if (Check.isNotNull(hour)) {
+            map.put("hour", hour);
+            return mapper.getNodeAccountsCostByHourly(map);
+        } else {
+            return mapper.getNodeAccountsCostByDaily(map);
+        }
+    }
+
+    @Override
+    public List<JSONObject> getAccountDataReport(JSONObject request) {
+        String startDate = request.getString("startDate");
+        String endDate = request.getString("endDate");
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        map.put("accountIdList", request.getJSONArray("accountIdList"));
+        String type = map.get("type").toString();
+        String filedAll = JsonResourceUtil.joinAllFiled(AccountReportConstants.getKuaishouAccountReport());
+        System.out.println(filedAll);
+        map.put("filedAll", filedAll);
+        if ("hourly".equals(type)) {
+            PageUtils.startPage();
+            return mapper.getAccountDataReportByHourly(map);
+        } else {
+            PageUtils.startPage();
+            return mapper.getAccountDataReportByDaily(map);
+        }
+    }
+
+    @Override
+    public List<JSONObject> exportAccountDataReport(JSONObject request) {
+        String startDate = request.getString("startDate");
+        String endDate = request.getString("endDate");
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        map.put("accountIdList", request.getJSONArray("accountIdList"));
+        String type = map.get("type").toString();
+        String filedAll = JsonResourceUtil.joinAllFiled(AccountReportConstants.getKuaishouAccountReport());
+        map.put("filedAll", filedAll);
+        if ("hourly".equals(type)) {
+            return mapper.getAccountDataReportByHourly(map);
+        } else {
+            return mapper.getAccountDataReportByDaily(map);
+        }
+    }
+
+
+    /*补全数据,排序 */
+    private void completeDate(List<JSONObject> list, List<String> allDates) {
+        String listStr = JSONObject.toJSONString(list);
+        for (String date : allDates) {
+            if (!listStr.contains(date)) {
+                JSONObject obj = new JSONObject();
+                obj.put("time", date);
+                obj.put("costTotal", 0);
+                list.add(obj);
+            }
+        }
+        //排序
+        Collections.sort(list, new Comparator<JSONObject>() {
+            @Override
+            public int compare(JSONObject o1, JSONObject o2) {
+                return o1.getString("time").compareTo(o2.getString("time"));
+            }
+        });
+    }
+
+    /*根据入参时间,整理上个时间周期,并判断查询日报OR时报*/
+    private Map<String, Object> getDateTime(String startDate, String endDate) {
+        Map<String, Object> map = new HashMap<>();
+        //当前小时
+        String today = DateUtils.getDate();
+        if (today.equals(endDate) && startDate.equals(endDate)) {
+            /* 开始日期和结束日期都是今天*/
+            Integer hour = DateUtils.getNowHour();
+            String yesterday = DateUtils.getSubtractTime(new Date(), 1);
+            map.put("hour", hour);
+            map.put("today", today.replace("-", ""));
+            map.put("yesterday", yesterday.replace("-", ""));
+            map.put("days", 1);
+            map.put("type", "hourly");
+        } else if (!today.equals(endDate) && startDate.equals(endDate)) {
+            /* 开始日期和结束日期相同,但不是当日日期*/
+            String previousDay = DateUtils.getSubtractTime(DateUtils.parseDate(startDate), 1);
+            map.put("startDate", startDate.replace("-", ""));
+            map.put("endDate", endDate.replace("-", ""));
+            map.put("lastStart", previousDay.replace("-", ""));
+            map.put("lastEnd", previousDay.replace("-", ""));
+            map.put("days", 1);
+            map.put("type", "daily");
+            //折线图时使用↓
+            map.put("today", startDate.replace("-", ""));
+            map.put("yesterday", previousDay.replace("-", ""));
+        } else {
+            /*多日日期*/
+            int days = DateUtils.differentDaysByMillisecond(DateUtils.parseDate(startDate), DateUtils.parseDate(endDate)) + 1;
+            String lastStart = DateUtils.getSubtractTime(DateUtils.parseDate(startDate), days);
+            String lastEnd = DateUtils.getSubtractTime(DateUtils.parseDate(endDate), days);
+            map.put("startDate", startDate.replace("-", ""));
+            map.put("endDate", endDate.replace("-", ""));
+            map.put("lastStart", lastStart.replace("-", ""));
+            map.put("lastEnd", lastEnd.replace("-", ""));
+            map.put("days", days);
+            map.put("type", "daily");
+        }
+        return map;
+    }
+
+}

+ 295 - 0
ruixuan-live/src/main/java/com/ruixuan/report/utils/AccountReportConstants.java

@@ -0,0 +1,295 @@
+package com.ruixuan.report.utils;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.Map;
+
+/**
+ * 整理报表字段
+ */
+public class AccountReportConstants {
+
+    public static final String KUAISHOU_ACCOUNT_REPORT_JSON = "{\n" +
+            "  \"costTotal\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.cost_total),0) as costTotal \",\n" +
+            "    \"comment\": \"花费\"\n" +
+            "  },\n" +
+            "  \"adShow\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.ad_show),0) as adShow \",\n" +
+            "    \"comment\": \"广告曝光数\"\n" +
+            "  },\n" +
+            "  \"adShow1kCost\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.ad_show) != 0 THEN ROUND(sum(t1.cost_total) / sum(t1.ad_show) * 1000, 2) ELSE 0 END AS adShow1kCost \",\n" +
+            "    \"comment\": \"平均千次广告曝光花费\"\n" +
+            "  },\n" +
+            "  \"impression\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.impression),0) as impression \",\n" +
+            "    \"comment\": \"封面曝光数\"\n" +
+            "  },\n" +
+            "  \"photoClick\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.photo_click),0) as photoClick \",\n" +
+            "    \"comment\": \"封面点击数\"\n" +
+            "  },\n" +
+            "  \"photoClickRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.impression) != 0 THEN CONCAT(CAST(ROUND((sum(t1.photo_click) / sum(t1.impression)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS photoClickRatio \",\n" +
+            "    \"comment\": \"封面点击率\"\n" +
+            "  },\n" +
+            "  \"click\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.click),0) as click \",\n" +
+            "    \"comment\": \"素材曝光数\"\n" +
+            "  },\n" +
+            "  \"actionbarClick\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.actionbar_click),0) as actionbarClick \",\n" +
+            "    \"comment\": \"行为数\"\n" +
+            "  },\n" +
+            "  \"actionbarClickCost\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.actionbar_click) != 0 THEN ROUND(sum(t1.cost_total) / sum(t1.actionbar_click), 2) ELSE 0 END AS actionbarClickCost \",\n" +
+            "    \"comment\": \"行为成本\"\n" +
+            "  },\n" +
+            "  \"espClickRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.ad_show) != 0 THEN CONCAT(CAST(ROUND((sum(t1.actionbar_click) / sum(t1.ad_show)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS espClickRatio \",\n" +
+            "    \"comment\": \"行为率\"\n" +
+            "  },\n" +
+            "  \"actionRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.click) != 0 THEN CONCAT(CAST(ROUND((sum(t1.actionbar_click) / sum(t1.click)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS actionRatio \",\n" +
+            "    \"comment\": \"素材点击率\"\n" +
+            "  },\n" +
+            "  \"adItemClickCount\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.ad_item_click_count),0) as adItemClickCount \",\n" +
+            "    \"comment\": \"组件点击数\"\n" +
+            "  },\n" +
+            "  \"espLivePlayedSeconds\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.esp_live_played_seconds),0) as espLivePlayedSeconds \",\n" +
+            "    \"comment\": \"直播平均观看时长\"\n" +
+            "  },\n" +
+            "  \"playedThreeSeconds\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.played_three_seconds),0) as playedThreeSeconds \",\n" +
+            "    \"comment\": \"作品3秒播放数\"\n" +
+            "  },\n" +
+            "  \"play3sRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.click) != 0 THEN CONCAT(CAST(ROUND((sum(t1.played_three_seconds) / sum(t1.click)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS play3sRatio \",\n" +
+            "    \"comment\": \"作品3秒播放率\"\n" +
+            "  },\n" +
+            "  \"playedFiveSeconds\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.played_five_seconds),0) as playedFiveSeconds \",\n" +
+            "    \"comment\": \"作品5秒播放数\"\n" +
+            "  },\n" +
+            "  \"play5sRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.click) != 0 THEN CONCAT(CAST(ROUND((sum(t1.played_five_seconds) / sum(t1.click)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS play5sRatio \",\n" +
+            "    \"comment\": \"作品5秒播放率\"\n" +
+            "  },\n" +
+            "  \"playedEnd\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.played_end),0) as playedEnd \",\n" +
+            "    \"comment\": \"作品完播数\"\n" +
+            "  },\n" +
+            "  \"playEndRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.click) != 0 THEN CONCAT(CAST(ROUND((sum(t1.played_end) / sum(t1.click)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS playEndRatio \",\n" +
+            "    \"comment\": \"作品完播率\"\n" +
+            "  },\n" +
+            "  \"share\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.share),0) as share \",\n" +
+            "    \"comment\": \"作品分享数\"\n" +
+            "  },\n" +
+            "  \"comment\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.comment),0) as comment \",\n" +
+            "    \"comment\": \"作品评论数\"\n" +
+            "  },\n" +
+            "  \"likes\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.likes),0) as likes \",\n" +
+            "    \"comment\": \"作品点赞数\"\n" +
+            "  },\n" +
+            "  \"report\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.report),0) as report \",\n" +
+            "    \"comment\": \"作品举报数\"\n" +
+            "  },\n" +
+            "  \"block\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.block),0) as block \",\n" +
+            "    \"comment\": \"作品拉黑数\"\n" +
+            "  },\n" +
+            "  \"itemNegative\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.item_negative),0) as itemNegative \",\n" +
+            "    \"comment\": \"详情页减少此类作品数\"\n" +
+            "  },\n" +
+            "  \"liveShare\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.live_share),0) as liveShare \",\n" +
+            "    \"comment\": \"直播间分享数\"\n" +
+            "  },\n" +
+            "  \"liveComment\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.live_comment),0) as liveComment \",\n" +
+            "    \"comment\": \"直播间评论数\"\n" +
+            "  },\n" +
+            "  \"liveReward\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.live_reward),0) as liveReward \",\n" +
+            "    \"comment\": \"直播间送礼数\"\n" +
+            "  },\n" +
+            "  \"effectivePlayCount\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.effective_play_count),0) as effectivePlayCount \",\n" +
+            "    \"comment\": \"有效播放数\"\n" +
+            "  },\n" +
+            "  \"effectivePlayRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.ad_show) != 0 THEN CONCAT(CAST(ROUND((sum(t1.effective_play_count) / sum(t1.ad_show)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS effectivePlayRatio \",\n" +
+            "    \"comment\": \"有效播放率\"\n" +
+            "  },\n" +
+            "  \"adLivePlayed1mNum\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.ad_live_played1m_num),0) as adLivePlayed1mNum \",\n" +
+            "    \"comment\": \"直播间停留1分数\"\n" +
+            "  },\n" +
+            "  \"conversionNum\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.conversion_num),0) as conversionNum \",\n" +
+            "    \"comment\": \"转化数\"\n" +
+            "  },\n" +
+            "  \"conversionCostEsp\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.conversion_num) != 0 THEN ROUND(sum(t1.cost_total) / sum(t1.conversion_num), 2) ELSE 0 END AS conversionCostEsp \",\n" +
+            "    \"comment\": \"转化成本\"\n" +
+            "  },\n" +
+            "  \"gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.gmv),0) as gmv \",\n" +
+            "    \"comment\": \"GMV\"\n" +
+            "  },\n" +
+            "  \"t0Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t0_gmv),0) as t0Gmv \",\n" +
+            "    \"comment\": \"当日累计GMV\"\n" +
+            "  },\n" +
+            "  \"t1Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t1_gmv),0) as t1Gmv \",\n" +
+            "    \"comment\": \"次日累计GMV\"\n" +
+            "  },\n" +
+            "  \"t7Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t7_gmv),0) as t7Gmv \",\n" +
+            "    \"comment\": \"7日累计GMV\"\n" +
+            "  },\n" +
+            "  \"t15Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t15_gmv),0) as t15Gmv \",\n" +
+            "    \"comment\": \"15日累计GMV\"\n" +
+            "  },\n" +
+            "  \"t30Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t30_gmv),0) as t30Gmv \",\n" +
+            "    \"comment\": \"30日累计GMV\"\n" +
+            "  },\n" +
+            "  \"roi\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.cost_total) != 0 THEN ROUND(sum(t1.cost_total) / sum(t1.conversion_num), 2) ELSE 0 END AS roi \",\n" +
+            "    \"comment\": \"ROI\"\n" +
+            "  },\n" +
+            "  \"paiedOrder\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.paied_order),0) as paiedOrder \",\n" +
+            "    \"comment\": \"直接订单数\"\n" +
+            "  },\n" +
+            "  \"orderRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.actionbar_click) != 0 THEN CONCAT(CAST(ROUND((sum(t1.paied_order) / sum(t1.actionbar_click)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS orderRatio \",\n" +
+            "    \"comment\": \"直接下单率\"\n" +
+            "  },\n" +
+            "  \"t0OrderCnt\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t0_order_cnt),0) as t0OrderCnt \",\n" +
+            "    \"comment\": \"当日累计订单数\"\n" +
+            "  },\n" +
+            "  \"t0OrderCntCost\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.t0_order_cnt) != 0 THEN ROUND(sum(t1.cost_total) / sum(t1.t0_order_cnt), 2) ELSE 0 END AS t0OrderCntCost \",\n" +
+            "    \"comment\": \"当日累计订单成本\"\n" +
+            "  },\n" +
+            "  \"t0OrderCntRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.actionbar_click) != 0 THEN CONCAT(CAST(ROUND((sum(t1.t0_order_cnt) / sum(t1.actionbar_click)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS t0OrderCntRatio \",\n" +
+            "    \"comment\": \"累计订单下单率\"\n" +
+            "  },\n" +
+            "  \"t1OrderCnt\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t1_order_cnt),0) as t1OrderCnt \",\n" +
+            "    \"comment\": \"次日累计订单数\"\n" +
+            "  },\n" +
+            "  \"t7OrderCnt\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t7_order_cnt),0) as t7OrderCnt \",\n" +
+            "    \"comment\": \"7日累计订单数\"\n" +
+            "  },\n" +
+            "  \"t15OrderCnt\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t15_order_cnt),0) as t15OrderCnt \",\n" +
+            "    \"comment\": \"15日累计订单数\"\n" +
+            "  },\n" +
+            "  \"t30OrderCnt\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t30_order_cnt),0) as t30OrderCnt \",\n" +
+            "    \"comment\": \"30日累计订单数\"\n" +
+            "  },\n" +
+            "  \"merchantRecoFans\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.merchant_reco_fans),0) as merchantRecoFans \",\n" +
+            "    \"comment\": \"涨粉数\"\n" +
+            "  },\n" +
+            "  \"t1Retention\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t1_retention),0) as t1Retention \",\n" +
+            "    \"comment\": \"次日涨粉留存数\"\n" +
+            "  },\n" +
+            "  \"t7Retention\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t7_retention),0) as t7Retention \",\n" +
+            "    \"comment\": \"7日涨粉留存数\"\n" +
+            "  },\n" +
+            "  \"t15Retention\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t15_retention),0) as t15Retention \",\n" +
+            "    \"comment\": \"15日涨粉留存数\"\n" +
+            "  },\n" +
+            "  \"t30Retention\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.t30_retention),0) as t30Retention \",\n" +
+            "    \"comment\": \"30日涨粉留存数\"\n" +
+            "  },\n" +
+            "  \"reservationSuccess\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.reservation_success),0) as reservationSuccess \",\n" +
+            "    \"comment\": \"预约成功数\"\n" +
+            "  },\n" +
+            "  \"reservationCost\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.reservation_success) != 0 THEN ROUND(sum(t1.cost_total) / sum(t1.reservation_success), 2) ELSE 0 END AS reservationCost \",\n" +
+            "    \"comment\": \"预约成功成本\"\n" +
+            "  },\n" +
+            "  \"standardLivePlayedStarted\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.standard_live_played_started),0) as standardLivePlayedStarted \",\n" +
+            "    \"comment\": \"直播观看数\"\n" +
+            "  },\n" +
+            "  \"liveAudienceCost\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.standard_live_played_started) != 0 THEN ROUND(sum(t1.cost_total) / sum(t1.standard_live_played_started), 2) ELSE 0 END AS liveAudienceCost \",\n" +
+            "    \"comment\": \"直播观看成本\"\n" +
+            "  },\n" +
+            "  \"liveEventGoodsView\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.live_event_goods_view),0) as liveEventGoodsView \",\n" +
+            "    \"comment\": \"直播间商品点击数\"\n" +
+            "  },\n" +
+            "  \"goodsClickRatio\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.standard_live_played_started) != 0 THEN CONCAT(CAST(ROUND((sum(t1.live_event_goods_view) / sum(t1.standard_live_played_started)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS goodsClickRatio \",\n" +
+            "    \"comment\": \"直播间商品点击率\"\n" +
+            "  },\n" +
+            "  \"directAttrPlatNewBuyerCnt\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.direct_attr_plat_new_buyer_cnt),0) as directAttrPlatNewBuyerCnt \",\n" +
+            "    \"comment\": \"直接平台新客\"\n" +
+            "  },\n" +
+            "  \"directAttrSellerNewBuyerCnt\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.direct_attr_seller_new_buyer_cnt),0) as directAttrSellerNewBuyerCnt \",\n" +
+            "    \"comment\": \"直接店铺新客\"\n" +
+            "  },\n" +
+            "  \"fansT0Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.fans_t0_gmv),0) as fansT0Gmv \",\n" +
+            "    \"comment\": \"涨粉当日GMV\"\n" +
+            "  },\n" +
+            "  \"fansT1Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.fans_t1_gmv),0) as fansT1Gmv \",\n" +
+            "    \"comment\": \"涨粉次日GMV\"\n" +
+            "  },\n" +
+            "  \"fansT7Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.fans_t7_gmv),0) as fansT7Gmv \",\n" +
+            "    \"comment\": \"涨粉7日GMV\"\n" +
+            "  },\n" +
+            "  \"fansT15Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.fans_t15_gmv),0) as fansT15Gmv \",\n" +
+            "    \"comment\": \"涨粉15日GMV\"\n" +
+            "  },\n" +
+            "  \"fansT30Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.fans_t30_gmv),0) as fansT30Gmv \",\n" +
+            "    \"comment\": \"涨粉30日GMV\"\n" +
+            "  },\n" +
+            "  \"fansT1Gmv\": {\n" +
+            "    \"filed\": \"IFNULL(sum(t1.fans_t1_gmv),0) as fansT1Gmv \",\n" +
+            "    \"comment\": \"涨粉次日GMV\"\n" +
+            "  },\n" +
+            "  \"fansT0Roi\": {\n" +
+            "    \"filed\": \"CASE WHEN sum(t1.cost_total) != 0 THEN CONCAT(CAST(ROUND((sum(t1.fans_t0_gmv) / sum(t1.cost_total)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' END AS fansT0Roi \",\n" +
+            "    \"comment\": \"涨粉当日ROI\"\n" +
+            "  }\n" +
+            "}";
+
+    public static Map<String, Map<String, Object>> getKuaishouAccountReport() {
+        Object kuaiShouVideoDictJson = JSON.parseObject(KUAISHOU_ACCOUNT_REPORT_JSON);
+        return JsonResourceUtil.jsonToMap(kuaiShouVideoDictJson);
+    }
+}

+ 122 - 0
ruixuan-live/src/main/java/com/ruixuan/report/utils/JsonResourceUtil.java

@@ -0,0 +1,122 @@
+package com.ruixuan.report.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 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;
+    }
+
+    //json文件转化为JSONArray
+    public static JSONArray getJsonArrFromResource(String filename) {
+        JSONArray 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.parseArray(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(Map<String, Map<String,Object>> mapMap,JSONArray array) {
+        StringBuilder sb = new StringBuilder();
+        array.forEach(it -> {
+            String filedName = it.toString();
+            if (null== mapMap.get(filedName)||mapMap.get(filedName).isEmpty()) {
+                sb.append(it).append(",");
+            } else {
+                sb.append(mapMap.get(filedName).get("filed")).append(",");
+            }
+        });
+        return sb.deleteCharAt(sb.length() - 1).toString();
+    }
+
+    /**
+     * 拼接title
+     */
+    public static List<String> joinTitle(Map<String, Map<String,Object>> mapMap,JSONArray array) {
+        List<String> titles = new ArrayList<>(20);
+        array.forEach(it -> {
+            String titleName = it.toString();
+            if (null== mapMap.get(titleName)||mapMap.get(titleName).isEmpty()) {
+                titles.add(it.toString());
+            } else {
+                titles.add(mapMap.get(it.toString()).get("comment").toString());
+            }
+        });
+        return titles;
+    }
+
+    /**
+     * 拼接字段
+     */
+    public static String joinAllFiled(Map<String, Map<String,Object>> mapMap) {
+        StringBuilder sb = new StringBuilder();
+        mapMap.forEach((k, v) -> sb.append(v.get("filed")).append(","));
+        return sb.deleteCharAt(sb.length() - 1).toString();
+    }
+}

+ 19 - 0
ruixuan-live/src/main/java/com/ruixuan/report/utils/ListPageUtil.java

@@ -0,0 +1,19 @@
+package com.ruixuan.report.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ListPageUtil {
+
+    public static <T> List<T> page(List<T> dataList, int pageSize, int currentPage) {
+        List<T> currentPageList = new ArrayList<>();
+        if (dataList != null && dataList.size() > 0) {
+            int currIdx = (currentPage > 1 ? (currentPage - 1) * pageSize : 0);
+            for (int i = 0; i < pageSize && i < dataList.size() - currIdx; i++) {
+                T data = dataList.get(currIdx + i);
+                currentPageList.add(data);
+            }
+        }
+        return currentPageList;
+    }
+}

+ 8 - 0
ruixuan-live/src/main/resources/mapper/jinniu/KuaishouAccountMapper.xml

@@ -87,6 +87,14 @@
         order by create_time desc
     </select>
 
+    <select id="getAccountNameByProjectId" resultType="com.alibaba.fastjson.JSONObject">
+        select account_id as 'accountId', account_name as 'accountName', operator_name as 'userName', product_name as 'productName', account_type as 'accountType'
+        from kuaishou_account
+        where project_id = #{projectId}
+          AND account_status = 1
+        order by create_time desc
+    </select>
+
     <select id="selectKuaishouAccountById" parameterType="Long" resultMap="KuaishouAccountResult">
         <include refid="selectKuaishouAccountVo"/>
         where id = #{id}

+ 38 - 0
ruixuan-live/src/main/resources/mapper/jinniu/KuaishouProjectMapper.xml

@@ -119,6 +119,44 @@
         </if>
     </select>
 
+    <select id="getMyProjectIdsByUserIds" resultType="Long">
+        SELECT
+        distinct t1.id
+        from kuaishou_project t1
+        LEFT JOIN kuaishou_project_member t2 ON t1.id = t2.project_id
+        <where>
+            <if test="userList != null and userList.size() > 0 ">
+                AND t2.user_id IN
+                <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                    #{userId}
+                </foreach>
+            </if>
+        </where>
+    </select>
+
+    <select id="getProjectsByMedia" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        distinct t1.id as 'projectId',
+        t1.project_name as 'projectName',
+        t1.media_code as 'mediaCode',
+        t1.advertiser_id as 'advertiserId',
+        t1.advertiser_name as 'advertiserName'
+        from kuaishou_project t1
+        LEFT JOIN kuaishou_project_member t2 ON t1.id = t2.project_id
+        <where>
+            <if test="userList != null and userList.size() > 0 ">
+                AND t2.user_id IN
+                <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                    #{userId}
+                </foreach>
+            </if>
+            <if test="mediaCode != null  and mediaCode != ''">
+                and t1.media_code = #{mediaCode}
+            </if>
+        </where>
+        order by t1.id
+    </select>
+
     <select id="selectKuaishouProjectById" parameterType="Long" resultMap="KuaishouProjectResult">
         <include refid="selectKuaishouProjectVo"/>
         where id = #{id}

+ 684 - 0
ruixuan-live/src/main/resources/mapper/report/KuaishouLiveAccountReportMapper.xml

@@ -0,0 +1,684 @@
+<?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="com.ruixuan.report.mapper.KuaishouLiveAccountReportMapper">
+
+    <select id="operateHomePageHead" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        t1.*,
+        IFNULL(ROUND((t1.costTotal - t2.costTotal) / t2.costTotal * 100, 2), 0) as 'costTotalRoi',
+        IFNULL(ROUND((t1.selfOperationCostTotal - t2.selfOperationCostTotal) / t2.selfOperationCostTotal * 100, 2), 0)
+        as 'selfOperationCostTotalRoi',
+        IFNULL(ROUND(t1.selfOperationCostTotal / t1.costTotal * 100, 2), 0) as 'roi'
+        FROM (
+        SELECT
+        SUM(cost_total) AS 'costTotal',
+        COUNT(DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.account_id ELSE 0 END) AS 'accountNum',
+        SUM(CASE WHEN t1.account_type = 1 THEN cost_total ELSE 0 END) AS 'selfOperationCostTotal'
+        FROM kuaishou_live_account_report_hourly_dw t1
+        LEFT JOIN kuaishou_account t2 ON t1.account_id = t2.account_id
+        WHERE report_date = #{today}
+        AND hour &lt;= #{hour}
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t1
+        LEFT JOIN
+        (
+        SELECT
+        SUM(cost_total) AS 'costTotal',
+        SUM(CASE WHEN t1.account_type = 1 THEN cost_total ELSE 0 END) AS 'selfOperationCostTotal'
+        FROM kuaishou_live_account_report_hourly_dw t1
+        WHERE report_date = #{yesterday}
+        AND hour &lt;= #{hour}
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t2 ON 1 = 1
+
+    </select>
+
+    <select id="getCustomersNum" resultType="Integer">
+        SELECT
+        COUNT(DISTINCT advertiser_id)
+        FROM
+        kuaishou_live_account_report_hourly_dw t1
+        LEFT JOIN kuaishou_account t2 ON t1.account_id = t2.account_id
+        WHERE cost_total > 0
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        AND report_date = #{today}
+        AND hour &lt;= #{hour}
+    </select>
+
+    <select id="getProjectCostListByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT * FROM (
+        SELECT t1.*,
+        IFNULL(ROUND((t1.costTotal - t2.costTotal) / t2.costTotal * 100, 2), 0) as 'costTotalRoi',
+        IFNULL(ROUND((t1.roi - t2.roi) / t2.roi * 100, 2), 0) as 'rRoi'
+        FROM (
+        SELECT t1.project_id as 'projectId',
+        t2.project_name as 'projectName',
+        t2.operator_id as 'operatorId',
+        t2.operator_name as 'operatorName',
+        SUM(cost_total) as 'costTotal',
+        IFNULL(ROUND(SUM(t1.t0_gmv) / SUM(cost_total), 2), 0) as 'roi'
+        FROM kuaishou_live_account_report_hourly_dw t1
+        LEFT JOIN `kuaishou_project` t2 ON t1.project_id = t2.id
+        WHERE report_date = #{today}
+        AND hour &lt;= #{hour}
+        AND t1.account_type = 1
+        <if test="projectIds != null and projectIds.size() > 0 ">
+            AND t1.project_id IN
+            <foreach collection="projectIds" item="projectId" open="(" separator="," close=")">
+                #{projectId}
+            </foreach>
+        </if>
+        GROUP BY t1.project_id
+        ) t1
+        LEFT JOIN
+        (
+        SELECT
+        t1.project_id as 'projectId',
+        SUM(cost_total) as 'costTotal',
+        IFNULL(ROUND(SUM(t1.t0_gmv) / SUM(cost_total), 2), 0) as 'roi'
+        FROM kuaishou_live_account_report_hourly_dw t1
+        WHERE report_date = #{yesterday}
+        AND hour &lt;= #{hour}
+        AND account_type = 1
+        <if test="projectIds != null and projectIds.size() > 0 ">
+            AND t1.project_id IN
+            <foreach collection="projectIds" item="projectId" open="(" separator="," close=")">
+                #{projectId}
+            </foreach>
+        </if>
+        GROUP BY t1.project_id
+        ) t2 ON t1.projectId = t2.projectId
+        ) t ORDER BY costTotal desc
+    </select>
+    <select id="getProjectCostListByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT *
+        FROM (
+        SELECT t1.*,
+        IFNULL(ROUND((t1.costTotal - t2.costTotal) / t2.costTotal * 100, 2), 0) as 'costTotalRoi',
+        IFNULL(ROUND((t1.roi - t2.roi) / t2.roi * 100, 2), 0) as 'rRoi'
+        FROM (
+        SELECT t1.project_id as 'projectId',
+        t2.project_name as 'projectName',
+        t2.operator_id as 'operatorId',
+        t2.operator_name as 'operatorName',
+        SUM(cost_total) as 'costTotal',
+        IFNULL(ROUND(SUM(t1.t0_gmv) / SUM(cost_total), 2), 0) as 'roi'
+        FROM kuaishou_live_account_report_daily_dw t1
+        LEFT JOIN `kuaishou_project` t2 ON t1.project_id = t2.id
+        WHERE report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        AND t1.account_type = 1
+        <if test="projectIds != null and projectIds.size() > 0 ">
+            AND t1.project_id IN
+            <foreach collection="projectIds" item="projectId" open="(" separator="," close=")">
+                #{projectId}
+            </foreach>
+        </if>
+        GROUP BY t1.project_id
+        ) t1
+        LEFT JOIN
+        (
+        SELECT
+        project_id as 'projectId',
+        SUM(cost_total) as 'costTotal',
+        IFNULL(ROUND(SUM(t0_gmv) / SUM(cost_total), 2), 0) as 'roi'
+        FROM kuaishou_live_account_report_daily_dw
+        WHERE report_date >=#{lastStart}
+        AND report_date &lt;=#{lastEnd}
+        AND account_type = 1
+        <if test="projectIds != null and projectIds.size() > 0 ">
+            AND project_id IN
+            <foreach collection="projectIds" item="projectId" open="(" separator="," close=")">
+                #{projectId}
+            </foreach>
+        </if>
+        GROUP BY project_id
+        ) t2 ON t1.projectId = t2.projectId
+        ) t
+        ORDER BY costTotal desc
+    </select>
+
+
+    <select id="getOperationsGroupCostByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        IFNULL(t1.costTotal,0) as 'costTotal',
+        IFNULL(t1.perCost,0) as 'perCost',
+        IFNULL(ROUND((t1.costTotal - t2.costTotal) / t2.costTotal * 100, 2), 0) as 'roi',
+        IFNULL(t2.costTotal,0) as 'yesCostTotal'
+        FROM (
+        SELECT
+        SUM(cost_total) as 'costTotal',
+        IFNULL(ROUND(SUM(cost_total) / ${operateNum}/${days}, 2), 0) as 'perCost'
+        FROM kuaishou_live_account_report_hourly_dw
+        WHERE report_date = #{today}
+        AND hour &lt;= #{hour}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t1
+        LEFT JOIN
+        (
+        SELECT
+        SUM(cost_total) as 'costTotal'
+        FROM kuaishou_live_account_report_hourly_dw
+        WHERE report_date = #{yesterday}
+        AND hour &lt;= #{hour}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t2 ON 1 = 1
+    </select>
+    <select id="getOperationsGroupCostByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        IFNULL(t1.costTotal,0) as 'costTotal',
+        IFNULL(t1.perCost,0) as 'perCost',
+        IFNULL(ROUND((t1.costTotal - t2.costTotal) / t2.costTotal * 100, 2), 0) as 'roi',
+        IFNULL(t2.costTotal,0) as 'yesCostTotal'
+        FROM (
+        SELECT
+        SUM(cost_total) as 'costTotal',
+        IFNULL(ROUND(SUM(cost_total) / ${operateNum}/${days}, 2), 0) as 'perCost'
+        FROM kuaishou_live_account_report_daily_dw
+        WHERE report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t1
+        LEFT JOIN
+        (
+        SELECT
+        SUM(cost_total) as 'costTotal'
+        FROM kuaishou_live_account_report_daily_dw
+        WHERE report_date >=#{lastStart}
+        AND report_date &lt;=#{lastEnd}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t2 ON 1 = 1
+    </select>
+
+
+    <select id="getOperateCostListByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        t1.*,
+        IFNULL( ROUND(( t1.costTotal - t2.costTotal )/ t2.costTotal * 100,2), 0) AS 'costTotalRoi',
+        IFNULL(ROUND(t1.costTotal / t1.accountNum/${days}, 2), 0) as 'accountCost'
+        FROM
+        (
+        SELECT
+        t2.operator_id AS 'userId',
+        t2.operator_name AS 'userName',
+        SUM(cost_total) AS 'costTotal',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.account_id ELSE 0 END ) AS 'accountNum',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.project_id ELSE 0 END ) AS 'projectNum'
+        FROM
+        kuaishou_live_account_report_hourly_dw t1
+        LEFT JOIN kuaishou_account t2 ON t1.account_id = t2.account_id
+        WHERE report_date = #{today}
+        AND hour &lt;= #{hour}
+        AND t2.account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND t1.user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        GROUP BY
+        t1.user_id
+        ORDER BY costTotal desc
+        ) t1
+        LEFT JOIN (
+        SELECT
+        user_id AS 'userId',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_hourly_dw
+        WHERE report_date = #{yesterday}
+        AND hour &lt;= #{hour}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        GROUP BY
+        user_id
+        ) t2 ON t1.userId = t2.userId
+    </select>
+    <select id="getOperateCostListByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        t1.*,
+        IFNULL( ROUND(( t1.costTotal - t2.costTotal )/ t2.costTotal * 100,2), 0) AS 'costTotalRoi',
+        IFNULL(ROUND(t1.costTotal / t1.accountNum/${days}, 2), 0) as 'accountCost'
+        FROM
+        (
+        SELECT
+        t2.operator_id AS 'userId',
+        t2.operator_name AS 'userName',
+        SUM(cost_total) AS 'costTotal',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.account_id ELSE 0 END ) AS 'accountNum',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.project_id ELSE 0 END ) AS 'projectNum'
+        FROM
+        kuaishou_live_account_report_daily_dw t1
+        LEFT JOIN kuaishou_account t2 ON t1.account_id = t2.account_id
+        WHERE report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        AND t2.account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        GROUP BY
+        t1.user_id
+        ORDER BY costTotal desc
+        ) t1
+        LEFT JOIN (
+        SELECT
+        user_id AS 'userId',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_daily_dw
+        WHERE report_date >=#{lastStart}
+        AND report_date &lt;=#{lastEnd}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        GROUP BY
+        user_id
+        ) t2 ON t1.userId = t2.userId
+    </select>
+
+    <select id="getOperateCostTotalByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        t1.*,
+        IFNULL( ROUND(( t1.costTotal - t2.costTotal )/ t2.costTotal * 100,2), 0) AS 'costTotalRoi',
+        IFNULL(ROUND(t1.costTotal / t1.accountNum/${days}, 2), 0) as 'accountCost'
+        FROM
+        (
+        SELECT
+        '汇总' AS 'userName',
+        SUM(cost_total) AS 'costTotal',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.account_id ELSE 0 END ) AS 'accountNum',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.project_id ELSE 0 END ) AS 'projectNum'
+        FROM
+        kuaishou_live_account_report_hourly_dw t1
+        LEFT JOIN kuaishou_account t2 ON t1.account_id = t2.account_id
+        WHERE report_date = #{today}
+        AND hour &lt;= #{hour}
+        AND t2.account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND t1.user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t1
+        LEFT JOIN (
+        SELECT
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_hourly_dw
+        WHERE report_date = #{yesterday}
+        AND hour &lt;= #{hour}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t2 ON 1=1
+    </select>
+    <select id="getOperateCostTotalByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        t1.*,
+        IFNULL(ROUND((t1.costTotal - t2.costTotal)/ t2.costTotal * 100,2), 0) AS 'costTotalRoi',
+        IFNULL(ROUND(t1.costTotal / t1.accountNum/${days}, 2), 0) as 'accountCost'
+        FROM
+        (
+        SELECT
+        '汇总' AS 'userName',
+        SUM(cost_total) AS 'costTotal',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.account_id ELSE 0 END ) AS 'accountNum',
+        count( DISTINCT CASE WHEN t1.cost_total > 0 THEN t1.project_id ELSE 0 END ) AS 'projectNum'
+        FROM
+        kuaishou_live_account_report_daily_dw t1
+        LEFT JOIN kuaishou_account t2 ON t1.account_id = t2.account_id
+        WHERE report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        AND t2.account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t1
+        LEFT JOIN (
+        SELECT
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_daily_dw
+        WHERE report_date >=#{lastStart}
+        AND report_date &lt;=#{lastEnd}
+        AND account_type = 1
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        ) t2 ON 1=1
+    </select>
+
+
+    <select id="getOperateCostTrendChartListByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        hour as 'time',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_hourly_dw
+        WHERE account_type = 1
+        AND report_date = #{today}
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        GROUP BY hour
+        ORDER BY hour
+    </select>
+    <select id="getOperateCostTrendChartListByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        date_format(report_date, '%Y-%m-%d') as 'time',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_daily_dw
+        WHERE account_type = 1
+        AND report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        <if test="userList != null and userList.size() > 0 ">
+            AND user_id IN
+            <foreach collection="userList" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        GROUP BY report_date
+        ORDER BY report_date
+    </select>
+
+
+    <select id="getStatisticalReportHeadByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        ROUND(t1.costTotal,2)AS'costTotal',
+        ROUND(t1.t0Gmv,2)AS't0Gmv',
+        ROUND(t1.t0Roi,2)AS't0Roi',
+        ROUND(t1.viewCost,2)AS'viewCost',
+        ROUND(t1.orderCost,2)AS'orderCost',
+        t1.upFans,
+        IFNULL(ROUND((t1.costTotal - t2.costTotal)/ t2.costTotal * 100,2), 0) AS 'costTotalRoi',
+        IFNULL(ROUND((t1.t0Gmv - t2.t0Gmv)/ t2.t0Gmv * 100,2), 0) AS 't0GmvRoi',
+        IFNULL(ROUND((t1.t0Roi - t2.t0Roi)/ t2.t0Roi * 100,2), 0) AS 't0RoiRoi',
+        IFNULL(ROUND((t1.viewCost - t2.viewCost)/ t2.viewCost * 100,2), 0) AS 'viewCostRoi',
+        IFNULL(ROUND((t1.orderCost - t2.orderCost)/ t2.orderCost * 100,2), 0) AS 'orderCostRoi',
+        IFNULL(ROUND((t1.upFans - t2.upFans)/ t2.upFans * 100,2), 0) AS 'upFansRoi'
+        FROM
+        (
+        SELECT
+        IFNULL(SUM(cost_total),0)AS'costTotal',
+        IFNULL(SUM(t0_gmv),0)AS't0Gmv',
+        IFNULL(SUM(t0_gmv)/SUM(cost_total),0)AS't0Roi',
+        IFNULL(SUM(cost_total)/SUM(standard_live_played_started),0)AS'viewCost',
+        IFNULL(SUM(merchant_reco_fans),0)AS'upFans',
+        IFNULL(SUM(cost_total)/SUM(t0_order_cnt),0)AS'orderCost'
+        FROM
+        kuaishou_live_account_report_hourly_dw
+        WHERE report_date = #{today}
+        AND hour &lt;= #{hour}
+        AND account_type = 1
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        )t1
+        LEFT JOIN
+        (
+        SELECT
+        IFNULL(SUM(cost_total),0)AS'costTotal',
+        IFNULL(SUM(t0_gmv),0)AS't0Gmv',
+        IFNULL(SUM(t0_gmv)/SUM(cost_total),0)AS't0Roi',
+        IFNULL(SUM(cost_total)/SUM(standard_live_played_started),0)AS'viewCost',
+        IFNULL(SUM(merchant_reco_fans),0)AS'upFans',
+        IFNULL(SUM(cost_total)/SUM(t0_order_cnt),0)AS'orderCost'
+        FROM
+        kuaishou_live_account_report_hourly_dw
+        WHERE report_date = #{yesterday}
+        AND hour &lt;= #{hour}
+        AND account_type = 1
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        )t2 ON 1=1
+    </select>
+    <select id="getStatisticalReportHeadByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        ROUND(t1.costTotal,2)AS'costTotal',
+        ROUND(t1.t0Gmv,2)AS't0Gmv',
+        ROUND(t1.t0Roi,2)AS't0Roi',
+        ROUND(t1.viewCost,2)AS'viewCost',
+        ROUND(t1.orderCost,2)AS'orderCost',
+        t1.upFans,
+        IFNULL(ROUND((t1.costTotal - t2.costTotal)/ t2.costTotal * 100,2), 0) AS 'costTotalRoi',
+        IFNULL(ROUND((t1.t0Gmv - t2.t0Gmv)/ t2.t0Gmv * 100,2), 0) AS 't0GmvRoi',
+        IFNULL(ROUND((t1.t0Roi - t2.t0Roi)/ t2.t0Roi * 100,2), 0) AS 't0RoiRoi',
+        IFNULL(ROUND((t1.viewCost - t2.viewCost)/ t2.viewCost * 100,2), 0) AS 'viewCostRoi',
+        IFNULL(ROUND((t1.orderCost - t2.orderCost)/ t2.orderCost * 100,2), 0) AS 'orderCostRoi',
+        IFNULL(ROUND((t1.upFans - t2.upFans)/ t2.upFans * 100,2), 0) AS 'upFansRoi'
+        FROM
+        (
+        SELECT
+        IFNULL(SUM(cost_total),0)AS'costTotal',
+        IFNULL(SUM(t0_gmv),0)AS't0Gmv',
+        IFNULL(SUM(t0_gmv)/SUM(cost_total),0)AS't0Roi',
+        IFNULL(SUM(cost_total)/SUM(standard_live_played_started),0)AS'viewCost',
+        IFNULL(SUM(merchant_reco_fans),0)AS'upFans',
+        IFNULL(SUM(cost_total)/SUM(t0_order_cnt),0)AS'orderCost'
+        FROM
+        kuaishou_live_account_report_daily_dw
+        WHERE report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        AND account_type = 1
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        )t1
+        LEFT JOIN
+        (
+        SELECT
+        IFNULL(SUM(cost_total),0)AS'costTotal',
+        IFNULL(SUM(t0_gmv),0)AS't0Gmv',
+        IFNULL(SUM(t0_gmv)/SUM(cost_total),0)AS't0Roi',
+        IFNULL(SUM(cost_total)/SUM(standard_live_played_started),0)AS'viewCost',
+        IFNULL(SUM(merchant_reco_fans),0)AS'upFans',
+        IFNULL(SUM(cost_total)/SUM(t0_order_cnt),0)AS'orderCost'
+        FROM
+        kuaishou_live_account_report_daily_dw
+        WHERE report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        AND account_type = 1
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        )t2 ON 1=1
+    </select>
+
+
+    <select id="getvisitorStatisticsTrendChartListByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        hour as 'time',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_hourly_dw
+        WHERE account_type = 1
+        AND report_date = #{today}
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        GROUP BY hour
+        ORDER BY hour
+    </select>
+    <select id="getvisitorStatisticsTrendChartListByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        date_format(report_date, '%Y-%m-%d') as 'time',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_daily_dw
+        WHERE account_type = 1
+        AND report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        GROUP BY report_date
+        ORDER BY report_date
+    </select>
+
+
+    <select id="getNodeAccountsCostByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        hour as 'time',
+        account_id as 'accountId',
+        account_name as 'accountName',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_hourly_dw
+        WHERE account_type = 1
+        AND report_date = #{date}
+        AND hour = #{hour}
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        GROUP BY account_id
+        ORDER BY account_id
+    </select>
+    <select id="getNodeAccountsCostByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        date_format(report_date, '%Y-%m-%d') as 'time',
+        account_id as 'accountId',
+        account_name as 'accountName',
+        SUM(cost_total) AS 'costTotal'
+        FROM
+        kuaishou_live_account_report_daily_dw
+        WHERE account_type = 1
+        AND report_date = #{date}
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        GROUP BY account_id
+        ORDER BY account_id
+    </select>
+
+
+    <select id="getAccountDataReportByHourly" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        date_format(report_date, '%Y-%m-%d') as 'date',
+        CONCAT(hour,':00-',(hour+1),':00') as 'time',
+        hour,
+        ${filedAll}
+        FROM
+        kuaishou_live_account_report_hourly_dw t1
+        WHERE account_type = 1
+        AND report_date = #{today}
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        GROUP BY hour
+        ORDER BY hour
+    </select>
+    <select id="getAccountDataReportByDaily" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+        date_format(report_date, '%Y-%m-%d') as 'time',
+        ${filedAll}
+        FROM
+        kuaishou_live_account_report_daily_dw t1
+        WHERE account_type = 1
+        AND report_date >= #{startDate}
+        AND report_date &lt;= #{endDate}
+        <if test="accountIdList != null and accountIdList.size() > 0 ">
+            AND account_id in
+            <foreach collection="accountIdList" item="accountId" open="(" separator="," close=")">
+                #{accountId}
+            </foreach>
+        </if>
+        GROUP BY report_date
+        ORDER BY report_date
+    </select>
+</mapper>