Pārlūkot izejas kodu

Merge branch 'refs/heads/master' into feature_netty连接_20260617

yuhongqi 1 nedēļu atpakaļ
vecāks
revīzija
491682092b
40 mainītis faili ar 670 papildinājumiem un 79 dzēšanām
  1. 30 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreDeliveryAbnormalOrderController.java
  2. 1 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java
  3. 1 0
      fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java
  4. 7 0
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  5. 9 8
      fs-company-app/src/main/java/com/fs/app/controller/LiveController.java
  6. 4 3
      fs-service/src/main/java/com/fs/app/service/impl/AppPayServiceImpl.java
  7. 3 1
      fs-service/src/main/java/com/fs/company/service/ICompanyVoiceRoboticCallLogCallphoneService.java
  8. 39 0
      fs-service/src/main/java/com/fs/course/dto/VideoCollectionDTO.java
  9. 62 18
      fs-service/src/main/java/com/fs/course/mapper/FsUserVideoMapper.java
  10. 1 1
      fs-service/src/main/java/com/fs/course/param/FsUserVideoCommentDelUParam.java
  11. 13 4
      fs-service/src/main/java/com/fs/course/service/impl/FsUserVideoCommentServiceImpl.java
  12. 1 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserVideoServiceImpl.java
  13. 10 0
      fs-service/src/main/java/com/fs/course/vo/FsUserVideoListUVO.java
  14. 3 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java
  15. 4 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreProductScrm.java
  16. 12 0
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java
  17. 4 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreProductAddEditParam.java
  18. 10 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsExpressScrmService.java
  19. 5 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java
  20. 155 13
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsExpressScrmServiceImpl.java
  21. 7 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java
  22. 73 13
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  23. 1 1
      fs-service/src/main/java/com/fs/hisStore/service/impl/MergedOrderServiceImpl.java
  24. 54 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreDeliveryAbnormalOrderExportVO.java
  25. 5 0
      fs-service/src/main/java/com/fs/live/service/ILiveSortLinkService.java
  26. 28 2
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  27. 43 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveSortLinkServiceImpl.java
  28. 13 2
      fs-service/src/main/java/com/fs/qw/vo/QwUserVoiceLogTotalVo.java
  29. 17 1
      fs-service/src/main/resources/db/changelog/changes/20260613-live-user-add-is-del.sql
  30. 1 0
      fs-service/src/main/resources/db/changelog/db.changelog-master.xml
  31. 17 0
      fs-service/src/main/resources/db/changelog/dictData/dict_data_update.sql
  32. 5 5
      fs-service/src/main/resources/mapper/course/FsUserTalentFollowMapper.xml
  33. 13 0
      fs-service/src/main/resources/mapper/course/FsUserVideoMapper.xml
  34. 5 1
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  35. 7 2
      fs-service/src/main/resources/mapper/hisStore/FsStoreProductScrmMapper.xml
  36. 3 1
      fs-service/src/main/resources/mapper/qw/QwUserVoiceLogMapper.xml
  37. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/TalentController.java
  38. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/VideoController.java
  39. 1 0
      fs-user-app/src/main/java/com/fs/app/controller/store/PayScrmController.java
  40. 1 0
      fs-user-app/src/main/java/com/fs/app/controller/store/WxPayScrmController.java

+ 30 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreDeliveryAbnormalOrderController.java

@@ -1,9 +1,13 @@
 package com.fs.hisStore.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.domain.model.LoginUser;
+import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.CloudHostUtils;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -31,6 +35,7 @@ import com.fs.hisStore.service.IFsStoreOrderItemScrmService;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.hisStore.service.IFsStoreOrderStatusScrmService;
 import com.fs.hisStore.service.IFsStorePaymentScrmService;
+import com.fs.hisStore.vo.FsStoreDeliveryAbnormalOrderExportVO;
 import com.fs.hisStore.vo.FsStoreOrderAuditLogVO;
 import com.fs.hisStore.vo.FsStoreOrderVO;
 import com.github.pagehelper.PageHelper;
@@ -130,6 +135,31 @@ public class FsStoreDeliveryAbnormalOrderController extends BaseController {
         return vo;
     }
 
+    /**
+     * 导出物流异常订单
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeDeliveryAbnormalOrder:export')")
+    @Log(title = "物流异常订单", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public AjaxResult export(@RequestBody FsStoreOrderParam param) {
+        normalizeTimeRange(param);
+        param.setDeliveryStatus(4);
+        if (fsStoreOrderService.isEntityNull(param)) {
+            return AjaxResult.error("请筛选数据导出");
+        }
+        List<FsStoreOrderVO> list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+        maskSensitiveFields(list);
+        List<FsStoreDeliveryAbnormalOrderExportVO> exportList = new ArrayList<>();
+        for (FsStoreOrderVO vo : list) {
+            FsStoreDeliveryAbnormalOrderExportVO exportVO = new FsStoreDeliveryAbnormalOrderExportVO();
+            BeanUtils.copyProperties(vo, exportVO);
+            exportList.add(exportVO);
+        }
+        ExcelUtil<FsStoreDeliveryAbnormalOrderExportVO> util =
+                new ExcelUtil<>(FsStoreDeliveryAbnormalOrderExportVO.class);
+        return util.exportExcel(exportList, "物流异常订单");
+    }
+
     /**
      * 获取物流异常订单详情
      */

+ 1 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java

