ソースを参照

Merge remote-tracking branch 'origin/master'

yumeng 2 年 前
コミット
bc3bee661b
37 ファイル変更3378 行追加59 行削除
  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. 70 0
      ruixuan-live/src/main/java/com/ruixuan/isc/controller/KuaishouLabelController.java
  4. 57 9
      ruixuan-live/src/main/java/com/ruixuan/isc/controller/KuaishouPromoterController.java
  5. 44 0
      ruixuan-live/src/main/java/com/ruixuan/isc/entity/KuaishouLabel.java
  6. 12 0
      ruixuan-live/src/main/java/com/ruixuan/isc/entity/KuaishouPromoter.java
  7. 2 0
      ruixuan-live/src/main/java/com/ruixuan/isc/mapper/KuaishouItemCollectSamplesMapper.java
  8. 66 0
      ruixuan-live/src/main/java/com/ruixuan/isc/mapper/KuaishouLabelMapper.java
  9. 17 1
      ruixuan-live/src/main/java/com/ruixuan/isc/mapper/KuaishouPromoterMapper.java
  10. 2 0
      ruixuan-live/src/main/java/com/ruixuan/isc/service/IKuaishouItemCollectSamplesService.java
  11. 63 0
      ruixuan-live/src/main/java/com/ruixuan/isc/service/IKuaishouLabelService.java
  12. 9 2
      ruixuan-live/src/main/java/com/ruixuan/isc/service/IKuaishouPromoterService.java
  13. 5 0
      ruixuan-live/src/main/java/com/ruixuan/isc/service/impl/KuaishouItemCollectSamplesServiceImpl.java
  14. 88 0
      ruixuan-live/src/main/java/com/ruixuan/isc/service/impl/KuaishouLabelServiceImpl.java
  15. 85 8
      ruixuan-live/src/main/java/com/ruixuan/isc/service/impl/KuaishouPromoterServiceImpl.java
  16. 10 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/controller/KuaishouProjectController.java
  17. 2 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/mapper/KuaishouAccountMapper.java
  18. 5 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/mapper/KuaishouProjectMapper.java
  19. 2 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/IKuaishouAccountService.java
  20. 2 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/IKuaishouProjectService.java
  21. 5 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/impl/KuaishouAccountServiceImpl.java
  22. 35 0
      ruixuan-live/src/main/java/com/ruixuan/jinniu/service/impl/KuaishouProjectServiceImpl.java
  23. 180 0
      ruixuan-live/src/main/java/com/ruixuan/report/controller/KuaishouLiveAccountReportController.java
  24. 629 0
      ruixuan-live/src/main/java/com/ruixuan/report/entity/KuaishouLiveAccountReport.java
  25. 78 0
      ruixuan-live/src/main/java/com/ruixuan/report/mapper/KuaishouLiveAccountReportMapper.java
  26. 41 0
      ruixuan-live/src/main/java/com/ruixuan/report/service/IKuaishouLiveAccountReportService.java
  27. 439 0
      ruixuan-live/src/main/java/com/ruixuan/report/service/impl/KuaishouLiveAccountReportServiceImpl.java
  28. 295 0
      ruixuan-live/src/main/java/com/ruixuan/report/utils/AccountReportConstants.java
  29. 137 0
      ruixuan-live/src/main/java/com/ruixuan/report/utils/JsonResourceUtil.java
  30. 19 0
      ruixuan-live/src/main/java/com/ruixuan/report/utils/ListPageUtil.java
  31. 5 0
      ruixuan-live/src/main/resources/mapper/isc/KuaishouItemCollectSamplesMapper.xml
  32. 88 0
      ruixuan-live/src/main/resources/mapper/isc/KuaishouLabelMapper.xml
  33. 106 34
      ruixuan-live/src/main/resources/mapper/isc/KuaishouPromoterMapper.xml
  34. 1 1
      ruixuan-live/src/main/resources/mapper/isc/SupplyChainMapper.xml
  35. 8 0
      ruixuan-live/src/main/resources/mapper/jinniu/KuaishouAccountMapper.xml
  36. 50 4
      ruixuan-live/src/main/resources/mapper/jinniu/KuaishouProjectMapper.xml
  37. 706 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()

+ 70 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/controller/KuaishouLabelController.java

@@ -0,0 +1,70 @@
+package com.ruixuan.isc.controller;
+
+
+import com.ruixuan.common.core.controller.BaseController;
+import com.ruixuan.common.core.domain.AjaxResult;
+import com.ruixuan.common.core.page.TableDataInfo;
+import com.ruixuan.common.utils.Result;
+import com.ruixuan.isc.entity.KuaishouLabel;
+import com.ruixuan.isc.service.IKuaishouLabelService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+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.RestController;
+
+import java.util.List;
+
+/**
+ * 快手标签Controller
+ *
+ * @author ruoyi
+ * @date 2023-03-28
+ */
+@Api(tags = "---------快手标签")
+@RestController
+@RequestMapping("/kuaishou/label")
+public class KuaishouLabelController extends BaseController {
+    @Autowired
+    private IKuaishouLabelService kuaishouLabelService;
+
+    /**
+     * 查询快手标签列表
+     */
+    @ApiOperation(value = "查询快手标签列表")
+    @GetMapping("/list")
+    public TableDataInfo list(KuaishouLabel kuaishouLabel) {
+        startPage();
+        List<KuaishouLabel> list = kuaishouLabelService.selectKuaishouLabelList(kuaishouLabel);
+        return getDataTable(list);
+    }
+
+    /**
+     * 新增快手标签
+     */
+    @ApiOperation(value = "新增快手标签")
+    @PostMapping(value = "/add")
+    public Result add(@RequestBody KuaishouLabel kuaishouLabel) {
+        return kuaishouLabelService.insertKuaishouLabel(kuaishouLabel);
+    }
+
+    /**
+     * 修改快手标签
+     */
+    @PostMapping(value = "/edit")
+    public AjaxResult edit(@RequestBody KuaishouLabel kuaishouLabel) {
+        return toAjax(kuaishouLabelService.updateKuaishouLabel(kuaishouLabel));
+    }
+
+    /**
+     * 删除快手标签
+     */
+    @ApiOperation(value = "删除快手标签")
+    @GetMapping(value = "/deleteById")
+    public AjaxResult remove(Long id) {
+        return toAjax(kuaishouLabelService.deleteKuaishouLabelById(id));
+    }
+}

