浏览代码

直播数据导出数据

yuhongqi 19 小时之前
父节点
当前提交
e3c17928bc

+ 23 - 0
fs-admin/src/main/java/com/fs/live/controller/LiveDataController.java

@@ -1,13 +1,18 @@
 package com.fs.live.controller;
 
+import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.SecurityUtils;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.live.domain.LiveData;
 import com.fs.live.param.LiveDataParam;
 import com.fs.live.service.ILiveDataService;
 import com.fs.live.vo.LiveUserFirstVo;
+import com.fs.live.vo.LiveUserDetailExportVO;
 import com.github.pagehelper.PageHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -153,4 +158,22 @@ public class LiveDataController extends BaseController {
         return liveDataService.getLiveUserDetailListByServer(liveId);
     }
 
+    /**
+     * 导出直播间用户详情数据
+     * @param liveId 直播间ID
+     * @return Excel文件
+     */
+    @PreAuthorize("@ss.hasPermi('liveData:liveData:export')")
+    @Log(title = "直播间用户详情", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportLiveUserDetail")
+    public AjaxResult exportLiveUserDetail(@RequestParam Long liveId) {
+        List<LiveUserDetailExportVO> list = liveDataService.exportLiveUserDetail(liveId);
+        if (list == null || list.isEmpty()) {
+            return AjaxResult.error("未找到用户详情数据");
+        }
+        
+        ExcelUtil<LiveUserDetailExportVO> util = new ExcelUtil<>(LiveUserDetailExportVO.class);
+        return util.exportExcel(list, "直播间用户详情数据");
+    }
+
 }

+ 1 - 1
fs-service/src/main/java/com/fs/live/mapper/LiveAfterSalesMapper.java