@@ -168,6 +168,7 @@ public class FsStorePaymentScrmController extends BaseController
                     String[] order=o.getOrg_req_seq_id().split("-");
                     switch (order[0]) {
                         case "store":
+                        case "live":
                             orderService.payConfirm(1,null,order[1], o.getOrg_hf_seq_id(),o.getOut_trans_id(),o.getParty_order_id());
                             break;
                         case "store_remain":

+ 1 - 0
fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java

@@ -721,6 +721,7 @@ public class MallStoreTask
                 if(orderResult.getStatus().equals("100")){
                     switch (order[0]) {
                         case "store":
+                        case "live":
                             orderService.payConfirm(1,null,order[1], o.getUpOrderId(),orderResult.getBankTrxId(),orderResult.getBankOrderId());
                         case "store_remain":
                             orderService.payRemainConfirm( order[1], o.getUpOrderId(),orderResult.getBankTrxId(),orderResult.getBankOrderId());

+ 7 - 0
fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -400,6 +400,13 @@ public class FsUserCourseVideoController extends AppBaseController {
         return openImResponseDTO;
     }
 
+
+    @GetMapping("/realLinkByLink")
+    @ApiOperation("根据短链link查询真实链接")
+    public R getRealLinkByLink(@RequestParam String link) {
+        return courseLinkService.getRealLink(link);
+    }
+
     @Login
     @ApiOperation("app-看课记录(包含今日完课、今日催课)")
     @GetMapping("/courseWatchLog")

+ 9 - 8
fs-company-app/src/main/java/com/fs/app/controller/LiveController.java

@@ -32,22 +32,19 @@ public class LiveController extends AppBaseController {
     @Autowired
     private ILiveSortLinkService liveSortLinkService;
 
-    @Login
+
     @GetMapping("/pageList")
     @ApiOperation("未开播/直播中直播间分页列表")
     public ResponseResult<PageInfo<Live>> pageList(FsLiveListParam param) {
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
-        param.setCompanyId(getCompanyId());
         List<Live> list = liveService.listAppAvailableLive(param);
         return ResponseResult.ok(new PageInfo<>(list));
     }
 
-    @Login
+
     @PostMapping("/liveSortLink")
     @ApiOperation("生成直播分享链接")
     public R createLiveSortLink(@RequestBody FsLiveSortLinkParam param) {
-        param.setCompanyId(getCompanyId());
-        param.setCompanyUserId(getCompanyUserId());
         R liveSortLink = liveSortLinkService.createLiveSortLink(param);
         Object url = liveSortLink.get("url");
         if (url == null) {
@@ -60,12 +57,10 @@ public class LiveController extends AppBaseController {
         return R.ok(map);
     }
 
-    @Login
+
     @PostMapping("/liveSortLinkTo")
     @ApiOperation("生成直播分享短链(APP发课)")
     public R createLiveSortLinkTo(@RequestBody FsLiveSortLinkParam param) {
-        param.setCompanyId(getCompanyId());
-        param.setCompanyUserId(getCompanyUserId());
         R liveSortLink = liveSortLinkService.createAppLiveSortLink(param);
         Object url = liveSortLink.get("url");
         if (url == null) {
@@ -85,4 +80,10 @@ public class LiveController extends AppBaseController {
         return ResponseResult.ok(liveService.getGotoWxAppLiveLink(linkStr, appid));
     }
 
+    @GetMapping("/realLinkByLink")
+    @ApiOperation("根据短链link查询真实链接")
+    public R getRealLinkByLink(@RequestParam String link) {
+        return liveSortLinkService.getRealLinkByLink(link);
+    }
+
 }

+ 4 - 3
fs-service/src/main/java/com/fs/app/service/impl/AppPayServiceImpl.java

@@ -118,15 +118,16 @@ public class AppPayServiceImpl implements AppPayService {
                 inquiryOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
                 break;
             case "store":
+            case "live":
                 storeOrderService.payConfirm(1, null,tradeNoArr[1],"",result.getTransactionId(),"");
                 break;
                 // 表示app的处方订单
             case "storeOrder":
                 fsStoreOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
                 break;
-            case "live":
-                liveOrderService.payConfirm(1, null,tradeNoArr[1],"",result.getTransactionId(),"");
-                break;
+//            case "live":
+//                liveOrderService.payConfirm(1, null,tradeNoArr[1],"",result.getTransactionId(),"");
+//                break;
             case "package":
                 packageOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
                 break;

+ 3 - 1
fs-service/src/main/java/com/fs/company/service/ICompanyVoiceRoboticCallLogCallphoneService.java

@@ -72,7 +72,6 @@ public interface ICompanyVoiceRoboticCallLogCallphoneService extends IService<Co
      */
     List<CompanyVoiceRoboticCallLogCallphone> selectCompanyVoiceRoboticCallLogCallphoneListData(CompanyVoiceRoboticCallLogCallphone companyVoiceRoboticCallLogCallphone);
 
-    List<CustomerRoboticCallOutCountVO> countRoboticCallOutByCustomerIds(List<Long> customerIds, Long companyId);
 
     List<CalleeRoboticCallOutCountVO> countRoboticCallOutByCalleeIds(List<Long> calleeIds, Long roboticId, Long companyId);
 
@@ -88,4 +87,7 @@ public interface ICompanyVoiceRoboticCallLogCallphoneService extends IService<Co
     CompanyVoiceRoboticCallLogCount selectCompanyVoiceRoboticCallPhoneLogCount();
 
     List<CompanyVoiceRoboticCallLogCallPhoneVO> listByRoboticId(CompanyVoiceRoboticCallLogCallphone companyVoiceRoboticCallLogCallphone);
+
+    List<CustomerRoboticCallOutCountVO> countRoboticCallOutByCustomerIds(List<Long> customerIds, Long companyId);
+
 }

+ 39 - 0
fs-service/src/main/java/com/fs/course/dto/VideoCollectionDTO.java

@@ -0,0 +1,39 @@
+package com.fs.course.dto;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class VideoCollectionDTO {
+    /** 合集ID */
+    private Long collectionId;
+
+    private Long userId;
+    /** 合集标题 */
+    @Excel(name = "合集标题")
+    private String title;
+
+    /** 合集描述 */
+    @Excel(name = "合集描述")
+    private String description;
+
+    /** 合集封面图 */
+    @Excel(name = "合集封面图")
+    private String coverUrl;
+
+    /** 达人ID */
+    @Excel(name = "达人ID")
+    private Long talentId;
+
+    /** 状态:1正常 0下架 */
+    @Excel(name = "状态:1正常 0下架")
+    private Long status;
+
+    /** 合集标签 */
+    @Excel(name = "合集标签")
+    private String tags;
+
+    private int count;
+
+    private Boolean isFavorite;
+}

+ 62 - 18
fs-service/src/main/java/com/fs/course/mapper/FsUserVideoMapper.java

@@ -131,20 +131,38 @@ public interface FsUserVideoMapper
     @Update("update fs_user_video set favorite_num=favorite_num-1 where video_id=#{videoId}")
     int minusFavorite(Long videoId);
 
-    @Select({"<script> " +
-            "select v.video_id as id,v.title,v.description as msg,t.user_id,t.nick_name as username,t.avatar as headImg, " +
-            "v.thumbnail as cover,v.url as src,v.likes as likeNum,v.comments as smsNum,v.favorite_num," +
-            "v.create_time,v.views as playNumber,v.product_id,p.img_url,p.package_name,v.upload_type,v.shares,v.add_num from fs_user_video v " +
-            "left join fs_user_talent t on t.talent_id = v.talent_id " +
-            " left join fs_package p on p.package_id = v.product_id " +
-            "where v.is_del = 0 and v.status = 1  " +
-            " and v.is_audit = 1 " +
-            "<if test = ' maps.keyword!=null and maps.keyword != \"\" '> " +
-            "and v.title like CONCAT('%',#{maps.keyword},'%') " +
-            "</if>" +
-            " order by RAND() "+
-            "</script>"})
-    List<FsUserVideoListUVO> selectFsUserVideoListUVO(@Param("maps") FsUserVideoListUParam param);
+//    @Select({"<script> " +
+//            "select v.video_id as id,v.title,v.description as msg,t.user_id,t.nick_name as username,t.avatar as headImg, " +
+//            "v.thumbnail as cover,v.url as src,v.likes as likeNum,v.comments as smsNum,v.favorite_num," +
+//            "v.create_time,v.views as playNumber,v.product_id,p.img_url,p.package_name,v.upload_type,v.shares,v.add_num from fs_user_video v " +
+//            "left join fs_user_talent t on t.talent_id = v.talent_id " +
+//            " left join fs_package p on p.package_id = v.product_id " +
+//            "where v.is_del = 0 and v.status = 1  " +
+//            " and v.is_audit = 1 " +
+//            "<if test = ' maps.keyword!=null and maps.keyword != \"\" '> " +
+//            "and v.title like CONCAT('%',#{maps.keyword},'%') " +
+//            "</if>" +
+//            " order by RAND() "+
+//            "</script>"})
+//    List<FsUserVideoListUVO> selectFsUserVideoListUVO(@Param("maps") FsUserVideoListUParam param);
+@Select({"<script> " +
+        "select v.video_id as id,v.talent_id as talentId,t.user_id as userId,v.title,v.description as msg,t.nick_name as username,t.avatar as headImg, " +
+        "v.thumbnail as cover,v.url as src,v.likes as likeNum,v.comments as smsNum,v.favorite_num as favoriteNum," +
+        "v.create_time,v.views as playNumber,v.product_id,p.img_url,p.package_name,v.upload_type,v.shares,v.add_num " +
+        "<if test = 'maps.userId != null'> " +
+        ",CASE WHEN EXISTS (SELECT 1 FROM fs_user_talent_follow tf WHERE tf.talent_id = v.talent_id AND tf.user_id = #{maps.userId}) THEN '1' ELSE '0' END as isFollow " +
+        "</if> " +
+        "from fs_user_video v " +
+        "left join fs_user_talent t on t.talent_id = v.talent_id " +
+        " left join fs_package p on p.package_id = v.product_id " +
+        "where v.is_del = 0 and v.status = 1  " +
+        " and v.is_audit = 1 " +
+        "<if test = ' maps.keyword!=null and maps.keyword != \"\" '> " +
+        "and v.title like CONCAT('%',#{maps.keyword},'%') " +
+        "</if>" +
+        " order by v.create_time desc "+
+        "</script>"})
+List<FsUserVideoListUVO> selectFsUserVideoListUVO(@Param("maps") FsUserVideoListUParam param);
 
     @Update("UPDATE fs_user_video SET comments = comments+#{commentCount} WHERE video_id = #{videoId}")
     void updateCommentCount(@Param("videoId") Long videoId, @Param("commentCount") Integer commentCount);
@@ -251,10 +269,31 @@ public interface FsUserVideoMapper
             "where v.is_del = 0 and  v.status = 1 and f.user_id = #{userId}")
     int countFavoriteVideos(@Param("userId") Long userId);
 
+//    @Select({"<script> " +
+//            "select v.video_id as id,v.title,v.description as msg,t.nick_name as username,t.avatar as headImg, " +
+//            "v.thumbnail as cover,v.url as src,v.likes as likeNum,v.comments as smsNum,v.favorite_num," +
+//            "v.create_time,v.views as playNumber,v.product_id,p.img_url,p.package_name,v.upload_type,v.shares,v.add_num,v.is_audit,v.status from fs_user_video v " +
+//            "left join fs_user_talent t on t.talent_id = v.talent_id " +
+//            " left join fs_package p on p.package_id = v.product_id " +
+//            "where v.is_del = 0 and (" +
+//            "(#{oneSelf} = true and (v.is_audit = -1 or v.is_audit = 0 or v.is_audit = 1)) or " +
+//            "(#{oneSelf} = false and v.is_audit = 1 and v.status = 1)" +
+//            ") " +
+//            "<if test = ' talentId!=null and talentId != \"\" '> " +
+//            "and v.talent_id = #{talentId}" +
+//            " order by v.create_time" +
+//            "</if>" +
+//            "</script>"})
+//    List<FsUserVideoListUVO> selectFsUserVideoListUVOByUser(@Param("talentId") Long talentId, @Param("oneSelf") boolean oneSelf);
+
     @Select({"<script> " +
-            "select v.video_id as id,v.title,v.description as msg,t.nick_name as username,t.avatar as headImg, " +
-            "v.thumbnail as cover,v.url as src,v.likes as likeNum,v.comments as smsNum,v.favorite_num," +
-            "v.create_time,v.views as playNumber,v.product_id,p.img_url,p.package_name,v.upload_type,v.shares,v.add_num,v.is_audit,v.status from fs_user_video v " +
+            "select v.video_id as id,v.talent_id as talentId,t.user_id as userId,v.title,v.description as msg,t.nick_name as username,t.avatar as headImg, " +
+            "v.thumbnail as cover,v.url as src,v.likes as likeNum,v.comments as smsNum,v.favorite_num as favoriteNum," +
+            "v.create_time,v.views as playNumber,v.product_id,p.img_url,p.package_name,v.upload_type,v.shares,v.add_num,v.is_audit,v.fail_reason,v.status" +
+            "<if test = 'userId != null'> " +
+            ",CASE WHEN EXISTS (SELECT 1 FROM fs_user_talent_follow tf WHERE tf.talent_id = v.talent_id AND tf.user_id = #{userId}) THEN '1' ELSE '0' END as isFollow " +
+            "</if> " +
+            "from fs_user_video v " +
             "left join fs_user_talent t on t.talent_id = v.talent_id " +
             " left join fs_package p on p.package_id = v.product_id " +
             "where v.is_del = 0 and (" +
@@ -266,6 +305,11 @@ public interface FsUserVideoMapper
             " order by v.create_time" +
             "</if>" +
             "</script>"})
-    List<FsUserVideoListUVO> selectFsUserVideoListUVOByUser(@Param("talentId") Long talentId, @Param("oneSelf") boolean oneSelf);
+    List<FsUserVideoListUVO> selectFsUserVideoListUVOByUser(@Param("talentId") Long talentId, @Param("oneSelf") boolean oneSelf, @Param("userId") Long userId);
+
+    // 评论数加一
+    int addCommentCount(Long videoId);
+
+    int delCommentCount(Long videoId);
 }
 

+ 1 - 1
fs-service/src/main/java/com/fs/course/param/FsUserVideoCommentDelUParam.java

@@ -20,7 +20,7 @@ public class FsUserVideoCommentDelUParam implements Serializable
     private Long commentId;
 
 //    @NotNull(message = "视频ID不能为空")
-//    private Long videoId;
+    private Long videoId;
 
     private String parentId;
 }

+ 13 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsUserVideoCommentServiceImpl.java

@@ -7,6 +7,7 @@ import java.util.stream.Collectors;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.course.mapper.FsUserVideoCommentLikeMapper;
+import com.fs.course.mapper.FsUserVideoMapper;
 import com.fs.course.param.FsUserVideoCommentAddUParam;
 import com.fs.course.param.FsUserVideoCommentDelUParam;
 import com.fs.course.param.FsUserVideoCommentUParam;
@@ -48,6 +49,9 @@ public class FsUserVideoCommentServiceImpl implements IFsUserVideoCommentService
     @Autowired
     private FsUserMapper fsUserMapper;
 
+    @Autowired
+    private FsUserVideoMapper fsUserVideoMapper;
+
     private static final String COMMENT_LIST_KEY_PREFIX = "comment:list:video:";
     private static final String COMMENT_HASH_KEY_PREFIX = "comment:hash:video:";
     private static final String REPLY_LIST_KEY_PREFIX = "reply:list:comment:";
@@ -191,6 +195,8 @@ public class FsUserVideoCommentServiceImpl implements IFsUserVideoCommentService
             comment.setParentId(param.getParentId());
         }
         if (fsUserVideoCommentMapper.insertFsUserVideoComment(comment)>0){
+            // 更新对应的评论数
+            fsUserVideoMapper.addCommentCount(comment.getVideoId());
             return R.ok().put("data",comment);
         };
         return R.error("新增评论失败");
@@ -486,11 +492,14 @@ public class FsUserVideoCommentServiceImpl implements IFsUserVideoCommentService
     @Transactional
     public R delComment(FsUserVideoCommentDelUParam param) {
         // 更新评论数
-        if (param.getParentId() == null) {
-            //除数据库中的回复
-            fsUserVideoCommentMapper.deleteByParentId(param.getCommentId().toString());
-        }
+//        if (param.getParentId() == null) {
+//            //除数据库中的回复
+//            fsUserVideoCommentMapper.deleteByParentId(param.getCommentId().toString());
+//        }
+
         fsUserVideoCommentMapper.deleteByCommentId(param.getCommentId());
+        // 评论数减一
+        fsUserVideoMapper.delCommentCount(param.getVideoId());
         return R.ok();
     }
 

+ 1 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserVideoServiceImpl.java

@@ -381,7 +381,7 @@ public class FsUserVideoServiceImpl implements IFsUserVideoService {
 
     @Override
     public List<FsUserVideoListUVO> selectFsUserVideoListUVOByUser(Long talentId, boolean oneSelf, Long userId) {
-        List<FsUserVideoListUVO> list = fsUserVideoMapper.selectFsUserVideoListUVOByUser(talentId, oneSelf);
+        List<FsUserVideoListUVO> list = fsUserVideoMapper.selectFsUserVideoListUVOByUser(talentId, oneSelf,userId);
         /*if (param != null && param.getUserId() != null) {
             Long userId = param.getUserId();
             list = selectLikesAndFavorites(userId, list);

+ 10 - 0
fs-service/src/main/java/com/fs/course/vo/FsUserVideoListUVO.java

@@ -1,6 +1,7 @@
 package com.fs.course.vo;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.course.dto.VideoCollectionDTO;
 import lombok.Data;
 
 import java.util.Date;
@@ -10,6 +11,8 @@ import java.util.List;
 public class FsUserVideoListUVO {
     private String id; // _id
     private Long userId;
+    private Long talentId;//视频发布的达人id
+    private String isFollow;//当前用户是否关注发布视频的达人
     private String username;//2.视频拥有者名称
     private String headImg;//3.发布者头像
     private String cover;//视频封面
@@ -39,4 +42,11 @@ public class FsUserVideoListUVO {
     private Integer uploadType;
     private Long shares;
     private String addNum; //随机添加数
+    private Integer isAudit;
+    private Integer status;
+    private String failReason;
+    private Boolean isInCollection;
+    //合集信息
+    private VideoCollectionDTO videoCollectionDTO;
+    private String thumbnail;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java

@@ -269,6 +269,9 @@ public class FsStoreOrderScrm extends BaseEntity
     @Excel(name = "发货时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date deliverySendTime;
 
+    /** 物流订阅成功的发货人手机号 */
+    private String senderPhone;
+
     //凭证
     private String certificates;
 

+ 4 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsStoreProductScrm.java

@@ -322,6 +322,10 @@ public class FsStoreProductScrm extends BaseEntity
     @Excel(name = "退货地址")
     private String returnAddress;
 
+    /** 发货人手机号,多个逗号分隔,最多3个 */
+    @Excel(name = "发货人手机号")
+    private String senderPhones;
+
 
     /** 原产地 */
     @Excel(name = "原产地")

+ 12 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java

@@ -512,6 +512,18 @@ public interface FsStoreOrderScrmMapper
      */
     @Update("UPDATE fs_store_order_scrm SET outer_oi_id = #{outerOiId} WHERE order_code = #{orderCode}")
     int updateOuterOiIdByOrderCode(@Param("orderCode") String orderCode, @Param("outerOiId") String outerOiId);
+
+    /**
+     * 根据订单号更新物流订阅成功的发货人手机号
+     */
+    @Update("UPDATE fs_store_order_scrm SET sender_phone = #{senderPhone} WHERE order_code = #{orderCode}")
+    int updateSenderPhoneByOrderCode(@Param("orderCode") String orderCode, @Param("senderPhone") String senderPhone);
+
+    /**
+     * 根据订单号查询物流订阅成功的发货人手机号
+     */
+    @Select("SELECT sender_phone FROM fs_store_order_scrm WHERE order_code = #{orderCode} LIMIT 1")
+    String selectSenderPhoneByOrderCode(@Param("orderCode") String orderCode);
     @Update("update fs_store_order_scrm set status=-3 where id=#{orderId}")
     int cancelOrder(Long orderId);
     @Select({"<script> " +

+ 4 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreProductAddEditParam.java

@@ -268,6 +268,10 @@ public class FsStoreProductAddEditParam implements Serializable
     @Excel(name = "退货地址")
     private String returnAddress;
 
+    /** 发货人手机号,多个逗号分隔,最多3个 */
+    @Excel(name = "发货人手机号")
+    private String senderPhones;
+
 
     private Integer isDrug;
 

+ 10 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsExpressScrmService.java

@@ -82,6 +82,16 @@ public interface IFsExpressScrmService
 
     void subscribeEspress(String orderCode, String deliverySn, String deliveryId, String userPhone);
 
+    /**
+     * 使用发货人手机号优先订阅物流(最多3个发货人手机号,失败后使用收货人手机号)
+     */
+    void subscribeEspressWithSenderPhones(String orderCode, String deliverySn, String deliveryId, String userPhone, String senderPhones);
+
+    /**
+     * 根据字典配置选择订阅方式
+     */
+    void subscribeExpressSmart(String orderCode, String deliverySn, String deliveryId, String userPhone, String senderPhones);
+
     R parseAddress(String content);
 
 

+ 5 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java

@@ -125,6 +125,11 @@ public interface IFsStoreOrderScrmService
 
     void cancelOrder(Long orderId);
 
+    /**
+     * 退回订单优惠券(商城券 / 直播券)
+     */
+    void refundOrderCoupon(FsStoreOrderScrm order);
+
     void refundPrescribeOrder(Long orderId);
 
     void refundOrder(Long orderId);

+ 155 - 13
fs-service/src/main/java/com/fs/hisStore/service/impl/FsExpressScrmServiceImpl.java

@@ -3,9 +3,11 @@ package com.fs.hisStore.service.impl;
 import java.net.URLEncoder;
 import java.security.MessageDigest;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
@@ -29,6 +31,8 @@ import com.fs.hisStore.param.FsStoreOrderExpressParam;
 import com.fs.live.domain.LiveOrder;
 import com.fs.live.mapper.LiveOrderMapper;
 import com.fs.system.service.ISysConfigService;
+import com.fs.system.service.ISysDictTypeService;
+import com.fs.common.core.domain.entity.SysDictData;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,6 +52,8 @@ import org.springframework.util.Base64Utils;
 @Service
 public class FsExpressScrmServiceImpl implements IFsExpressScrmService
 {
+    private static final String STORE_EXPRESS_SENDER_PHONE_SUBSCRIBE = "store_express_sender_phone";
+
     Logger logger = LoggerFactory.getLogger(FsExpressScrmServiceImpl.class);
     @Autowired
     private FsExpressScrmMapper fsExpressMapper;
@@ -56,6 +62,9 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
     @Autowired
     private ISysConfigService configService;
 
+    @Autowired
+    private ISysDictTypeService sysDictTypeService;
+
     @Autowired
     private LiveOrderMapper liveOrderMapper;
     /**
@@ -134,11 +143,12 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
 
     @Override
     public ExpressInfoDTO getExpressInfo(String OrderCode, String ShipperCode, String LogisticCode, String lastFourNumber)     {
+        String customerName = resolveExpressQueryPhone(OrderCode, ShipperCode, lastFourNumber);
 
         //处理顺丰查询轨迹需手机号码后4位
         String requestData;
         if (ShipperCode.equals(ShipperCodeEnum.SF.getValue()) || ShipperCode.equals(ShipperCodeEnum.ZTO.getValue())) {
-            requestData = "{'OrderCode':'" + OrderCode + "','ShipperCode':'" + ShipperCode + "','LogisticCode':'" + LogisticCode + "','CustomerName':'" + lastFourNumber + "'}";
+            requestData = "{'OrderCode':'" + OrderCode + "','ShipperCode':'" + ShipperCode + "','LogisticCode':'" + LogisticCode + "','CustomerName':'" + customerName + "'}";
         } else {
             requestData = "{'OrderCode':'" + OrderCode + "','ShipperCode':'" + ShipperCode + "','LogisticCode':'" + LogisticCode + "'}";
         }
@@ -215,7 +225,57 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
 
     @Override
     public void subscribeEspress(String orderCode, String deliverySn, String deliveryId, String userPhone) {
-        //处理顺丰查询轨迹需手机号码后4位
+        ExpressInfoDTO dto = doSubscribeRequest(orderCode, deliverySn, deliveryId, userPhone);
+        if (dto == null || !dto.isSuccess()) {
+            logger.error("订阅物流失败:orderCode={}, deliveryId={}, reason={}",
+                    orderCode, deliveryId, dto != null ? dto.getReason() : "订阅物流返回为空");
+            afterExpressFailure(orderCode, deliveryId, dto != null ? dto.getReason() : "订阅物流返回为空");
+            throw new CustomException(dto != null && StringUtils.isNotBlank(dto.getReason()) ? dto.getReason() : "订阅物流失败");
+        }
+    }
+
+    @Override
+    public void subscribeEspressWithSenderPhones(String orderCode, String deliverySn, String deliveryId, String userPhone, String senderPhones) {
+        List<String> senderPhoneList = parseSenderPhones(senderPhones);
+        if (!senderPhoneList.isEmpty()) {
+            for (String senderPhone : senderPhoneList) {
+                String customerName = resolveCustomerName(deliverySn, senderPhone);
+                ExpressInfoDTO dto = doSubscribeRequest(orderCode, deliverySn, deliveryId, customerName);
+                if (dto != null && dto.isSuccess()) {
+                    logger.info("订阅物流成功(发货人手机号): orderCode={}, phone={}", orderCode, senderPhone);
+                    updateOrderSenderPhoneByOrderCode(orderCode, senderPhone);
+                    return;
+                }
+                if (isPhoneError(dto)) {
+                    logger.warn("发货人手机号订阅失败,尝试下一个: orderCode={}, phone={}, reason={}",
+                            orderCode, senderPhone, dto != null ? dto.getReason() : null);
+                    continue;
+                }
+                logger.warn("订阅物流失败(非手机号错误),改用收货人手机号: orderCode={}, reason={}",
+                        orderCode, dto != null ? dto.getReason() : null);
+                break;
+            }
+        }
+        ExpressInfoDTO receiverDto = doSubscribeRequest(orderCode, deliverySn, deliveryId, userPhone);
+        if (receiverDto == null || !receiverDto.isSuccess()) {
+            logger.error("订阅物流失败(收货人手机号):orderCode={}, deliveryId={}, reason={}",
+                    orderCode, deliveryId, receiverDto != null ? receiverDto.getReason() : "订阅物流返回为空");
+            afterExpressFailure(orderCode, deliveryId, receiverDto != null ? receiverDto.getReason() : "订阅物流返回为空");
+        } else {
+            logger.info("订阅物流成功(收货人手机号): orderCode={}", orderCode);
+        }
+    }
+
+    @Override
+    public void subscribeExpressSmart(String orderCode, String deliverySn, String deliveryId, String userPhone, String senderPhones) {
+        if (isSenderPhoneSubscribeEnabled()) {
+            subscribeEspressWithSenderPhones(orderCode, deliverySn, deliveryId, userPhone, senderPhones);
+        } else {
+            subscribeEspress(orderCode, deliverySn, deliveryId, userPhone);
+        }
+    }
+
+    private ExpressInfoDTO doSubscribeRequest(String orderCode, String deliverySn, String deliveryId, String userPhone) {
         String requestData;
         if (deliverySn.equals(ShipperCodeEnum.SF.getValue()) || deliverySn.equals(ShipperCodeEnum.ZTO.getValue())) {
             requestData = "{'OrderCode':'" + orderCode + "','ShipperCode':'" + deliverySn + "','LogisticCode':'" + deliveryId + "','CustomerName':'" + userPhone + "'}";
@@ -226,25 +286,69 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
         Map<String, Object> params = new HashMap<>();
         try {
             String json = this.configService.selectConfigByKey("his.config");
-            FSSysConfig sysConfig= JSON.parseObject(json,FSSysConfig.class);
+            FSSysConfig sysConfig = JSON.parseObject(json, FSSysConfig.class);
             params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));
-            params.put("EBusinessID",sysConfig.getKdnId().trim());
-            params.put("RequestType", "8001");
+            params.put("EBusinessID", sysConfig.getKdnId().trim());
+            params.put("RequestType", "8008");
             String dataSign = encrypt(requestData, sysConfig.getKdnKeyId().trim(), "UTF-8");
             params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));
             params.put("DataType", "2");
             String result = HttpUtil.post(sysConfig.getKdnSubscribeUrl().trim(), params);
-            logger.info("订阅物流:"+result);
-            ExpressInfoDTO dto = JSONUtil.toBean(result, ExpressInfoDTO.class);
-            if (dto == null || !dto.isSuccess()) {
-                logger.error("订阅物流失败:{}:{}", result, requestData);
-                afterExpressFailure(orderCode, deliveryId, dto != null ? dto.getReason() : "订阅物流返回为空");
+            logger.info("订阅物流:{}", result);
+            return JSONUtil.toBean(result, ExpressInfoDTO.class);
+        } catch (Exception e) {
+            logger.error("订阅物流异常: orderCode={}, deliveryId={}", orderCode, deliveryId, e);
+            return null;
+        }
+    }
+
+    private boolean isSenderPhoneSubscribeEnabled() {
+        List<SysDictData> dictList = sysDictTypeService.selectDictDataByType(STORE_EXPRESS_SENDER_PHONE_SUBSCRIBE);
+        if (dictList == null || dictList.isEmpty()) {
+            return false;
+        }
+        return dictList.stream()
+                .filter(item -> "0".equals(item.getStatus()))
+                .anyMatch(item -> "1".equals(StringUtils.trimToEmpty(item.getDictValue())));
+    }
+
+    private List<String> parseSenderPhones(String senderPhones) {
+        if (StringUtils.isBlank(senderPhones)) {
+            return new ArrayList<>();
+        }
+        return Arrays.stream(senderPhones.split("[,,]"))
+                .map(String::trim)
+                .filter(StringUtils::isNotBlank)
+                .limit(3)
+                .collect(Collectors.toList());
+    }
+
+    private String resolveCustomerName(String deliverySn, String phone) {
+        if (StringUtils.isBlank(phone)) {
+            return "";
+        }
+        if (deliverySn.equals(ShipperCodeEnum.SF.getValue()) || deliverySn.equals(ShipperCodeEnum.ZTO.getValue())) {
+            if (phone.length() == 11) {
+                return StrUtil.sub(phone, phone.length(), -4);
             }
+        }
+        return phone;
+    }
 
-        } catch (Exception e) {
-            afterExpressFailure(orderCode, deliveryId, e.getMessage());
-            throw  new CustomException(e.getMessage());
+    private boolean isPhoneError(ExpressInfoDTO dto) {
+        if (dto == null || dto.isSuccess()) {
+            return false;
         }
+        String reason = StringUtils.trimToEmpty(dto.getReason());
+        if (StringUtils.isBlank(reason)) {
+            return false;
+        }
+        return reason.contains("手机尾号不正确")
+                || reason.contains("手机尾号")
+                || reason.contains("手机")
+                || reason.contains("电话")
+                || reason.contains("CustomerName")
+                || reason.contains("号码");
     }
 
     @Override
@@ -376,6 +480,44 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
         return lastFourNumber;
     }
 
+    /**
+     * 根据订单号查询物流订阅成功的发货人手机号
+     */
+    private String getOrderSenderPhoneByOrderCode(String orderCode) {
+        if (StringUtils.isBlank(orderCode)) {
+            return null;
+        }
+        return fsStoreOrderMapper.selectSenderPhoneByOrderCode(orderCode);
+    }
+
+    /**
+     * 解析物流查询使用的手机号:字典开启且订单有发货人手机号时优先使用,否则使用收货人手机尾号
+     */
+    private String resolveExpressQueryPhone(String orderCode, String shipperCode, String lastFourNumber) {
+        if (!isSenderPhoneSubscribeEnabled() || StringUtils.isBlank(orderCode)) {
+            return lastFourNumber;
+        }
+        String senderPhone = getOrderSenderPhoneByOrderCode(orderCode);
+        if (StringUtils.isBlank(senderPhone)) {
+            return lastFourNumber;
+        }
+        return resolveCustomerName(shipperCode, senderPhone);
+    }
+
+    /**
+     * 根据订单号更新物流订阅成功的发货人手机号
+     */
+    private void updateOrderSenderPhoneByOrderCode(String orderCode, String senderPhone) {
+        if (StringUtils.isBlank(orderCode) || StringUtils.isBlank(senderPhone)) {
+            return;
+        }
+        try {
+            fsStoreOrderMapper.updateSenderPhoneByOrderCode(orderCode, senderPhone);
+        } catch (Exception e) {
+            logger.error("更新订单发货人手机号异常: orderCode={}, senderPhone={}", orderCode, senderPhone, e);
+        }
+    }
+
     /**
      * 快递查询/订阅失败或异常时更新订单物流状态为问题件
      */

+ 7 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java

@@ -1204,6 +1204,9 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
                                 request.setOrdAmt(payment.getPayMoney().setScale(2, RoundingMode.DOWN).toString());
                             }
                             extendInfoMap.put("org_req_seq_id", "store-"+payment.getPayCode());
+                            if("北京卓美".equals(companyName) && order.getOrderType() != null && 2 == order.getOrderType()){
+                                extendInfoMap.put("org_req_seq_id", "live-"+payment.getPayCode());
+                            }
                         }else {
                             if("北京卓美".equals(companyName)){
                                 request.setOrdAmt(refundAmount.setScale(2, RoundingMode.DOWN).toString());
@@ -1246,6 +1249,8 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
         if(order.getTuiUserId()!=null&&order.getTuiUserId()>0){
             userService.subTuiMoney(order);
         }
+        // 优惠券返回(直播订单走 live_coupon_user 回退)
+        orderService.refundOrderCoupon(order);
         // 删除限购记录
         this.deletePurchaseLimitRecordsForStoreOrder(order);
         return R.ok();
@@ -2050,6 +2055,8 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
             }
         }
 
+        // 优惠券返回(直播订单走 live_coupon_user 回退)
+        orderService.refundOrderCoupon(fsStoreOrder);
 
         return i;
     }

+ 73 - 13
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -108,8 +108,10 @@ import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
 import com.fs.huifuPay.service.HuiFuService;
+import com.fs.live.domain.LiveCouponUser;
 import com.fs.live.domain.LiveOrder;
 import com.fs.live.mapper.LiveOrderMapper;
+import com.fs.live.service.ILiveCouponUserService;
 import com.fs.pay.pay.dto.OrderQueryDTO;
 import com.fs.pay.pay.dto.RefundDTO;
 import com.fs.pay.service.IPayService;
@@ -337,6 +339,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     @Autowired
     private IFsStoreCouponUserScrmService couponUserService;
     @Autowired
+    private ILiveCouponUserService liveCouponUserService;
+    @Autowired
     private ICompanyService companyService;
     @Autowired
     private IFsStoreOrderItemScrmService storeOrderItemService;
@@ -678,6 +682,9 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             }
             return rows;
         }
+        if (fsStoreOrder.getDeliveryType() != null && "4".equals(fsStoreOrder.getDeliveryType())) {
+            fsStoreOrder.setDeliveryExceptionStatus(1);
+        }
 
         return fsStoreOrderMapper.updateFsStoreOrder(fsStoreOrder);
     }
@@ -2142,14 +2149,36 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     }
 
 
+    @Override
+    public void refundOrderCoupon(FsStoreOrderScrm order) {
+        refundCoupon(order);
+    }
+
     private void refundCoupon(FsStoreOrderScrm order) {
-        if (order.getCouponId() != null) {
-            FsStoreCouponUserScrm couponUser = couponUserService.selectFsStoreCouponUserById(order.getCouponId());
-            if (couponUser != null) {
-                couponUser.setStatus(0);
-                couponUser.setUseTime(null);
-                couponUserService.updateFsStoreCouponUser(couponUser);
-            }
+        if (order == null || order.getCouponId() == null) {
+            return;
+        }
+        // 直播订单(orderType=2)couponId 存的是 live_coupon_user.id
+        if (order.getOrderType() != null && order.getOrderType() == 2) {
+            refundLiveCoupon(order.getCouponId());
+        }
+//        FsStoreCouponUserScrm couponUser = couponUserService.selectFsStoreCouponUserById(order.getCouponId());
+//        if (couponUser != null) {
+//            couponUser.setStatus(0);
+//            couponUser.setUseTime(null);
+//            couponUserService.updateFsStoreCouponUser(couponUser);
+//        }
+    }
+
+    /**
+     * 直播优惠券回退(与 LiveOrderServiceImpl#refundCoupon 一致)
+     */
+    private void refundLiveCoupon(Long couponUserId) {
+        LiveCouponUser couponUser = liveCouponUserService.selectLiveCouponUserById(couponUserId);
+        if (couponUser != null) {
+            couponUser.setStatus(0);
+            couponUser.setUseTime(null);
+            liveCouponUserService.updateLiveCouponUser(couponUser);
         }
     }
 
@@ -2284,7 +2313,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
                 }
             }