+ 57 - 9
ruixuan-live/src/main/java/com/ruixuan/isc/controller/KuaishouPromoterController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.ruixuan.common.core.controller.BaseController;
 import com.ruixuan.common.core.domain.AjaxResult;
 import com.ruixuan.common.core.page.TableDataInfo;
+import com.ruixuan.common.utils.Result;
 import com.ruixuan.isc.entity.KuaishouPromoter;
 import com.ruixuan.isc.service.IKuaishouPromoterService;
 import com.ruixuan.isc.utils.Tess4jClient;
@@ -62,11 +63,10 @@ public class KuaishouPromoterController extends BaseController {
     @ApiOperation(value = "达人公海")
     public TableDataInfo list2(@ApiParam("达人ID") @RequestParam(value = "promoterId", required = false) Long promoterId,
                                @ApiParam("达人名称") @RequestParam(value = "promoterNickName", required = false) String promoterNickName,
+                               @ApiParam("认领状态,1-认领,2-未认领") @RequestParam(value = "status", required = false) String status,
                                @ApiParam("排序参数") @RequestParam(value = "parameter", required = false) String parameter,
-                               @ApiParam("正序倒叙") @RequestParam(value = "orderBy", required = false) String orderBy
-
-    ) {
-        List<KuaishouPromoter> list = kuaishouPromoterService.selectKuaishouPromoterList2(promoterId, promoterNickName, parameter, orderBy);
+                               @ApiParam("正序倒叙") @RequestParam(value = "orderBy", required = false) String orderBy) {
+        List<JSONObject> list = kuaishouPromoterService.selectKuaishouPromoterList2(promoterId, promoterNickName, status, parameter, orderBy);
         return getDataTable(list);
     }
 
@@ -113,7 +113,45 @@ public class KuaishouPromoterController extends BaseController {
     @PostMapping(value = "/add")
     @ApiOperation(value = "新增快手达人")
     public JSONObject add(@RequestBody KuaishouPromoter kuaishouPromoter) {
-        return kuaishouPromoterService.insertKuaishouPromoter(kuaishouPromoter);
+        try {
+            return kuaishouPromoterService.insertKuaishouPromoter(kuaishouPromoter);
+        } catch (Exception e) {
+            e.printStackTrace();
+            JSONObject result = new JSONObject();
+            result.put("code", -1);
+            result.put("msg", "失败");
+            return result;
+        }
+    }
+
+    /**
+     * 新增达人跟进记录
+     */
+    @PostMapping(value = "/addFollowUpRecords")
+    @ApiOperation(value = "新增达人跟进记录")
+    public Result addFollowUpRecords(@RequestBody JSONObject result) {
+        try {
+            kuaishouPromoterService.addFollowUpRecords(result);
+            return Result.success();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("失败");
+        }
+    }
+
+    /**
+     * 新增达人跟进记录
+     */
+    @PostMapping(value = "/updateFollowUpRecords")
+    @ApiOperation(value = "修改达人跟进记录")
+    public Result updateFollowUpRecords(@RequestBody JSONObject result) {
+        try {
+            kuaishouPromoterService.updateFollowUpRecords(result);
+            return Result.success();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("失败");
+        }
     }
 
     /**
@@ -126,14 +164,22 @@ public class KuaishouPromoterController extends BaseController {
     }
 
     /**
+     * 修改快手达人标签信息
+     */
+    @PostMapping(value = "/updatePromoterLabel")
+    @ApiOperation(value = "修改快手达人标签")
+    public Result updatePromoterLabel(@RequestBody JSONObject result) {
+        return kuaishouPromoterService.updatePromoterLabel(result);
+    }
+
+    /**
      * 删除快手达人 信息
      */
     @GetMapping("/deleteById")
     @ApiOperation(value = "删除快手达人")
-    public AjaxResult deleteById(@ApiParam("主键") @RequestParam(value = "id", required = true) Long id,
-                                 @ApiParam("操作人ID") @RequestParam(value = "userId", required = true) Long userId
-    ) {
-        return toAjax(kuaishouPromoterService.deleteKuaishouPromoterById(id, userId));
+    public Result deleteById(@ApiParam("主键") @RequestParam(value = "id", required = true) Long id,
+                             @ApiParam("操作人ID") @RequestParam(value = "userId", required = true) Long userId) {
+        return kuaishouPromoterService.deleteKuaishouPromoterById(id, userId);
     }
 
 
@@ -156,4 +202,6 @@ public class KuaishouPromoterController extends BaseController {
         result.put("message", "fail");
         return result;
     }
+
+
 }

+ 44 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/entity/KuaishouLabel.java

@@ -0,0 +1,44 @@
+package com.ruixuan.isc.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 快手标签对象 kuaishou_label
+ *
+ * @author ruoyi
+ * @date 2023-03-28
+ */
+@Data
+public class KuaishouLabel {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 标签id
+     */
+    private Long id;
+
+    /**
+     * 标签名
+     */
+    @ApiModelProperty(name = "标签名")
+    private String labelName;
+
+    /**
+     * 标签颜色
+     */
+    @ApiModelProperty(name = "标签颜色")
+    private String labelColour;
+
+    /**
+     * 标签类别
+     */
+    @ApiModelProperty(name = "标签类别")
+    private String labelType;
+
+    /**
+     * 标签级别
+     */
+    @ApiModelProperty(name = "标签级别")
+    private String labelLevel;
+}

+ 12 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/entity/KuaishouPromoter.java

@@ -1,11 +1,13 @@
 package com.ruixuan.isc.entity;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.util.Date;
+import java.util.List;
 
 /**
  * 快手达人 信息对象 kuaishou_promoter
@@ -128,6 +130,16 @@ public class KuaishouPromoter {
     @ApiModelProperty(name = "出单金额")
     private String validAmount;
 
+    /**
+     * 跟进记录
+     */
+    @ApiModelProperty(name = "跟进记录")
+    private String followUpRecord;
+
+    /**
+     * 标签集
+     */
+    private List<JSONObject> labels;
 
     /**
      * 更新时间

+ 2 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/mapper/KuaishouItemCollectSamplesMapper.java

@@ -112,5 +112,7 @@ public interface KuaishouItemCollectSamplesMapper {
     List<JSONObject> queryProductList(Map<String, Object> map);
 
     void batchProcess(@Param("ids") JSONArray ids,@Param("status") Integer status);
+
+    List<KuaishouItemCollectSamples> getListByPromoterId(@Param("promoterId") Long promoterId);
 }
 

+ 66 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/mapper/KuaishouLabelMapper.java

@@ -0,0 +1,66 @@
+package com.ruixuan.isc.mapper;
+
+import com.ruixuan.isc.entity.KuaishouLabel;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 快手标签Mapper接口
+ *
+ * @author ruoyi
+ * @date 2023-03-28
+ */
+public interface KuaishouLabelMapper {
+    /**
+     * 查询快手标签
+     *
+     * @param id 快手标签主键
+     * @return 快手标签
+     */
+    public KuaishouLabel selectKuaishouLabelById(Long id);
+
+    /**
+     * 查询快手标签列表
+     *
+     * @param kuaishouLabel 快手标签
+     * @return 快手标签集合
+     */
+    public List<KuaishouLabel> selectKuaishouLabelList(KuaishouLabel kuaishouLabel);
+
+    /**
+     * 新增快手标签
+     *
+     * @param kuaishouLabel 快手标签
+     * @return 结果
+     */
+    public int insertKuaishouLabel(KuaishouLabel kuaishouLabel);
+
+    /**
+     * 修改快手标签
+     *
+     * @param kuaishouLabel 快手标签
+     * @return 结果
+     */
+    public int updateKuaishouLabel(KuaishouLabel kuaishouLabel);
+
+    /**
+     * 删除快手标签
+     *
+     * @param id 快手标签主键
+     * @return 结果
+     */
+    public int deleteKuaishouLabelById(Long id);
+
+    /**
+     * 批量删除快手标签
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteKuaishouLabelByIds(Long[] ids);
+
+    int updateLabelColourStatus(@Param("labelColour") String labelColour);
+
+    String getLabelColour();
+}

+ 17 - 1
ruixuan-live/src/main/java/com/ruixuan/isc/mapper/KuaishouPromoterMapper.java

@@ -68,9 +68,25 @@ public interface KuaishouPromoterMapper {
 
     void updateKuaishouPromoterByPromoterId(KuaishouPromoter promoters);
 
-    List<KuaishouPromoter> selectAllPromoterList(@Param("promoterId") Long promoterId, @Param("promoterNickName") String promoterNickName, @Param("parameter") String parameter, @Param("orderBy") String orderBy);
+    List<JSONObject> selectAllPromoterList(@Param("promoterId") Long promoterId, @Param("promoterNickName") String promoterNickName, @Param("status") String status, @Param("parameter") String parameter, @Param("orderBy") String orderBy);
 
     List<KuaishouPromoter> getFailInfo();
 
     List<JSONObject> getBoundPromoterRoleKey(@Param("promoterId") Long promoterId);
+
+    int addFollowUpRecords(@Param("result") JSONObject result);
+
+    void updateFollowUpRecords(@Param("result") JSONObject result);
+
+    JSONObject getFollowUpRecordsByUserId(@Param("promoterId") Long promoterId, @Param("userId") Long userId);
+
+    List<JSONObject> getFollowUpRecordListByPromoterId(@Param("promoterId") Long promoterId, @Param("id") Long id);
+
+    int deletePromoterLabel(@Param("promoterId") Long promoterId, @Param("userId") Long userId);
+
+    void insertPromoterLabels(@Param("list") List<JSONObject> list);
+
+    List<JSONObject> getPromoterLabel(@Param("promoterId") Long promoterId, @Param("userId") Long userId);
+
+
 }

+ 2 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/service/IKuaishouItemCollectSamplesService.java

@@ -107,5 +107,7 @@ public interface IKuaishouItemCollectSamplesService {
     void batchProcess(JSONArray ids,Integer status);
 
     void batchAddLogs(List<KuaishouItemCollectSampleLog> logs);
+
+    List<KuaishouItemCollectSamples> getListByPromoterId(Long promoterId);
 }
 

+ 63 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/service/IKuaishouLabelService.java

@@ -0,0 +1,63 @@
+package com.ruixuan.isc.service;
+
+
+import com.ruixuan.common.utils.Result;
+import com.ruixuan.isc.entity.KuaishouLabel;
+
+import java.util.List;
+
+/**
+ * 快手标签Service接口
+ *
+ * @author ruoyi
+ * @date 2023-03-28
+ */
+public interface IKuaishouLabelService {
+    /**
+     * 查询快手标签
+     *
+     * @param id 快手标签主键
+     * @return 快手标签
+     */
+    public KuaishouLabel selectKuaishouLabelById(Long id);
+
+    /**
+     * 查询快手标签列表
+     *
+     * @param kuaishouLabel 快手标签
+     * @return 快手标签集合
+     */
+    public List<KuaishouLabel> selectKuaishouLabelList(KuaishouLabel kuaishouLabel);
+
+    /**
+     * 新增快手标签
+     *
+     * @param kuaishouLabel 快手标签
+     * @return 结果
+     */
+    public Result insertKuaishouLabel(KuaishouLabel kuaishouLabel);
+
+    /**
+     * 修改快手标签
+     *
+     * @param kuaishouLabel 快手标签
+     * @return 结果
+     */
+    public int updateKuaishouLabel(KuaishouLabel kuaishouLabel);
+
+    /**
+     * 批量删除快手标签
+     *
+     * @param ids 需要删除的快手标签主键集合
+     * @return 结果
+     */
+    public int deleteKuaishouLabelByIds(Long[] ids);
+
+    /**
+     * 删除快手标签信息
+     *
+     * @param id 快手标签主键
+     * @return 结果
+     */
+    public int deleteKuaishouLabelById(Long id);
+}

+ 9 - 2
ruixuan-live/src/main/java/com/ruixuan/isc/service/IKuaishouPromoterService.java

@@ -2,6 +2,7 @@ package com.ruixuan.isc.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.ruixuan.common.core.domain.AjaxResult;
+import com.ruixuan.common.utils.Result;
 import com.ruixuan.isc.entity.KuaishouPromoter;
 
 import java.util.List;
@@ -51,7 +52,7 @@ public interface IKuaishouPromoterService {
      * @param id 快手达人 信息主键
      * @return 结果
      */
-    public int deleteKuaishouPromoterById(Long id, Long userId);
+    public Result deleteKuaishouPromoterById(Long id, Long userId);
 
     AjaxResult getPromoterInfo(Long promoterId);
 
@@ -61,7 +62,13 @@ public interface IKuaishouPromoterService {
 
     JSONObject getgetMonthPromoterTotal(List<Long> userList, String start, String end);
 
-    List<KuaishouPromoter> selectKuaishouPromoterList2(Long promoterId, String promoterNickName, String parameter, String orderBy);
+    List<JSONObject> selectKuaishouPromoterList2(Long promoterId, String promoterNickName,String status, String parameter, String orderBy);
 
     String supplementInfo();
+
+    int addFollowUpRecords(JSONObject result);
+
+    Result updatePromoterLabel(JSONObject result);
+
+    void updateFollowUpRecords(JSONObject result);
 }

+ 5 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/service/impl/KuaishouItemCollectSamplesServiceImpl.java

@@ -655,6 +655,11 @@ public class KuaishouItemCollectSamplesServiceImpl implements IKuaishouItemColle
         kuaishouItemCollectSamplesMapper.batchAddLogs(logs);
     }
 
+    @Override
+    public List<KuaishouItemCollectSamples> getListByPromoterId(Long promoterId) {
+        return kuaishouItemCollectSamplesMapper.getListByPromoterId(promoterId);
+    }
+
     // 渠道—数据分析
     private JSONObject getDataAnalysisByChannel(List<Long> userList, String startDate, String endDate) {
         JSONObject data = new JSONObject();

+ 88 - 0
ruixuan-live/src/main/java/com/ruixuan/isc/service/impl/KuaishouLabelServiceImpl.java

@@ -0,0 +1,88 @@
+package com.ruixuan.isc.service.impl;
+
+import com.ruixuan.common.utils.Result;
+import com.ruixuan.isc.entity.KuaishouLabel;
+import com.ruixuan.isc.mapper.KuaishouLabelMapper;
+import com.ruixuan.isc.service.IKuaishouLabelService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 快手标签Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2023-03-28
+ */
+@Service
+public class KuaishouLabelServiceImpl implements IKuaishouLabelService {
+    @Autowired
+    private KuaishouLabelMapper kuaishouLabelMapper;
+
+    /**
+     * 查询快手标签
+     *
+     * @param id 快手标签主键
+     * @return 快手标签
+     */
+    @Override
+    public KuaishouLabel selectKuaishouLabelById(Long id) {
+        return kuaishouLabelMapper.selectKuaishouLabelById(id);
+    }
+
+    /**
+     * 查询快手标签列表
+     *
+     * @param kuaishouLabel 快手标签
+     * @return 快手标签
+     */
+    @Override
+    public List<KuaishouLabel> selectKuaishouLabelList(KuaishouLabel kuaishouLabel) {
+        return kuaishouLabelMapper.selectKuaishouLabelList(kuaishouLabel);
+    }
+
+    /**
+     * 新增快手标签
+     */
+    @Override
+    public Result insertKuaishouLabel(KuaishouLabel kuaishouLabel) {
+        String colour = kuaishouLabelMapper.getLabelColour();
+        kuaishouLabel.setLabelColour(colour);
+        int i = kuaishouLabelMapper.insertKuaishouLabel(kuaishouLabel);
+        if (i > 0) {
+             kuaishouLabelMapper.updateLabelColourStatus(colour);
+        }
+        return Result.success(kuaishouLabel);
+    }
+
+    /**
+     * 修改快手标签
+     */
+    @Override
+    public int updateKuaishouLabel(KuaishouLabel kuaishouLabel) {
+        return kuaishouLabelMapper.updateKuaishouLabel(kuaishouLabel);
+    }
+
+    /**
+     * 批量删除快手标签
+     *
+     * @param ids 需要删除的快手标签主键
+     * @return 结果
+     */
+    @Override
+    public int deleteKuaishouLabelByIds(Long[] ids) {
+        return kuaishouLabelMapper.deleteKuaishouLabelByIds(ids);
+    }
+
+    /**
+     * 删除快手标签信息
+     *
+     * @param id 快手标签主键
+     * @return 结果
+     */
+    @Override
+    public int deleteKuaishouLabelById(Long id) {
+        return kuaishouLabelMapper.deleteKuaishouLabelById(id);
+    }
+}

+ 85 - 8
ruixuan-live/src/main/java/com/ruixuan/isc/service/impl/KuaishouPromoterServiceImpl.java

@@ -1,5 +1,6 @@
 package com.ruixuan.isc.service.impl;
 
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.ruixuan.common.core.domain.AjaxResult;
 import com.ruixuan.common.core.domain.entity.SysUser;
@@ -7,9 +8,12 @@ import com.ruixuan.common.utils.Check;
 import com.ruixuan.common.utils.DateUtils;
 import com.ruixuan.common.utils.PageUtils;
 import com.ruixuan.common.utils.RedisUtil;
+import com.ruixuan.common.utils.Result;
 import com.ruixuan.common.utils.http.HttpUtil;
+import com.ruixuan.isc.entity.KuaishouItemCollectSamples;
 import com.ruixuan.isc.entity.KuaishouPromoter;
 import com.ruixuan.isc.mapper.KuaishouPromoterMapper;
+import com.ruixuan.isc.service.IKuaishouItemCollectSamplesService;
 import com.ruixuan.isc.service.IKuaishouPromoterService;
 import com.ruixuan.system.service.ISysDeptService;
 import com.ruixuan.system.service.ISysRoleService;
@@ -19,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
@@ -56,6 +61,9 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
     @Autowired
     private RedisUtil redisUtil;
 
+    @Autowired
+    private IKuaishouItemCollectSamplesService kuaishouItemCollectSamplesService;
+
     /**
      * 查询快手达人 信息列表
      *
@@ -84,25 +92,43 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
         }
         if (Check.isNull(parameter)) {
             parameter = "t1.create_time";
+        } else {
+            switch (parameter) {
+                case "avg_video_sales":
+                    parameter = "SUBSTRING_INDEX(t1.avg_video_sales,'-',-1)+0";
+                    break;
+                case "video_sales":
+                    parameter = "SUBSTRING_INDEX(t1.video_sales,'-',1)+0";
+                    break;
+                case "total_sale":
+                    parameter = "SUBSTRING_INDEX(t1.total_sale,'-',-1)+0";
+                    break;
+            }
         }
         if (Check.isNull(orderBy)) {
             orderBy = "desc";
         }
         PageUtils.startPage();
         List<KuaishouPromoter> list = kuaishouPromoterMapper.selectKuaishouPromoterList(userList, promoterId, promoterNickName, parameter, orderBy);
+        list.forEach(ent -> {
+            JSONObject follow = kuaishouPromoterMapper.getFollowUpRecordsByUserId(ent.getPromoterId(), ent.getUserId());
+            ent.setFollowUpRecord(Check.isNull(follow) ? "-" : follow.getString("txt"));
+            List<JSONObject> promoterLabelList = kuaishouPromoterMapper.getPromoterLabel(ent.getPromoterId(), ent.getUserId());
+            ent.setLabels(promoterLabelList);
+        });
         return list;
     }
 
     @Override
-    public List<KuaishouPromoter> selectKuaishouPromoterList2(Long promoterId, String promoterNickName, String parameter, String orderBy) {
+    public List<JSONObject> selectKuaishouPromoterList2(Long promoterId, String promoterNickName, String status, String parameter, String orderBy) {
         if (Check.isNull(parameter)) {
-            parameter = "t1.create_time";
+            parameter = "promoterId";
         }
         if (Check.isNull(orderBy)) {
             orderBy = "desc";
         }
         PageUtils.startPage();
-        List<KuaishouPromoter> list = kuaishouPromoterMapper.selectAllPromoterList(promoterId, promoterNickName, parameter, orderBy);
+        List<JSONObject> list = kuaishouPromoterMapper.selectAllPromoterList(promoterId, promoterNickName, status, parameter, orderBy);
         return list;
     }
 
@@ -137,6 +163,18 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
                 log.info("获取达人详情数据,用时:{}s", (System.currentTimeMillis() - startTime) / 1000);
                 data.put("promoterInfo", promoter);
                 data.put("result", result);
+                //跟进记录
+                JSONObject followUpRecord = kuaishouPromoterMapper.getFollowUpRecordsByUserId(promoter.getPromoterId(), promoter.getUserId());
+                data.put("followUpRecord", followUpRecord);
+                Long followUpRecordId = null;
+                if (Check.isNotNull(followUpRecord)) {
+                    followUpRecordId = followUpRecord.getLong("id");
+                }
+                List<JSONObject> followUpRecordList = kuaishouPromoterMapper.getFollowUpRecordListByPromoterId(promoter.getPromoterId(), followUpRecordId);
+                data.put("historyFollowUpRecord", followUpRecordList);
+                //标签
+                List<JSONObject> promoterLabelList = kuaishouPromoterMapper.getPromoterLabel(promoter.getPromoterId(), promoter.getUserId());
+                data.put("promoterLabelList", promoterLabelList);
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -160,7 +198,7 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
             result.put("msg", "该数据已存在,请重新输入");
             return result;
         }
-        //同一达人ID 不能绑定到多个渠道角色用户上
+        /*//同一达人ID 不能绑定到多个渠道角色用户上
         String roleKey = sysUserService.getRoleKeyByUserId(promoter.getUserId());
         if (roleKey.contains("bd")) {
             List<JSONObject> keys = kuaishouPromoterMapper.getBoundPromoterRoleKey(promoter.getPromoterId());
@@ -174,7 +212,7 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
                     }
                 }
             }
-        }
+        }*/
         SysUser sysUser = sysUserService.selectUserById(promoter.getUserId());
         if (Check.isNotNull(sysUser)) {
             promoter.setUserName(sysUser.getNickName());
@@ -244,6 +282,38 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
         return "共计" + list.size() + "条,数据补充中...";
     }
 