@@ -110,7 +110,7 @@ public interface LiveAfterSalesMapper {
     Map<Long, LiveAfterSales> findByOrderIds(@Param("orderIdList") List<Long> orderIdList);
 
     @Select({"<script> " +
-            "select *  from live_after_sales  " +
+            "select lo.order_code,las.*  from live_after_sales las left join live_order lo on lo.order_id = las.order_id " +
             "where 1=1 " +
             "<if test = 'maps.status != null and maps.status ==1   '> " +
             "and sales_status = 0 " +

+ 3 - 1
fs-service/src/main/java/com/fs/live/mapper/LiveMapper.java

@@ -137,7 +137,8 @@ public interface LiveMapper
     @Select({"<script>" +
             "select * from live where 1=1 " +
             " <if test='param.companyId!=null' > and company_id = #{param.companyId} </if> and live_type IN (1,2, 3) AND status IN (3, 4) AND is_del = 0 and is_audit=1 " +
-            " <if test='param.liveName!=null' > and live_name like concat('%' ,#{param.liveName},'%') </if>" +
+            " <if test='param.liveName!=null' > and live_name like concat('%' ,#{param.liveName},'%') </if> " +
+            " order by create_time desc" +
             " </script>"})
     List<Live> listLiveData(@Param("param") LiveDataParam param);
 
@@ -145,6 +146,7 @@ public interface LiveMapper
             "select count(1) from live where 1=1 " +
             " <if test='param.companyId!=null' > and company_id = #{param.companyId} </if> and live_type IN (1,2, 3) AND status IN (3, 4) AND is_del = 0 and is_audit=1" +
             " <if test='param.liveName!=null' > and live_name like concat('%' ,#{param.liveName},'%') </if>" +
+            "  order by create_time desc " +
             " </script>"})
     int listLiveDataCount(@Param("param") LiveDataParam param);
 

+ 8 - 4
fs-service/src/main/java/com/fs/live/service/ILiveDataService.java

@@ -4,10 +4,7 @@ package com.fs.live.service;
 import com.fs.common.core.domain.R;
 import com.fs.live.domain.LiveData;
 import com.fs.live.param.LiveDataParam;
-import com.fs.live.vo.ColumnsConfigVo;
-import com.fs.live.vo.LiveUserFirstVo;
-import com.fs.live.vo.RecentLiveDataVo;
-import com.fs.live.vo.TrendDataVO;
+import com.fs.live.vo.*;
 
 import java.util.List;
 import java.util.Map;
@@ -163,4 +160,11 @@ public interface ILiveDataService {
      * @return 用户详情列表
      */
     R getLiveUserDetailListByServer(Long liveId);
+
+    /**
+     * 导出直播间用户详情数据
+     * @param liveId 直播间ID
+     * @return 导出VO列表
+     */
+    List<LiveUserDetailExportVO> exportLiveUserDetail(Long liveId);
 }

+ 73 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveDataServiceImpl.java

@@ -1075,4 +1075,77 @@ public class LiveDataServiceImpl implements ILiveDataService {
         return result;
     }
 
+    /**
+     * 导出直播间用户详情数据
+     * @param liveId 直播间ID
+     * @return 导出VO列表
+     */
+    @Override
+    public List<LiveUserDetailExportVO> exportLiveUserDetail(Long liveId) {
+        // 查询用户详情列表
+        List<LiveUserDetailVo> userDetailList = liveDataMapper.selectLiveUserDetailListBySql(liveId);
+        if (userDetailList == null || userDetailList.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // 转换为导出VO列表
+        List<LiveUserDetailExportVO> exportList = new ArrayList<>();
+        for (LiveUserDetailVo userDetail : userDetailList) {
+            LiveUserDetailExportVO exportVO = new LiveUserDetailExportVO();
+
+            // 用户基本信息
+            exportVO.setUserId(userDetail.getUserId());
+            exportVO.setUserName(userDetail.getUserName());
+
+            // 观看时长(秒转分钟)
+            exportVO.setLiveWatchDuration(formatSecondsToMinutes(userDetail.getLiveWatchDuration()));
+            exportVO.setPlaybackWatchDuration(formatSecondsToMinutes(userDetail.getPlaybackWatchDuration()));
+
+            // 计算总观看时长
+            Long totalSeconds = (userDetail.getLiveWatchDuration() != null ? userDetail.getLiveWatchDuration() : 0L) +
+                               (userDetail.getPlaybackWatchDuration() != null ? userDetail.getPlaybackWatchDuration() : 0L);
+//            exportVO.setTotalWatchDuration(formatSecondsToMinutes(totalSeconds));
+
+            // 订单信息
+            exportVO.setOrderCount(Math.toIntExact(userDetail.getOrderCount()));
+            exportVO.setOrderAmount(formatMoney(userDetail.getOrderAmount()));
+
+            // 公司和销售信息
+            exportVO.setCompanyName(userDetail.getCompanyName());
+            exportVO.setSalesName(userDetail.getSalesName());
+
+            // 是否完课(根据观看时长判断,假设30分钟以上为完课)
+            if (totalSeconds >= 1800) {
+                exportVO.setIsCompleted("是");
+            } else {
+                exportVO.setIsCompleted("否");
+            }
+
+            exportList.add(exportVO);
+        }
+
+        return exportList;
+    }
+
+    /**
+     * 格式化秒数为分钟(保留2位小数)
+     */
+    private String formatSecondsToMinutes(Long seconds) {
+        if (seconds == null || seconds == 0) {
+            return "0.00";
+        }
+        BigDecimal minutes = new BigDecimal(seconds).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
+        return minutes.toString();
+    }
+
+    /**
+     * 格式化金额
+     */
+    private String formatMoney(BigDecimal value) {
+        if (value == null) {
+            return "0.00";
+        }
+        return value.setScale(2, RoundingMode.HALF_UP).toString();
+    }
+
 }

+ 1 - 0
fs-service/src/main/java/com/fs/live/vo/LiveDataDetailVo.java

@@ -96,3 +96,4 @@ public class LiveDataDetailVo {
 }
 
 
+

+ 56 - 0
fs-service/src/main/java/com/fs/live/vo/LiveUserDetailExportVO.java

@@ -0,0 +1,56 @@
+package com.fs.live.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+/**
+ * 直播间用户详情导出VO
+ *
+ * @author fs
+ * @date 2025-12-02
+ */
+@Data
+public class LiveUserDetailExportVO {
+
+    /** 用户ID */
+    @Excel(name = "用户ID")
+    private Long userId;
+
+    /** 用户名称 */
+    @Excel(name = "用户名称")
+    private String userName;
+
+    /** 直播观看时长(分钟) */
+    @Excel(name = "直播观看时长(分钟)")
+    private String liveWatchDuration;
+
+    /** 回放观看时长(分钟) */
+    @Excel(name = "回放观看时长(分钟)")
+    private String playbackWatchDuration;
+
+//    /** 总观看时长(分钟) */
+//    @Excel(name = "总观看时长(分钟)")
+//    private String totalWatchDuration;
+
+    /** 订单数 */
+    @Excel(name = "订单数")
+    private Integer orderCount;
+
+    /** 订单金额(元) */
+    @Excel(name = "订单金额(元)")
+    private String orderAmount;
+
+    /** 分公司 */
+    @Excel(name = "分公司")
+    private String companyName;
+
+    /** 销售 */
+    @Excel(name = "销售")
+    private String salesName;
+
+    /** 是否完课 */
+    @Excel(name = "是否完课")
+    private String isCompleted;
+
+}
+

+ 1 - 0
fs-service/src/main/java/com/fs/live/vo/LiveUserDetailVo.java

@@ -38,3 +38,4 @@ public class LiveUserDetailVo {
 }
 
 
+

+ 1 - 0
fs-service/src/main/java/com/fs/live/vo/ProductSalesVo.java

@@ -26,3 +26,4 @@ public class ProductSalesVo {
 }
 
 
+

+ 4 - 4
fs-service/src/main/resources/mapper/live/LiveDataMapper.xml

@@ -412,7 +412,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectLiveDataDetailBySql" resultType="com.fs.live.vo.LiveDataDetailVo">
         SELECT
             COALESCE(video_duration.total_duration, 0) AS videoDuration,
-            COUNT(DISTINCT lwu.user_id) AS totalViewers,
+            (COUNT(DISTINCT CASE WHEN lwu.live_flag = 1 AND lwu.replay_flag = 0 THEN lwu.user_id END) +  COUNT(DISTINCT CASE WHEN lwu.live_flag = 0 AND lwu.replay_flag = 1 THEN lwu.user_id END)) AS totalViewers,
             COUNT(DISTINCT CASE
                 WHEN lwu.online_seconds >= COALESCE(video_duration.total_duration, 0) AND video_duration.total_duration > 0
                 THEN lwu.user_id
@@ -536,9 +536,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             WHERE live_id = #{liveId} AND user_id IS NOT NULL AND user_id != ''
             GROUP BY user_id
         ) order_info ON lwu.user_id = order_info.user_id
-        LEFT JOIN fs_user_company_user fucu ON lwu.user_id = fucu.user_id
-        LEFT JOIN company c ON fucu.company_id = c.company_id
-        LEFT JOIN company_user cu ON fucu.company_user_id = cu.user_id
+        left join live_user_first_entry lufe on lwu.live_id = lufe.live_id and lwu.user_id = lufe.user_id
+        LEFT JOIN company c ON lufe.company_id = c.company_id
+        LEFT JOIN company_user cu ON lufe.company_user_id = cu.user_id
         WHERE lwu.live_id = #{liveId}
         GROUP BY u.user_id, u.nick_name, u.nickname, order_info.orderCount, order_info.orderAmount, c.company_name, cu.user_name
         ORDER BY order_info.orderAmount DESC, liveWatchDuration DESC

+ 48 - 1
fs-user-app/src/main/java/com/fs/app/controller/live/LiveGoodsController.java

@@ -9,6 +9,13 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.his.service.IFsStoreProductService;
+import com.fs.hisStore.domain.FsStoreProductAttrScrm;
+import com.fs.hisStore.domain.FsStoreProductAttrValueScrm;
+import com.fs.hisStore.domain.FsStoreProductRelationScrm;
+import com.fs.hisStore.domain.FsStoreProductScrm;
+import com.fs.hisStore.service.IFsStoreProductAttrScrmService;
+import com.fs.hisStore.service.IFsStoreProductAttrValueScrmService;
+import com.fs.hisStore.service.IFsStoreProductRelationScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
 import com.fs.live.domain.LiveGoods;
 import com.fs.live.service.ILiveGoodsService;
@@ -17,6 +24,7 @@ import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -37,6 +45,13 @@ public class LiveGoodsController extends AppBaseController
 
     @Autowired
     private RedisCache redisCache;
+    @Autowired
+    private IFsStoreProductAttrScrmService attrService;
+    @Autowired
+    private IFsStoreProductRelationScrmService productRelationService;
+
+    @Autowired
+    private IFsStoreProductAttrValueScrmService attrValueService;
 
     /**
      * 查询直播商品列表
@@ -119,7 +134,39 @@ public class LiveGoodsController extends AppBaseController
     @GetMapping("/liveGoodsDetail/{productId}")
     public R liveGoodsDetail(@PathVariable Long productId)
     {
-        return R.ok().put("data",fsStoreProductService.selectFsStoreProductById(productId));
+        FsStoreProductScrm product = fsStoreProductService.selectFsStoreProductById(productId);
+        if(product==null){
+            return R.error("商品不存在或已下架");
+        }
+        List<FsStoreProductAttrScrm> productAttr=attrService.selectFsStoreProductAttrByProductId(productId);
+        List<FsStoreProductAttrValueScrm> productValues=attrValueService.selectFsStoreProductAttrValueByProductId(productId);
+//获取用户的TOKEN写入足迹
+        String userId=getUserId();
+        if(userId!=null){
+            FsStoreProductRelationScrm productRelation=new FsStoreProductRelationScrm();
+            productRelation.setIsDel(0);
+            productRelation.setUserId(Long.parseLong(userId));
+            productRelation.setProductId(product.getProductId());
+            productRelation.setType("foot");
+            List<FsStoreProductRelationScrm> productRelations=productRelationService.selectFsStoreProductRelationList(productRelation);
+            if(productRelations!=null&&productRelations.size()>0){
+                FsStoreProductRelationScrm relation=productRelations.get(0);
+                relation.setUpdateTime(new Date());
+                productRelationService.updateFsStoreProductRelation(relation);
+            }
+            else{
+                FsStoreProductRelationScrm relation=new FsStoreProductRelationScrm();
+                relation.setUserId(Long.parseLong(userId));
+                relation.setIsDel(0);
+                relation.setProductId(product.getProductId());
+                relation.setUpdateTime(new Date());
+                relation.setType("foot");
+                relation.setCreateTime(new Date());
+                relation.setUpdateTime(new Date());
+                productRelationService.insertFsStoreProductRelation(relation);
+            }
+        }
+        return R.ok().put("product",product).put("productAttr",productAttr).put("productValues",productValues);
     }
 
     /**