-            expressService.subscribeEspress(order.getOrderCode(), order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
+            subscribeOrderExpress(order, order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
 
             TemplateBean templateBean = TemplateBean.builder()
                     .orderId(order.getId().toString())
@@ -2313,6 +2342,35 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         }
     }
 
+    private String resolveSenderPhonesByOrder(FsStoreOrderScrm order) {
+        if (order == null || StringUtils.isBlank(order.getItemJson())) {
+            return null;
+        }
+        try {
+            com.alibaba.fastjson.JSONArray itemArray = JSON.parseArray(order.getItemJson());
+            if (itemArray == null || itemArray.isEmpty()) {
+                return null;
+            }
+            Long productId = itemArray.getJSONObject(0).getLong("productId");
+            if (productId == null) {
+                return null;
+            }
+            FsStoreProductScrm product = productService.selectFsStoreProductById(productId);
+            return product != null ? product.getSenderPhones() : null;
+        } catch (Exception e) {
+            log.warn("解析订单itemJson获取发货人手机号失败: orderCode={}, error={}", order.getOrderCode(), e.getMessage());
+            return null;
+        }
+    }
+
+    private void subscribeOrderExpress(FsStoreOrderScrm order, String deliverySn, String deliveryId, String lastFourNumber) {
+        if (order == null || StringUtils.isBlank(deliverySn) || StringUtils.isBlank(deliveryId)) {
+            return;
+        }
+        String senderPhones = resolveSenderPhonesByOrder(order);
+        expressService.subscribeExpressSmart(order.getOrderCode(), deliverySn, deliveryId, lastFourNumber, senderPhones);
+    }
+
     @Override
     public void updateDeliveryOrder(Long id, String deliveryId, String deliverCode, String deliverName) {
         FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(id);
@@ -2343,7 +2401,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                         lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
                     }
                 }