+    @Override
+    public int addFollowUpRecords(JSONObject result) {
+        return kuaishouPromoterMapper.addFollowUpRecords(result);
+    }
+
+    @Override
+    public void updateFollowUpRecords(JSONObject result) {
+        kuaishouPromoterMapper.updateFollowUpRecords(result);
+    }
+
+    @Override
+    public Result updatePromoterLabel(JSONObject result) {
+        Long promoterId = result.getLong("promoterId");
+        Long userId = result.getLong("userId");
+        kuaishouPromoterMapper.deletePromoterLabel(promoterId, userId);
+        JSONArray ids = result.getJSONArray("ids");
+        if (Check.isNotNull(ids)) {
+            List<JSONObject> list = new ArrayList<>();
+            for (int i = 0; i < ids.size(); i++) {
+                JSONObject obj = new JSONObject();
+                Long labelId = ids.getLong(i);
+                obj.put("promoterId", promoterId);
+                obj.put("labelId", labelId);
+                obj.put("userId", userId);
+                list.add(obj);
+            }
+            kuaishouPromoterMapper.insertPromoterLabels(list);
+        }
+        return Result.success();
+    }
+
+
     /**
      * 修改快手达人 信息
      *
@@ -258,12 +328,18 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
     /**
      * 删除快手达人 信息信息
      *
-     * @param id 快手达人 信息主键
+     * @param id 快手达人 信息主键 follow_up_records
      * @return 结果
      */
     @Override