-                expressService.subscribeEspress(order.getOrderCode(), express.getCode(), deliveryId, lastFourNumber);
+                subscribeOrderExpress(order, express.getCode(), deliveryId, lastFourNumber);
             }
         }
     }
@@ -3626,6 +3684,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         if (order.getTuiUserId() != null && order.getTuiUserId() > 0) {
             userService.subTuiMoney(order);
         }
+        // 优惠券返回(含直播券)
+        this.refundCoupon(order);
         // 卓美财务要求,如果退款就必须生成售后订单
         // 检查配置,如果delete_after_sales为true,创建退款成功的售后订单
         String deleteAfterSalesConfig = configService.selectConfigByKey("delete_after_sales");
@@ -4820,7 +4880,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                                     }
                                 }
                                 logger.info("物流重新订阅:{}", order.getDeliveryId());
-                                expressService.subscribeEspress(order.getOrderCode(), order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
+                                subscribeOrderExpress(order, order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
                             }
 
                         }
@@ -5212,7 +5272,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                         lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
                     }
                 }
-                expressService.subscribeEspress(o.getOrderCode(), fsStoreOrder.getDeliveryCode(), fsStoreOrder.getDeliverySn(), lastFourNumber);
+                subscribeOrderExpress(o, fsStoreOrder.getDeliveryCode(), fsStoreOrder.getDeliverySn(), lastFourNumber);
 
                 try {
                     String s = fsPrescribeService.PrescribeImg(o.getPrescribeId());
@@ -5308,7 +5368,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
             }
         }
-        expressService.subscribeEspress(order.getOrderCode(), fsStoreOrder.getDeliveryCode(), fsStoreOrder.getDeliverySn(), lastFourNumber);
+        subscribeOrderExpress(order, fsStoreOrder.getDeliveryCode(), fsStoreOrder.getDeliverySn(), lastFourNumber);
         return i;
     }
 
@@ -5637,7 +5697,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                             lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
                         }
                     }
-                    expressService.subscribeEspress(order.getOrderCode(), order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
+                    subscribeOrderExpress(order, order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
 
                     TemplateBean templateBean = TemplateBean.builder()
                             .orderId(order.getId().toString())

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/service/impl/MergedOrderServiceImpl.java

@@ -354,7 +354,7 @@ public class MergedOrderServiceImpl implements IMergedOrderService
             return R.error("订单类型不能为空");
         }
 
-        if (orderType == 1) {
+        if (orderType == 0) {
             // 商城订单
             com.fs.hisStore.domain.FsStoreOrderScrm storeOrder = storeOrderService.selectFsStoreOrderById(orderId);
             if (storeOrder == null) {

+ 54 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreDeliveryAbnormalOrderExportVO.java

@@ -0,0 +1,54 @@
+package com.fs.hisStore.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 物流异常订单导出
+ */
+@Data
+public class FsStoreDeliveryAbnormalOrderExportVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Excel(name = "ID")
+    private Long id;
+
+    @Excel(name = "所属公司")
+    private String companyName;
+
+    @Excel(name = "所属员工")
+    private String companyUserNickName;
+
+    @Excel(name = "订单单号")
+    private String orderCode;
+
+    @Excel(name = "会员手机号")
+    private String userPhone;
+
+    @Excel(name = "订单状态", dictType = "store_order_status")
+    private String status;
+
+    @Excel(name = "物流状态", dictType = "store_order_delivery_status")
+    private Integer deliveryStatus;
+
+    @Excel(name = "物流单号")
+    private String deliveryId;
+
+    @Excel(name = "异常状态", dictType = "store_order_delivery_type")
+    private String deliveryType;
+
+    @Excel(name = "处理状态", readConverterExp = "1=待处理,2=已处理")
+    private Integer deliveryExceptionStatus;
+
+    @Excel(name = "异常备注")
+    private String deliveryExceptionRemark;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+}

+ 5 - 0
fs-service/src/main/java/com/fs/live/service/ILiveSortLinkService.java

@@ -18,4 +18,9 @@ public interface ILiveSortLinkService {
      */
     R createAppLiveSortLink(FsLiveSortLinkParam param);
 
+    /**
+     * 根据短链 link 后缀查询 realLink
+     */
+    R getRealLinkByLink(String link);
+
 }

+ 28 - 2
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -2079,7 +2079,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 }
             }
             try {
-                expressService.subscribeEspress(order.getOrderCode(), order.getDeliveryCode(), order.getDeliverySn(), lastFourNumber);
+                subscribeLiveOrderExpress(order, order.getDeliveryCode(), order.getDeliverySn(), lastFourNumber);
                 TemplateBean templateBean = TemplateBean.builder()
                         .orderId(order.getOrderId().toString())
                         .orderCode(order.getOrderCode())
@@ -3429,11 +3429,37 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                         lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
                     }
                 }