-    public int deleteKuaishouPromoterById(Long id, Long userId) {
+    public Result deleteKuaishouPromoterById(Long id, Long userId) {
         KuaishouPromoter promoter = kuaishouPromoterMapper.selectKuaishouPromoterById(id);
+        List<KuaishouItemCollectSamples> list = kuaishouItemCollectSamplesService.getListByPromoterId(promoter.getPromoterId());
+        for (KuaishouItemCollectSamples item : list) {
+            if (item.getCollectSampleStatus() != 2 && item.getCollectSampleStatus() != 7) {
+                return Result.error("该达人还有未完成的领样申请,请在完成后进行解绑!");
+            }
+        }
         if (Check.isNotNull(promoter)) {
             JSONObject record = new JSONObject();
             record.put("promoterId", promoter.getPromoterId());
@@ -271,7 +347,8 @@ public class KuaishouPromoterServiceImpl implements IKuaishouPromoterService {
             record.put("operatorId", userId);
             kuaishouPromoterMapper.insertKuaishouPromoterRecord(record);
         }
-        return kuaishouPromoterMapper.deleteKuaishouPromoterById(id);
+        kuaishouPromoterMapper.deleteKuaishouPromoterById(id);
+        return Result.success();
     }
 
     @Override

+ 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());

+ 35 - 0
ruixuan-live/src/main/java/com/ruixuan/jinniu/service/impl/KuaishouProjectServiceImpl.java

@@ -162,7 +162,42 @@ public class KuaishouProjectServiceImpl implements IKuaishouProjectService {
 
     @Override
     public List<KuaishouProject> getMyProjects(KuaishouProject kuaishouProject) {
+        String roleKey = sysUserService.getRoleKeyByUserId(kuaishouProject.getUserId());
+        if ("admin".equals(roleKey) || "directorOperations".equals(roleKey)) {
 
+        } else if ("operationsManager".equals(roleKey)) {
+            //运营经理 可以看自己部门所有人的(自己和下属的)
+            Long deptId = deptService.getDeptIdByUserId(kuaishouProject.getUserId());
+            kuaishouProject.setOperatorIdList(deptService.getDeptUserListByDeptId(deptId));
+        } else {
+            kuaishouProject.setOperatorIdList(Arrays.asList(kuaishouProject.getUserId()));
+        }
         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);
+    }
+
 }

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