-                expressService.subscribeEspress(existOrder.getOrderCode(), fsExpress.getCode(), deliveryId, lastFourNumber);
+                subscribeLiveOrderExpress(existOrder, fsExpress.getCode(), deliveryId, lastFourNumber);
             }
         }
     }
 
+    private String resolveSenderPhonesByLiveOrder(LiveOrder order) {
+        if (order == null) {
+            return null;
+        }
+        Long productId = order.getProductId();
+        if (productId == null) {
+            List<LiveOrderItem> items = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
+            if (items != null && !items.isEmpty() && items.get(0).getProductId() != null) {
+                productId = items.get(0).getProductId();
+            }
+        }
+        if (productId == null) {
+            return null;
+        }
+        FsStoreProductScrm product = fsStoreProductService.selectFsStoreProductById(productId);
+        return product != null ? product.getSenderPhones() : null;
+    }
+
+    private void subscribeLiveOrderExpress(LiveOrder order, String deliverySn, String deliveryId, String lastFourNumber) {
+        if (order == null || StringUtils.isBlank(deliverySn) || StringUtils.isBlank(deliveryId)) {
+            return;
+        }
+        String senderPhones = resolveSenderPhonesByLiveOrder(order);
+        expressService.subscribeExpressSmart(order.getOrderCode(), deliverySn, deliveryId, lastFourNumber, senderPhones);
+    }
+
     //    @Autowired
 //    private FsStoreProductMapper fsStoreProductMapper;
     @Override

+ 43 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveSortLinkServiceImpl.java

@@ -22,6 +22,8 @@ import com.fs.voice.utils.StringUtil;
 
 import java.util.Calendar;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.UUID;
 
 import static com.fs.course.utils.LinkUtil.generateRandomStringWithLock;
@@ -130,6 +132,47 @@ public class LiveSortLinkServiceImpl implements ILiveSortLinkService {
         return R.error("生成链接失败!");
     }
 
+    @Override
+    public R getRealLinkByLink(String link) {
+        if (StringUtils.isEmpty(link)) {
+            return R.error("link不能为空");
+        }
+        String linkSuffix = extractLinkSuffix(link);
+        FsCourseLink courseLink = fsCourseLinkMapper.selectFsCourseLinkByLink(linkSuffix);
+        if (courseLink == null) {
+            return R.error("链接不存在");
+        }
+        if (courseLink.getUpdateTime() != null && courseLink.getUpdateTime().before(new Date())) {
+            return R.error("链接已过期");
+        }
+        if (StringUtils.isEmpty(courseLink.getRealLink())) {
+            return R.error("真实链接不存在");
+        }
+
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        String domainName = getDomainName(courseLink.getCompanyUserId(), config);
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("link", linkSuffix);
+        map.put("realLink", courseLink.getRealLink());
+        map.put("url", domainName + courseLink.getRealLink());
+        map.put("linkId", courseLink.getLinkId());
+        map.put("liveId", courseLink.getLiveId());
+        return R.ok(map);
+    }
+
+    /**
+     * 支持直接传 link 后缀,或短链完整路径(含 ?s=)
+     */
+    private String extractLinkSuffix(String link) {
+        if (link.contains("s=")) {
+            int index = link.indexOf("s=");
+            return link.substring(index + 2).split("[&#?]")[0];
+        }
+        return link.trim();
+    }
+
     private String getDomainName(Long companyUserId, CourseConfig config) {
         String domainName = companyUserMapper.selectDomainByUserId(companyUserId);
         if (StringUtils.isEmpty(domainName)) {

+ 13 - 2
fs-service/src/main/java/com/fs/qw/vo/QwUserVoiceLogTotalVo.java

@@ -74,9 +74,12 @@ public class QwUserVoiceLogTotalVo extends BaseEntity {
     //接通数量
     @Excel(name = "接通数量")
     private Long connectCount;
-    //未接通数量
-    @Excel(name = "未接通数量")
+    //拒接数量
+    @Excel(name = "拒接数量")
     private Long noConnectCount;
+    //未接听数量
+    @Excel(name = "未接听数量")
+    private Long missedConnectCount;
 
     private QwExternalContact qwExternalContact;
 
@@ -134,6 +137,14 @@ public class QwUserVoiceLogTotalVo extends BaseEntity {
         this.noConnectCount = noConnectCount;
     }
 
+    public Long getMissedConnectCount() {
+        return missedConnectCount;
+    }
+
+    public void setMissedConnectCount(Long missedConnectCount) {
+        this.missedConnectCount = missedConnectCount;
+    }
+
     public Long getId() {
         return id;
     }

+ 17 - 1
fs-service/src/main/resources/db/changelog/changes/20260613-live-user-add-is-del.sql

@@ -74,4 +74,20 @@ ALTER TABLE fs_course_coupon_user
 --precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'fs_integral_order' AND column_name = 'virtual_phone'
 ALTER TABLE `fs_integral_order`
     ADD COLUMN `virtual_phone` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '虚拟手机号' AFTER `quantity_cart`;
---rollback ALTER TABLE fs_integral_order DROP COLUMN type;
+--rollback ALTER TABLE fs_integral_order DROP COLUMN type;
+
+--changeset yhq:20260623-fs-store-product-sender-phones
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:1 SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'fs_store_product_scrm'
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'fs_store_product_scrm' AND column_name = 'sender_phones'
+ALTER TABLE fs_store_product_scrm
+    ADD COLUMN sender_phones VARCHAR(128) NULL DEFAULT NULL COMMENT '发货人手机号,多个逗号分隔,最多3个';
+--rollback ALTER TABLE fs_store_product_scrm DROP COLUMN sender_phones;
+
+--changeset yhq:20260624-fs-store-order-sender-phone
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:1 SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'fs_store_order_scrm'
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'fs_store_order_scrm' AND column_name = 'sender_phone'
+ALTER TABLE fs_store_order_scrm
+    ADD COLUMN sender_phone VARCHAR(20) NULL DEFAULT NULL COMMENT '物流订阅成功的发货人手机号';
+--rollback ALTER TABLE fs_store_order_scrm DROP COLUMN sender_phone;

+ 1 - 0
fs-service/src/main/resources/db/changelog/db.changelog-master.xml

@@ -11,5 +11,6 @@
     <include file="baseline/baseline.sql" relativeToChangelogFile="true"/>
     <include file="changes/20260613-live-user-add-is-del.sql" relativeToChangelogFile="true"/>
     <include file="table/live_group_type.sql" relativeToChangelogFile="true"/>
+    <include file="dictData/dict_data_update.sql" relativeToChangelogFile="true"/>
 
 </databaseChangeLog>

+ 17 - 0
fs-service/src/main/resources/db/changelog/dictData/dict_data_update.sql

@@ -0,0 +1,17 @@
+--liquibase formatted sql
+
+--changeset yhq:20260624-store-express-sender-phone-dict
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM sys_dict_type WHERE dict_type = 'store_express_sender_phone'
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM sys_dict_data WHERE dict_type = 'store_express_sender_phone'
+INSERT INTO `sys_dict_type`
+(`dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    ('发货人手机号订阅物流', 'store_express_sender_phone', '0', 'admin', NOW(), '', NULL, '值为1时启用发货人手机号优先订阅物流');
+
+INSERT INTO `sys_dict_data`
+(`dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    (1, '启用', '0', 'store_express_sender_phone', '', 'success', 'Y', '0', 'admin', NOW(), '', NULL, '启用发货人手机号优先订阅物流');
+--rollback DELETE FROM sys_dict_data WHERE dict_type = 'store_express_sender_phone';
+--rollback DELETE FROM sys_dict_type WHERE dict_type = 'store_express_sender_phone';

+ 5 - 5
fs-service/src/main/resources/mapper/course/FsUserTalentFollowMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.course.mapper.FsUserTalentFollowMapper">
-    
+
     <resultMap type="FsUserTalentFollow" id="FsUserTalentFollowResult">
         <result property="id"    column="id"    />
         <result property="userId"    column="user_id"    />
@@ -18,12 +18,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectFsUserTalentFollowList" parameterType="FsUserTalentFollow" resultMap="FsUserTalentFollowResult">
         <include refid="selectFsUserTalentFollowVo"/>
-        <where>  
+        <where>
             <if test="userId != null "> and user_id = #{userId}</if>
             <if test="talentId != null "> and talent_id = #{talentId}</if>
         </where>
     </select>
-    
+
     <select id="selectFsUserTalentFollowById" parameterType="Long" resultMap="FsUserTalentFollowResult">
         <include refid="selectFsUserTalentFollowVo"/>
         where id = #{id}
@@ -95,9 +95,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
 
     <delete id="deleteFsUserTalentFollowByIds" parameterType="String">
-        delete from fs_user_talent_follow where id in 
+        delete from fs_user_talent_follow where id in
         <foreach item="id" collection="array" open="(" separator="," close=")">
             #{id}
         </foreach>
     </delete>
-</mapper>
+</mapper>

+ 13 - 0
fs-service/src/main/resources/mapper/course/FsUserVideoMapper.xml

@@ -205,4 +205,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{videoId}
         </foreach>
     </update>
+
+    <insert id="addCommentCount">
+        update fs_user_video
+        set comments = comments + 1
+        where video_id = #{videoId}
+    </insert>
+
+    <insert id="delCommentCount">
+        update fs_user_video
+        set comments = comments - 1
+        where video_id = #{videoId}
+    </insert>
+
 </mapper>

+ 5 - 1
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -87,6 +87,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="customerId"    column="customer_id"    />
         <result property="isPayRemain"    column="is_pay_remain"    />
         <result property="deliverySendTime"    column="delivery_send_time"    />
+        <result property="senderPhone"    column="sender_phone"    />
         <result property="certificates"    column="certificates"    />
         <result property="scheduleId"    column="schedule_id"    />
         <result property="orderVisit"    column="order_visit"    />
@@ -171,7 +172,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectShoppingPointsPendingOrders" resultMap="FsStoreOrderResult">
         <include refid="selectFsStoreOrderVo"/>
         WHERE  paid = 1
-          AND status = 4
+          AND status = 3
           AND (shopping_points_claimed IS NULL OR shopping_points_claimed = 0)
           AND create_time &gt;= #{cutoffDate}
           AND finish_time &lt;= #{sevenDaysAgo}
@@ -280,6 +281,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="customerId != null">customer_id,</if>
             <if test="isPayRemain != null">is_pay_remain,</if>
             <if test="deliverySendTime != null">delivery_send_time,</if>
+            <if test="senderPhone != null">sender_phone,</if>
             <if test="orderVisit != null">order_visit,</if>
             <if test="serviceFee != null">service_fee,</if>
             <if test="orderMedium != null">order_medium,</if>
@@ -373,6 +375,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="customerId != null">#{customerId},</if>
             <if test="isPayRemain != null">#{isPayRemain},</if>
             <if test="deliverySendTime != null">#{deliverySendTime},</if>
+            <if test="senderPhone != null">#{senderPhone},</if>
             <if test="orderVisit != null">#{orderVisit},</if>
             <if test="serviceFee != null">#{serviceFee},</if>
             <if test="orderMedium != null">#{orderMedium},</if>
@@ -473,6 +476,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="customerId != null">customer_id = #{customerId},</if>
             <if test="isPayRemain != null">is_pay_remain = #{isPayRemain},</if>
             <if test="deliverySendTime != null">delivery_send_time = #{deliverySendTime},</if>
+            <if test="senderPhone != null">sender_phone = #{senderPhone},</if>
             <if test="scheduleId != null">schedule_id = #{scheduleId},</if>
             <if test="orderVisit != null">order_visit = #{orderVisit},</if>
             <if test="serviceFee != null">service_fee = #{serviceFee},</if>

+ 7 - 2
fs-service/src/main/resources/mapper/hisStore/FsStoreProductScrmMapper.xml

@@ -69,6 +69,7 @@
         <result property="isAudit" column="is_audit"/>
         <result property="storeId" column="store_id"/>
         <result property="returnAddress"    column="return_address"    />
+        <result property="senderPhones"    column="sender_phones"    />
         <result property="brand"    column="brand"    />
         <result property="foodProductionLicenseCode"    column="food_production_license_code"    />
         <result property="originPlace"    column="origin_place"    />
@@ -92,7 +93,7 @@
                integral, product_type, prescribe_code, prescribe_spec, prescribe_factory, prescribe_name,
                is_display,tui_cate_id,company_ids,is_drug,drug_image,drug_reg_cert_no,common_name,dosage_form,
                unit_price,batch_number,mah,mah_address,manufacturer,manufacturer_address,indications,dosage,
-               adverse_reactions,contraindications,precautions,is_audit,store_id,return_address,brand,food_production_license_code,
+               adverse_reactions,contraindications,precautions,is_audit,store_id,return_address,sender_phones,brand,food_production_license_code,
                origin_place,net_content,shelf_life,domestic_imported,app_ids,purchase_limit,single_purchase_limit,activity_type,activity_start_time,activity_end_time,tag_info
         from fs_store_product_scrm
     </sql>
@@ -105,7 +106,7 @@
                p.integral, p.product_type, p.prescribe_code, p.prescribe_spec, p.prescribe_factory, p.prescribe_name,
                p.is_display,p.tui_cate_id,p.company_ids,p.is_drug,p.drug_image,p.drug_reg_cert_no,p.common_name,p.dosage_form,
                p.unit_price,p.batch_number,p.mah,p.mah_address,p.manufacturer,p.manufacturer_address,p.indications,p.dosage,
-               p.adverse_reactions,p.contraindications,p.precautions,p.is_audit,p.store_id,p.return_address,p.brand,p.food_production_license_code,
+               p.adverse_reactions,p.contraindications,p.precautions,p.is_audit,p.store_id,p.return_address,p.sender_phones,p.brand,p.food_production_license_code,
                p.origin_place,p.net_content,p.shelf_life,p.domestic_imported,app_ids,p.purchase_limit,p.single_purchase_limit,p.activity_type,p.tag_info
         from fs_store_product_scrm p
     </sql>
@@ -186,6 +187,7 @@
             <if test="netContent != null and netContent != ''">and net_content = #{netContent} </if>
             <if test="shelfLife != null">and shelf_life = #{shelfLife} </if>
             <if test="domesticImported != null and domesticImported != ''">and domestic_imported = #{domesticImported} </if>
+            <if test="senderPhones != null and senderPhones != ''">and sender_phones like concat('%', #{senderPhones}, '%') </if>
         </where>
     </select>
 
@@ -282,6 +284,7 @@
             <if test="isAudit != null and isAudit != ''">is_audit ,</if>
             <if test="storeId != null and storeId != ''">store_id ,</if>
             <if test="returnAddress != null">return_address,</if>
+            <if test="senderPhones != null">sender_phones,</if>
             <if test="brand != null and brand != ''">brand,</if>
             <if test="foodProductionLicenseCode != null and foodProductionLicenseCode != ''">food_production_license_code,</if>
             <if test="originPlace != null and originPlace != ''">origin_place,</if>
@@ -358,6 +361,7 @@
             <if test="isAudit != null and isAudit != ''">#{isAudit} ,</if>
             <if test="storeId != null and storeId != ''">#{storeId} ,</if>
             <if test="returnAddress != null">#{returnAddress},</if>
+            <if test="senderPhones != null">#{senderPhones},</if>
             <if test="brand != null and brand != ''">#{brand},</if>
             <if test="foodProductionLicenseCode != null and foodProductionLicenseCode != ''">#{foodProductionLicenseCode},</if>
             <if test="originPlace != null and originPlace != ''">#{originPlace},</if>
@@ -438,6 +442,7 @@
             <if test="isAudit != null and isAudit != ''">is_audit = #{isAudit} ,</if>
             <if test="storeId != null and storeId != ''">store_id = #{storeId} ,</if>
             <if test="returnAddress != null">return_address = #{returnAddress},</if>
+            <if test="senderPhones != null">sender_phones = #{senderPhones},</if>
             <if test="brand != null and brand != ''">brand = #{brand},</if>
             <if test="foodProductionLicenseCode != null and foodProductionLicenseCode != ''">food_production_license_code = #{foodProductionLicenseCode},</if>
             <if test="originPlace != null">origin_place = #{originPlace},</if>

+ 3 - 1
fs-service/src/main/resources/mapper/qw/QwUserVoiceLogMapper.xml

@@ -23,6 +23,7 @@
         <result property="duration"    column="duration"    />
         <result property="connectCount"    column="connectCount"    />
         <result property="noConnectCount"    column="noConnectCount"    />
+        <result property="missedConnectCount"    column="missedConnectCount"    />
         <result property="createTime"     column="create_time"     />
         <result property="companyUserId"     column="company_user_id"     />
         <association property="qwUser" javaType="com.fs.qw.domain.QwUser" autoMapping="true">
@@ -105,7 +106,8 @@
                uvl.company_id, uvl.company_user_id, uvl.create_time,qec.`name`,qec.tag_ids tagIds,qu.qw_user_name,
         SUM(duration) duration,
         COUNT(CASE WHEN uvl.status=1 THEN 1 END) AS connectCount,
-        COUNT(CASE WHEN uvl.status=2 THEN 1 END) AS noConnectCount
+        COUNT(CASE WHEN uvl.status=2 THEN 1 END) AS noConnectCount,
+        COUNT(CASE WHEN uvl.status=3 THEN 1 END) AS missedConnectCount
         FROM qw_user_voice_log uvl
         LEFT JOIN qw_user qu ON uvl.qw_user_id = qu.id
         left join qw_external_contact qec on uvl.ext_id = qec.id

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/TalentController.java

@@ -63,6 +63,7 @@ public class TalentController extends  AppBaseController{
     @Autowired
     private IFsUserVideoTagsService fsUserVideoTagsService;
 
+
     private static final String VIDEO_UPLOAD_DIR = "C:\\fs\\uploadPath\\talent\\video";  // 上传目录
     private static final String FRAME_OUTPUT_DIR = "C:\\fs\\uploadPath\\talent\\frame";  // 输出帧的目录
 
@@ -253,7 +254,6 @@ public class TalentController extends  AppBaseController{
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         boolean oneSelf = userId == param.getUserId();
         List<FsUserVideoListUVO> list = fsUserVideoService.selectFsUserVideoListUVOByUser(fsUserTalent.getTalentId(),oneSelf,userId);
-
         PageInfo<FsUserVideoListUVO> listPageInfo=new PageInfo<>(list);
         return R.ok().put("data",listPageInfo);
     }

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/VideoController.java

@@ -55,7 +55,7 @@ public class VideoController extends  AppBaseController{
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         List<FsUserVideoListUVO> list= videoService.selectFsUserVideoListUVO(param);
         //添加假数据
-        list = videoService.addNum(list);
+//        list = videoService.addNum(list);
         PageInfo<FsUserVideoListUVO> listPageInfo=new PageInfo<>(list);
         if (param.getUserId() != null) {
             // 对分页后的数据进行推荐排序

+ 1 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/PayScrmController.java

@@ -127,6 +127,7 @@ public class PayScrmController {
         String[] order=o.getLowOrderId().split("-");
         switch (order[0]) {
             case "store":
+            case "live":
                 return orderService.payConfirm(1,null,order[1], o.getUpOrderId(),orderResult.getBankTrxId(),orderResult.getBankOrderId());
             case "store_remain":
                 return orderService.payRemainConfirm( order[1], o.getUpOrderId(),orderResult.getBankTrxId(),orderResult.getBankOrderId());

+ 1 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/WxPayScrmController.java

@@ -79,6 +79,7 @@ public class WxPayScrmController {
                 String[] orderId=outtradeno.split("-");
                 switch (orderId[0]){
                     case "store":
+                    case "live":
                         orderService.payConfirm(1,null,orderId[1], outtradeno,tradeNo,null);
                         break;
                     case "store_remain":