@@ -0,0 +1,180 @@
+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("type 1-查自己") @RequestParam(value = "type", required = true) String type,
+                                               @ApiParam("endDate") @RequestParam(value = "endDate", required = true) String endDate) {
+        JSONObject result = KuaishouLiveAccountReportService.getOperateCostTrendChartList(userId, type, 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 = "账户数据报表")
+    @GetMapping("/getAccountDataReport")
+    public TableDataInfo getAccountDataReport(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId,
+                                              @ApiParam("accountIdList") @RequestParam(value = "accountIdList", required = false) String accountIdList,
+                                              @ApiParam("startDate") @RequestParam(value = "startDate", required = false) String startDate,
+                                              @ApiParam("endDate") @RequestParam(value = "endDate", required = false) String endDate) {
+        List<JSONObject> list = KuaishouLiveAccountReportService.getAccountDataReport(userId, accountIdList, startDate, endDate);
+        return getDataTable(list);
+    }
+
+    @ApiOperation(value = "获取报表字段")
+    @GetMapping("/getReportFields")
+    public Result getReportFields() {
+        return KuaishouLiveAccountReportService.getReportFields();
+    }
+
+    @ApiOperation(value = "记录人员报表字段")
+    @PostMapping("/addKuaishouFields")
+    public Result addKuaishouFields(@RequestBody JSONObject request) {
+        return KuaishouLiveAccountReportService.addKuaishouFields(request);
+    }
+
+    @ApiOperation(value = "获取人员报表字段")
+    @GetMapping("/getKuaishouFieldsByUserId")
+    public Result addKuaishouFields(@ApiParam("userId") @RequestParam(value = "userId", required = true) Long userId,
+                                    @ApiParam("columnType") @RequestParam(value = "columnType", required = true) String columnType) {
+        return KuaishouLiveAccountReportService.getKuaishouFieldsByUserId(userId, columnType);
+    }
+
+    @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;
+
+
+}

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

@@ -0,0 +1,78 @@
+package com.ruixuan.report.mapper;
+
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.ibatis.annotations.Param;
+
+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);
+
+    void replaceKuaishouFields(@Param("request") JSONObject request);
+
+    JSONObject getKuaishouFieldsByUserId(@Param("userId") Long userId, @Param("columnType") String columnType);
+}

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

@@ -0,0 +1,41 @@
+package com.ruixuan.report.service;
+
+import com.alibaba.fastjson.JSONObject;
+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 type, String startDate, String endDate);
+
+    JSONObject getStatisticalReportHead(JSONObject request);
+
+    List<JSONObject> getvisitorStatisticsTrendChartList(JSONObject request);
+
+    List<JSONObject> nodeAccountCost(JSONObject request);
+
+    List<JSONObject> getAccountDataReport(Long userId, String accountIdList, String startDate, String endDate);
+
+    List<JSONObject> exportAccountDataReport(JSONObject request);
+
+    Result getReportFields();
+
+    Result addKuaishouFields(JSONObject request);
+
+    Result getKuaishouFieldsByUserId(Long userId, String columnType);
+}

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

@@ -0,0 +1,439 @@
+package com.ruixuan.report.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+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 queryType, String startDate, String endDate) {
+        String roleKey = sysUserService.getRoleKeyByUserId(userId);
+        List<Long> userList;
+        if ("1".equals(queryType)) {
+            userList = Arrays.asList(userId);
+        } else {
+            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)) {
+            List<JSONObject> todayInfo = mapper.getOperateCostTrendChartListByHourly(map);
+            completeHour(todayInfo);
+            result.put("todayInfo", todayInfo);
+            map.put("today", map.get("yesterday"));
+            List<JSONObject> yesterdayInfo = mapper.getOperateCostTrendChartListByHourly(map);
+            completeHour(yesterdayInfo);
+            result.put("yesterdayInfo", yesterdayInfo);
+        } 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)) {
+            List<JSONObject> list = mapper.getvisitorStatisticsTrendChartListByHourly(map);
+            completeHour(list);
+            return list;
+        } 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(Long userId, String accountIdList, String startDate, String endDate) {
+        //整理入参时间
+        Map<String, Object> map = getDateTime(startDate, endDate);
+        map.put("accountIdList", JSONArray.parseArray(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);
+        }
+    }
+
+    @Override
+    public Result getReportFields() {
+        List<JSONObject> fieldsNames = JsonResourceUtil.getFieldsNames(AccountReportConstants.getKuaishouAccountReport());
+        return Result.success(fieldsNames);
+    }
+
+    @Override
+    public Result addKuaishouFields(JSONObject request) {
+        mapper.replaceKuaishouFields(request);
+        return Result.success();
+    }
+
+    @Override
+    public Result getKuaishouFieldsByUserId(Long userId, String columnType) {
+        JSONObject o = mapper.getKuaishouFieldsByUserId(userId, columnType);
+        return Result.success(o);
+    }
+
+
+    /*补全数据,排序 */
+    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"));
+            }
+        });
+    }
+
+
+    /*补全小时数据,排序 */
+    private void completeHour(List<JSONObject> list) {
+        List<Integer> newDayList = new ArrayList<>();
+        for (JSONObject data : list) {
+            newDayList.add(data.getInteger("time"));
+        }
+        List<Integer> dayList = new ArrayList<>();
+        for (int i = 0; i <= 23; i++) {
+            dayList.add(i);
+        }
+        for (Integer hour : dayList) {
+            if (!newDayList.contains(hour)) {
+                JSONObject obj = new JSONObject();
+                obj.put("time", hour);
+                obj.put("costTotal", 0);
+                list.add(obj);
+            }
+        }
+    }
+
+    /*根据入参时间,整理上个时间周期,并判断查询日报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.conversion_num) != 0 THEN CONCAT(CAST(ROUND((sum(t1.cost_total) / sum(t1.conversion_num)) * 100,2) AS CHAR) ,'%') ELSE '0.00%' 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);
+    }
+}

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

@@ -0,0 +1,137 @@
+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();
+    }
+
+    /**
+     * 获取字段名称JSON
+     */
+    public static List<JSONObject> getFieldsNames(Map<String, Map<String, Object>> mapMap) {
+        List<JSONObject> list = new ArrayList<>();
+        mapMap.forEach((k, v) -> {
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("code",k);
+            jsonObject.put("name", v.get("comment"));
+            list.add(jsonObject);
+        });
+        return list;
+    }
+
+}

+ 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;
+    }
+}

+ 5 - 0
ruixuan-live/src/main/resources/mapper/isc/KuaishouItemCollectSamplesMapper.xml

@@ -605,6 +605,11 @@
         </where>
     </select>
 
+    <select id="getListByPromoterId" resultMap="KuaishouItemCollectSamplesResult">
+        <include refid="selectKuaishouItemCollectSamplesVo"/>
+        where promoter_id = #{promoterId}
+    </select>
+
     <select id="queryProductList" resultType="com.alibaba.fastjson.JSONObject">
         SELECT * from (SELECT
         promoter_id as 'promoterId',

+ 88 - 0
ruixuan-live/src/main/resources/mapper/isc/KuaishouLabelMapper.xml

@@ -0,0 +1,88 @@
+<?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.isc.mapper.KuaishouLabelMapper">
+
+    <resultMap type="com.ruixuan.isc.entity.KuaishouLabel" id="KuaishouLabelResult">
+        <result property="id" column="id"/>
+        <result property="labelName" column="label_name"/>
+        <result property="labelColour" column="label_colour"/>
+        <result property="labelType" column="label_type"/>
+        <result property="labelLevel" column="label_level"/>
+    </resultMap>
+
+    <sql id="selectKuaishouLabelVo">
+        select id, label_name, label_colour, label_type, label_level
+        from kuaishou_label
+    </sql>
+
+    <select id="selectKuaishouLabelList" parameterType="com.ruixuan.isc.entity.KuaishouLabel"
+            resultMap="KuaishouLabelResult">
+        <include refid="selectKuaishouLabelVo"/>
+        <where>
+            <if test="labelName != null  and labelName != ''">and label_name like concat('%', #{labelName}, '%')</if>
+            <if test="labelColour != null  and labelColour != ''">and label_colour = #{labelColour}</if>
+            <if test="labelType != null  and labelType != ''">and label_type = #{labelType}</if>
+            <if test="labelLevel != null  and labelLevel != ''">and label_level = #{labelLevel}</if>
+        </where>
+    </select>
+
+    <select id="selectKuaishouLabelById" parameterType="Long" resultMap="KuaishouLabelResult">
+        <include refid="selectKuaishouLabelVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertKuaishouLabel" parameterType="com.ruixuan.isc.entity.KuaishouLabel" useGeneratedKeys="true"
+            keyProperty="id">
+        insert into kuaishou_label
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="labelName != null">label_name,</if>
+            <if test="labelColour != null">label_colour,</if>
+            <if test="labelType != null">label_type,</if>
+            <if test="labelLevel != null">label_level,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="labelName != null">#{labelName},</if>
+            <if test="labelColour != null">#{labelColour},</if>
+            <if test="labelType != null">#{labelType},</if>
+            <if test="labelLevel != null">#{labelLevel},</if>
+        </trim>
+    </insert>
+
+    <update id="updateKuaishouLabel" parameterType="com.ruixuan.isc.entity.KuaishouLabel">
+        update kuaishou_label
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="labelName != null">label_name = #{labelName},</if>
+            <if test="labelColour != null">label_colour = #{labelColour},</if>
+            <if test="labelType != null">label_type = #{labelType},</if>
+            <if test="labelLevel != null">label_level = #{labelLevel},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteKuaishouLabelById" parameterType="Long">
+        delete
+        from kuaishou_label
+        where id = #{id}
+    </delete>
+
+    <delete id="deleteKuaishouLabelByIds" parameterType="String">
+        delete from kuaishou_label where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <update id="updateLabelColourStatus">
+        update kuaishou_label_colour
+        set colour_status = 0
+        where colour_code = #{labelColour}
+    </update>
+
+    <select id="getLabelColour" resultType="String">
+        select colour_code
+        from kuaishou_label_colour
+        where colour_status = 1 Limit 1
+    </select>
+</mapper>

+ 106 - 34
ruixuan-live/src/main/resources/mapper/isc/KuaishouPromoterMapper.xml

@@ -27,6 +27,7 @@
         <result property="monthDayGmv" column="30day_gmv"/>
         <result property="monthDayOrderNum" column="30day_order_num"/>
         <result property="validAmount" column="valid_amount"/>
+        <result property="followUpRecord" column="txt"/>
     </resultMap>
 
     <sql id="selectKuaishouPromoterVo">
@@ -94,38 +95,48 @@
         order by ${parameter} ${orderBy}
     </select>
 
-    <select id="selectAllPromoterList" resultMap="KuaishouPromoterResult">
+    <select id="selectAllPromoterList" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT *
+        FROM (
         SELECT
-        t1.id,
-        t1.user_id,
-        t1.user_name,
-        t1.promoter_id,
-        t1.promoter_nick_name,
-        t1.`state`,
-        t1.province,
-        t1.commission_requirement,
-        t1.category_requirement,
-        t1.promoter_url,
-        t1.phone,
-        t1.consignee,
-        t1.promoter_address,
-        t1.total_sale,
-        t1.fans_number,
-        t1.avg_video_sales,
-        t1.video_sales,
-        t1.create_time,
-        t2.30day_gmv,
-        t2.30day_order_num
+        t0.promoter_id AS 'promoterId',
+        (CASE WHEN t2.promoter_id IS NULL THEN 2 ELSE 1 END) AS 'status',
+        IF(t0.promoter_name is null,t2.promoter_nick_name,t0.promoter_name) AS 'promoterNickName',
+        IFNULL(t2.userName,'-') AS 'userName',
+        t2.commission_requirement AS 'commissionRequirement',
+        IF(t0.handurl is null,t2.promoter_url,t0.handurl) AS 'promoterUrl',
+        IF(t0.fans is null,t2.fans_number,t0.fans) AS 'fansNumber',
+        t1.30day_gmv AS 'monthDayGmv',
+        t1.30day_order_num AS 'monthDayOrderNum',
+        t1.valid_amount AS 'validAmount'
         FROM
-        kuaishou_promoter t1
-        LEFT JOIN promoter_oerder_amount t2 on t1.promoter_id = t2.promoter_id
-        where t2.30day_order_num > 0
-        <if test="promoterId != null ">
-            and t1.promoter_id = #{promoterId}
-        </if>
-        <if test="promoterNickName != null  and promoterNickName != ''">
-            and t1.promoter_nick_name like concat('%', #{promoterNickName}, '%')
-        </if>
+        promoter_info t0
+        LEFT JOIN promoter_oerder_amount t1 ON t1.promoter_id = t0.promoter_id
+        LEFT JOIN (
+        SELECT
+        promoter_id,
+        group_concat( user_name ) AS 'userName',
+        fans_number, promoter_url,
+        commission_requirement,
+        promoter_nick_name
+        FROM kuaishou_promoter
+        GROUP BY promoter_id
+        ) t2 ON t1.promoter_id =
+        t2.promoter_id
+        <where>
+            <if test="promoterId != null ">
+                and t1.promoter_id = #{promoterId}
+            </if>
+            <if test="promoterNickName != null  and promoterNickName != ''">
+                and t2.promoter_nick_name like concat('%', #{promoterNickName}, '%')
+            </if>
+        </where>
+        ) t
+        <where>
+            <if test="status != null ">
+                and `status` = #{status}
+            </if>
+        </where>
         order by ${parameter} ${orderBy}
     </select>
 
@@ -140,9 +151,9 @@
     </select>
 
     <select id="getBoundPromoterRoleKey" resultType="com.alibaba.fastjson.JSONObject">
-        SELECT 	t1.user_id,
-                  t3.role_key,
-                  t1.user_name
+        SELECT t1.user_id,
+               t3.role_key,
+               t1.user_name
         FROM kuaishou_promoter t1
                  LEFT JOIN sys_user_role t2 ON t1.user_id = t2.user_id
                  LEFT JOIN sys_role t3 ON t2.role_id = t3.role_id
@@ -225,7 +236,6 @@
             <if test="phone != null">phone,</if>
             <if test="consignee != null">consignee,</if>
             <if test="promoterAddress != null">promoter_address,</if>
-
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="userId != null">#{userId},</if>
@@ -247,6 +257,22 @@
         </trim>
     </insert>
 
+    <insert id="addFollowUpRecords">
+        insert into kuaishou_promoter_follow_up_record
+        (promoter_id,
+         user_id,
+         txt)
+        values (#{result.promoterId},
+                #{result.userId},
+                #{result.txt})
+    </insert>
+
+    <update id="updateFollowUpRecords">
+        update kuaishou_promoter_follow_up_record
+        Set txt =#{result.txt}
+        where id = #{result.id}
+    </update>
+
     <update id="updateKuaishouPromoter" parameterType="com.ruixuan.isc.entity.KuaishouPromoter">
         update kuaishou_promoter
         <trim prefix="SET" suffixOverrides=",">
@@ -310,6 +336,21 @@
         </foreach>
     </delete>
 
+    <delete id="deletePromoterLabel" parameterType="Long">
+        delete
+        from kuaishou_promoter_label_rel
+        where promoter_id = #{promoterId}
+          AND user_id = #{userId}
+    </delete>
+
+    <insert id="insertPromoterLabels">
+        insert into kuaishou_promoter_label_rel
+        (promoter_id,user_id, label_id)
+        values
+        <foreach collection="list" item="ent" separator=",">
+            (#{ent.promoterId},#{ent.userId}, #{ent.labelId})
+        </foreach>
+    </insert>
     <select id="getNearlyMonthGmv" resultType="com.alibaba.fastjson.JSONObject">
         SELECT SUM(order_amount) as 'orderAmount', CONCAT(IFNULL(ROUND((SELECT COUNT(1)
                                                                         FROM kuaishou_item_collect_samples
@@ -341,4 +382,35 @@
         </trim>
     </insert>
 
+    <select id="getFollowUpRecordsByUserId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT id,
+               txt
+        FROM kuaishou_promoter_follow_up_record
+        Where promoter_id = #{promoterId}
+          AND user_id = #{userId}
+        ORDER BY update_time DESC LIMIT 1
+    </select>
+
+    <select id="getFollowUpRecordListByPromoterId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT t1.id,
+        txt,
+        t2.nick_name as 'userName',
+        t1.update_time as 'updateTime'
+        FROM kuaishou_promoter_follow_up_record t1
+        LEFT JOIN sys_user t2 ON t1.user_id = t2.user_id
+        Where t1.promoter_id = #{promoterId}
+        <if test="id != null">
+            AND t1.id != #{id}
+        </if>
+        ORDER BY t1.update_time DESC
+    </select>
+
+    <select id="getPromoterLabel" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT t2.id as 'labelId', t2.label_colour as 'labelColour', t2.label_name as 'labelName'
+        FROM kuaishou_promoter_label_rel t1
+                 LEFT JOIN kuaishou_label t2 ON t1.label_id = t2.id
+        WHERE t1.promoter_id = #{promoterId}
+          AND user_id = #{userId}
+        order by t2.id
+    </select>
 </mapper>

+ 1 - 1
ruixuan-live/src/main/resources/mapper/isc/SupplyChainMapper.xml

@@ -788,7 +788,7 @@
             and t1.item_id = #{itemId}
         </if>
         <if test="itemTitle != null and itemTitle != ''">
-            and t1.item_title like concat(concat('%',#{itemTitle}),'%')
+            and t2.item_title like concat(concat('%',#{itemTitle}),'%')
         </if>
         GROUP BY
         t1.item_id

+ 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}

+ 50 - 4
ruixuan-live/src/main/resources/mapper/jinniu/KuaishouProjectMapper.xml

@@ -113,10 +113,56 @@
         t1.update_time
         from kuaishou_project t1
         LEFT JOIN kuaishou_project_member t2 ON t1.id = t2.project_id
-        WHERE t2.user_id =#{userId}
-        <if test="projectName != null  and projectName != ''">
-            and t1.project_name like concat('%', #{projectName}, '%')
-        </if>
+        <where>
+            <if test="operatorIdList != null and operatorIdList.size() > 0 ">
+                AND t2.user_id IN
+                <foreach collection="operatorIdList" item="userId" open="(" separator="," close=")">
+                    #{userId}
+                </foreach>
+            </if>
+            <if test="projectName != null  and projectName != ''">
+                and t1.project_name like concat('%', #{projectName}, '%')
+            </if>
+        </where>
+        GROUP BY t1.id
+    </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">

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

@@ -0,0 +1,706 @@
+<?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>
+
+
+    <insert id="replaceKuaishouFields">
+        replace
+        into kuaishou_field_definition(
+        user_id,
+        json,
+        column_type
+        )values(
+        #{request.userId},
+        #{request.json},
+        #{request.columnType}
+        )
+    </insert>
+    <select id="getKuaishouFieldsByUserId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT user_id as 'userId',
+               json,
+               column_type as 'columnType'
+        FROM kuaishou_field_definition
+        WHERE user_id = #{userId}
+          AND column_type = #{columnType} Limit 1
+    </select>
+</mapper>