소스 검색

Merge remote-tracking branch 'origin/master'

ct 4 일 전
부모
커밋
b487133162
42개의 변경된 파일489개의 추가작업 그리고 34개의 파일을 삭제
  1. 6 6
      fs-admin/src/main/java/com/fs/his/controller/FsAdvController.java
  2. 1 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesScrmController.java
  3. 1 0
      fs-admin/src/main/java/com/fs/live/controller/LiveAfterSalesController.java
  4. 13 2
      fs-company/src/main/java/com/fs/company/controller/live/LiveWatchLogController.java
  5. 19 4
      fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java
  6. 7 1
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  7. 4 0
      fs-service/src/main/java/com/fs/config/cloud/CloudHostProper.java
  8. 3 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java
  9. 4 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  10. 2 0
      fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java
  11. 6 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  12. 24 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  13. 68 16
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  14. 8 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  15. 6 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreAfterSalesScrm.java
  16. 4 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreAfterSalesScrmMapper.java
  17. 2 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreAfterSalesVO.java
  18. 3 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderItemExportRefundZMVO.java
  19. 7 1
      fs-service/src/main/java/com/fs/ipad/IpadSendUtils.java
  20. 31 0
      fs-service/src/main/java/com/fs/ipad/vo/WxSendTextAtMsgVo.java
  21. 3 0
      fs-service/src/main/java/com/fs/live/mapper/LiveWatchLogMapper.java
  22. 8 0
      fs-service/src/main/java/com/fs/live/service/ILiveWatchLogService.java
  23. 10 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveWatchLogServiceImpl.java
  24. 6 0
      fs-service/src/main/java/com/fs/live/vo/LiveAfterSalesVo.java
  25. 118 0
      fs-service/src/main/java/com/fs/live/vo/LiveWatchLogListVO.java
  26. 2 0
      fs-service/src/main/java/com/fs/qw/vo/QwSopTempSetting.java
  27. 3 0
      fs-service/src/main/java/com/fs/sop/domain/QwSopTemp.java
  28. 3 0
      fs-service/src/main/java/com/fs/sop/domain/QwSopTempRules.java
  29. 6 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java
  30. 46 0
      fs-service/src/main/java/com/fs/wxwork/dto/WxSendTextAtMsgTwoDTO.java
  31. 7 0
      fs-service/src/main/java/com/fs/wxwork/service/WxWorkServiceNew.java
  32. 1 0
      fs-service/src/main/resources/application-config-dev-jnlzjk.yml
  33. 1 0
      fs-service/src/main/resources/application-config-druid-hsyy.yml
  34. 1 0
      fs-service/src/main/resources/application-config-druid-jnlzjk.yml
  35. 1 0
      fs-service/src/main/resources/application-config-druid-sxjz.yml
  36. 1 0
      fs-service/src/main/resources/application-config-myhk.yml
  37. 2 0
      fs-service/src/main/resources/application-config-zkzh.yml
  38. 1 1
      fs-service/src/main/resources/application-druid-sxjz.yml
  39. 2 1
      fs-service/src/main/resources/mapper/live/LiveAfterSalesMapper.xml
  40. 35 0
      fs-service/src/main/resources/mapper/live/LiveWatchLogMapper.xml
  41. 5 0
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseQwController.java
  42. 8 0
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseTransferController.java

+ 6 - 6
fs-admin/src/main/java/com/fs/his/controller/FsAdvController.java

@@ -40,7 +40,7 @@ public class FsAdvController extends BaseController
     /**
      * 查询广告列表
      */
-    @PreAuthorize("@ss.hasPermi('store:adv:list')")
+    @PreAuthorize("@ss.hasPermi('store:adv:list') or @ss.hasPermi('his:adv:list')")
     @GetMapping("/list")
     public TableDataInfo list(FsAdv fsAdv)
     {
@@ -52,7 +52,7 @@ public class FsAdvController extends BaseController
     /**
      * 导出广告列表
      */
-    @PreAuthorize("@ss.hasPermi('store:adv:export')")
+    @PreAuthorize("@ss.hasPermi('store:adv:export') or @ss.hasPermi('his:adv:export')")
     @Log(title = "广告", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
     public AjaxResult export(FsAdv fsAdv)
@@ -65,7 +65,7 @@ public class FsAdvController extends BaseController
     /**
      * 获取广告详细信息
      */
-    @PreAuthorize("@ss.hasPermi('store:adv:query')")
+    @PreAuthorize("@ss.hasPermi('store:adv:query') or @ss.hasPermi('his:adv:query')")
     @GetMapping(value = "/{advId}")
     public AjaxResult getInfo(@PathVariable("advId") String advId)
     {
@@ -76,7 +76,7 @@ public class FsAdvController extends BaseController
     /**
      * 新增广告
      */
-    @PreAuthorize("@ss.hasPermi('store:adv:add')")
+    @PreAuthorize("@ss.hasPermi('store:adv:add') or @ss.hasPermi('his:adv:add')")
     @Log(title = "广告", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody FsAdv fsAdv)
@@ -91,7 +91,7 @@ public class FsAdvController extends BaseController
     /**
      * 修改广告
      */
-    @PreAuthorize("@ss.hasPermi('store:adv:edit')")
+    @PreAuthorize("@ss.hasPermi('store:adv:edit') or @ss.hasPermi('his:adv:edit')")
     @Log(title = "广告", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody FsAdv fsAdv)
@@ -105,7 +105,7 @@ public class FsAdvController extends BaseController
     /**
      * 删除广告
      */
-    @PreAuthorize("@ss.hasPermi('store:adv:remove')")
+    @PreAuthorize("@ss.hasPermi('store:adv:remove') or @ss.hasPermi('his:adv:remove')")
     @Log(title = "广告", businessType = BusinessType.DELETE)
 	@DeleteMapping("/{advIds}")
     public AjaxResult remove(@PathVariable String[] advIds)

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

@@ -106,6 +106,7 @@ public class FsStoreAfterSalesScrmController extends BaseController
                     .map(vo -> {
                         FsStoreOrderItemExportRefundZMVO zmvo = new FsStoreOrderItemExportRefundZMVO();
                         try {
+                            zmvo.setPayCode(vo.getPayCode());
                             zmvo.setOrderCode(vo.getOrderCode());
                             zmvo.setStatus(vo.getOrderStatus().toString());
                             zmvo.setUserId(vo.getUserId());

+ 1 - 0
fs-admin/src/main/java/com/fs/live/controller/LiveAfterSalesController.java

@@ -120,6 +120,7 @@ public class LiveAfterSalesController extends BaseController
                     .map(vo -> {
                         FsStoreOrderItemExportRefundZMVO zmvo = new FsStoreOrderItemExportRefundZMVO();
                         try {
+                            zmvo.setPayCode(vo.getPayCode());
                             zmvo.setOrderCode(vo.getOrderCode());
                             zmvo.setStatus(vo.getOrderStatus().toString());
                             zmvo.setUserId(vo.getUserId());

+ 13 - 2
fs-company/src/main/java/com/fs/company/controller/live/LiveWatchLogController.java

@@ -3,6 +3,10 @@ package com.fs.company.controller.live;
 import java.util.List;
 
 import com.fs.common.core.domain.R;
+import com.fs.common.utils.ServletUtils;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.service.TokenService;
+import com.fs.live.vo.LiveWatchLogListVO;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -34,7 +38,8 @@ public class LiveWatchLogController extends BaseController
 {
     @Autowired
     private ILiveWatchLogService liveWatchLogService;
-
+    @Autowired
+    private TokenService tokenService;
     /**
      * 查询直播看课记录列表
      */
@@ -43,7 +48,13 @@ public class LiveWatchLogController extends BaseController
     public TableDataInfo list(LiveWatchLog liveWatchLog)
     {
         startPage();
-        List<LiveWatchLog> list = liveWatchLogService.selectLiveWatchLogList(liveWatchLog);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(null == loginUser) {
+           throw new RuntimeException("用户信息错误");
+        }
+        Long companyId = loginUser.getCompany().getCompanyId();
+        liveWatchLog.setCompanyId(companyId);
+        List<LiveWatchLogListVO> list = liveWatchLogService.selectLiveWatchLogListInfo(liveWatchLog);
         return getDataTable(list);
     }
 

+ 19 - 4
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -40,10 +40,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -248,6 +245,21 @@ public class IpadSendServer {
         }
     }
 
+        public void sendTxtAtMsg(BaseVo vo) {
+        WxSendTextAtMsgTwoDTO dto = new WxSendTextAtMsgTwoDTO();
+        List<WxSendTextAtMsgTwoDTO.Contentva> contentvaList = new ArrayList<>();
+        WxSendTextAtMsgTwoDTO.Contentva contentva = new WxSendTextAtMsgTwoDTO.Contentva();
+        contentva.setMsgtype(5);
+        contentva.setVid(0);
+        contentvaList.add(contentva);
+        dto.setContentva(contentvaList);
+        dto.setBase(vo);
+         dto.setUuid(vo.getUuid());
+        dto.setSend_userid(ipadSendUtils.userIds(vo));
+        dto.setIsRoom(true);
+       ipadSendUtils.sendTxtAtMsgVo(dto, vo.getServerId());
+    }
+    
     public void sendVoice(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
         if (StringUtils.isEmpty(content.getVoiceUrl()) || StringUtils.isEmpty(content.getVoiceDuration())) {
             log.debug("语音未生成无法发送,转文字发送:{}", vo);
@@ -465,6 +477,9 @@ public class IpadSendServer {
                     // 语音
                     sendWxVideo(vo, content);
                     break;
+                case "99":
+                    // 群发
+                    sendTxtAtMsg(vo);
                 default:
                     // 未知类型,记录警告
                     log.error("SOP_LOG_ID:{}错误的发送类型: {}", qwSopLogs.getId(), content.getContentType());

+ 7 - 1
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -676,6 +676,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             content.setVideoId(e.getVideoId());
             content.setCourseType(e.getCourseType());
             content.setAiTouch(e.getAiTouch());
+            content.setIsAtAll(e.getIsAtAll());
             return content;
         }).sorted(Comparator.comparing(e -> LocalTime.parse(e.getTime() + ":00"))).peek(e -> e.setIndex(i.getAndIncrement())).collect(Collectors.toList());
     }
@@ -1032,7 +1033,12 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             log.error("Cloned content settings are empty, skipping.");
             return;
         }
-
+        //如果是@所有人,就添加
+        if (1 == content.getIsAtAll()) {
+            QwSopTempSetting.Content.Setting atMsg = new QwSopTempSetting.Content.Setting();
+            atMsg.setContentType("99");
+            settings.add(atMsg);
+        }
         // 顺序处理每个 Setting,避免过多的并行导致线程开销
         for (QwSopTempSetting.Content.Setting setting : settings) {
             switch (setting.getContentType()) {

+ 4 - 0
fs-service/src/main/java/com/fs/config/cloud/CloudHostProper.java

@@ -19,4 +19,8 @@ public class CloudHostProper {
     //火山云空间名称
     @Value("${cloud_host.spaceName}")
     public String spaceName;
+
+    //火山云空间绑定域名
+    @Value("${cloud_host.volcengineUrl}")
+    public String volcengineUrl;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java

@@ -75,6 +75,9 @@ public interface FsCourseRedPacketLogMapper
     @Select("select * from fs_course_red_packet_log where out_batch_no = #{outBatchNo}")
     FsCourseRedPacketLog selectFsCourseRedPacketLogByBatchNo(@Param("outBatchNo") String outBatchNo);
 
+    @Select("select * from fs_course_red_packet_log where batch_id = #{batchId}")
+    FsCourseRedPacketLog selectFsCourseRedPacketLogByBatchId(@Param("batchId") String batchId);
+
 
     @Select({"<script> " +
             "select o.*,v.title as video_name,u.phone as user_name  from fs_course_red_packet_log l " +

+ 4 - 1
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -209,7 +209,7 @@ public interface FsUserCourseVideoMapper extends BaseMapper<FsUserCourseVideo> {
             "        <if test=\"data.keyword != null and data.keyword !='' \">\n" +
             "            AND v.title LIKE concat('%',#{data.keyword},'%')\n" +
             "        </if>" +
-            "order by v.video_id asc " +
+            "order by v.course_sort asc, v.video_id asc " +
             "</script>")
     List<FsCourseVideoListBySidebarVO> getFsCourseVideoListBySidebar(@Param("data") FsCourseListBySidebarParam param);
 
@@ -271,4 +271,7 @@ public interface FsUserCourseVideoMapper extends BaseMapper<FsUserCourseVideo> {
 
     @Select("select * from fs_user_course_video where job_id is not null and vid is null")
     List<FsUserCourseVideo> selectVideoByJobId();
+
+    @Select("select * from fs_user_course_video where vid is not null")
+    List<FsUserCourseVideo> selectVideoByVid();
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java

@@ -87,4 +87,6 @@ public interface IFsCourseRedPacketLogService
     void sendRedPacketBf();
 
     void queryRedPacketResult(String startTime, String endTime);
+
+    R getBillsByTransferBillNo(String batchId);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java

@@ -234,4 +234,10 @@ public interface IFsUserCourseVideoService extends IService<FsUserCourseVideo> {
      * @return
      */
     R getVidByJob();
+
+    /**
+     * 通过vid获取视频路径并且组装地址存到替换线路二
+     * @return
+     */
+    R getVideoInfoByVid();
 }

+ 24 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -476,4 +476,28 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
                 company.getCompanyId(), moneyLog.getMoney());
     }
 
+    @Override
+    public R getBillsByTransferBillNo(String batchId) {
+        FsCourseRedPacketLog log = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByBatchNo(batchId);
+        if (log ==null){
+            return R.error("未查询到红包记录!");
+        }
+        String json = configService.selectConfigByKey("redPacket.config");
+        RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
+        //创建微信订单
+        WxPayConfig payConfig = new WxPayConfig();
+        BeanUtils.copyProperties(config,payConfig);
+        WxPayService wxPayService = new WxPayServiceImpl();
+        wxPayService.setConfig(payConfig);
+        TransferService transferService=wxPayService.getTransferService();
+
+        try {
+            TransferBillsGetResult queryRedPacketResult = transferService.getBillsByTransferBillNo(batchId);
+            logger.info("FsCourseRedPacketLog-log_id:{},【红包处理】查询批次结果:{}",log.getLogId(),queryRedPacketResult);
+            return R.ok(queryRedPacketResult.toString());
+        } catch (WxPayException e) {
+            logger.error(e.getMessage());
+            return R.error(e.getMessage());
+        }
+    }
 }

+ 68 - 16
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -4075,10 +4075,11 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
             //用户额外信息,最大长度 512 字节。
             uRLSetsBuilder.setCallbackArgs("");
             // 火山云存储路径(文件上传后在火山云的路径)
-            String datePath = new SimpleDateFormat("yyyyMMdd").format(new Date());
-            String fileName = System.currentTimeMillis() + ".mp4";
-            String remoteFileName = "fs/" + datePath + "/" + fileName;
-            uRLSetsBuilder.setFileName(remoteFileName);
+//            String datePath = new SimpleDateFormat("yyyyMMdd").format(new Date());
+//            String fileName = System.currentTimeMillis() + ".mp4";
+//            String remoteFileName = "fs/" + datePath + "/" + fileName;
+
+            uRLSetsBuilder.setFileName(courseVideo.getFileKey());
             reqBuilder.addURLSets(uRLSetsBuilder);
 
             VodUrlUploadResponse resp = vodService.uploadMediaByUrl(reqBuilder.build());
@@ -4123,7 +4124,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
             for (FsUserCourseVideo video : batch) {
                 uploadExecutor.submit(() -> {
                     try {
-                        uploadSingleTaskWithRetry(video);
+                        uploadSingleTaskWithRetry(video,1);
                     } finally {
                         latch.countDown();
                     }
@@ -4144,6 +4145,53 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         log.info("全部批次执行完成");
         return R.ok();
     }
+
+    @Override
+    public R getVideoInfoByVid() {
+        // 查询有JobId的视频
+        List<FsUserCourseVideo> list = fsUserCourseVideoMapper.selectVideoByVid();
+        if (list.isEmpty()) {
+            log.info("没有包含vid的视频");
+            return R.error();
+        }
+        // 按五百一批切割
+        List<List<FsUserCourseVideo>> batches = splitList(list, 500);
+        log.info("总任务 {} 条,分成 {} 批", list.size(), batches.size());
+
+        int batchIndex = 1;
+
+        // 批次顺序执行,每批内部多线程并发执行
+        for (List<FsUserCourseVideo> batch : batches) {
+
+            log.info("开始执行批次 {}/{},本批任务 {} 条", batchIndex, batches.size(), batch.size());
+
+            CountDownLatch latch = new CountDownLatch(batch.size());
+
+            for (FsUserCourseVideo video : batch) {
+                uploadExecutor.submit(() -> {
+                    try {
+                        uploadSingleTaskWithRetry(video,2);
+                    } finally {
+                        latch.countDown();
+                    }
+                });
+            }
+
+            // 等待这一批全部完成
+            try {
+                latch.await();
+            } catch (InterruptedException e) {
+                log.error("批次等待异常", e);
+            }
+
+            log.info("批次 {}/{} 执行完成", batchIndex, batches.size());
+            batchIndex++;
+        }
+
+        log.info("全部批次执行完成");
+        return R.ok();
+    }
+
     private final ExecutorService uploadExecutor = new ThreadPoolExecutor(
             8,  // core
             16, // max
@@ -4202,10 +4250,16 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
                 System.out.println(resp.getResponseMetadata().getError());
                 System.exit(-1);
             }else {
+                //更新小节
                 FsUserCourseVideo video = new FsUserCourseVideo();
                 video.setVideoId(courseVideo.getVideoId());
-                video.setLineTwo(resp.getResult().getMediaInfoList(0).getSourceInfo().getStoreUri());
+                String url = cloudHostProper.volcengineUrl+"/"+resp.getResult().getMediaInfoList(0).getSourceInfo().getStoreUri();
+                video.setLineTwo(url);
                 fsUserCourseVideoMapper.updateFsUserCourseVideo(video);
+                //更新视频资源
+                FsVideoResource videoResource = fsVideoResourceMapper.selectByFileKey(courseVideo.getFileKey());
+                videoResource.setLine2(url);
+                fsVideoResourceMapper.updateById(videoResource);
             }
             System.out.println(resp);
         } catch (Exception e) {
@@ -4214,19 +4268,17 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     }
 
 
-    public void uploadSingleTaskWithRetry(FsUserCourseVideo courseVideo) {
+    public void uploadSingleTaskWithRetry(FsUserCourseVideo courseVideo,Integer type) {
         int maxRetry = 3;
         for (int i = 1; i <= maxRetry; i++) {
             try {
-                //获取上传成功的视频vid,同步到数据库
-                getVidByJobId(courseVideo);
-                //查询需要上传的视频,上传后将视频任务id存到数据库
-//                uploadVideoByUrl(fsUserVideo);
-                //根据视频vid获取火山云的视频信息,并同步到数据库
-                /**
-                 * 下面这个方法调用前去润天his_java确认一下,是否一致的
-                 */
-                //getVideoInfoByVid(fsUserVideo);
+                if (type == 1){
+                    //获取上传成功的视频vid,同步到数据库
+                    getVidByJobId(courseVideo);
+                }else if (type == 2){
+                    //获取视频地址同步到线路二
+                    getVideoInfoByVid(courseVideo);
+                }
                 return;
             } catch (Exception e) {
                 log.error("视频 {} 上传失败,第 {} 次重试,原因:{}",

+ 8 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -624,6 +624,10 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                     break;
                 case 2:
                     json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
+                    //如果分公司配置为空就走总后台的配置
+                    if (StringUtils.isEmpty(json)){
+                        json = configService.selectConfigByKey("redPacket.config");
+                    }
                     config = JSONUtil.toBean(json, RedPacketConfig.class);
                     break;
                 default:
@@ -749,6 +753,10 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                     break;
                 case 2:
                     json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
+                    //如果分公司配置为空就走总后台的配置
+                    if (StringUtils.isEmpty(json)){
+                        json = configService.selectConfigByKey("redPacket.config");
+                    }
                     config = JSONUtil.toBean(json, RedPacketConfig.class);
                     break;
                 default:

+ 6 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsStoreAfterSalesScrm.java

@@ -144,4 +144,10 @@ public class FsStoreAfterSalesScrm extends BaseEntity
     @TableField(exist = false)
     private String productName;
 
+    /**
+     * 用于查询汇付订单号
+     */
+    @TableField(exist = false)
+    private String hfOrderCode;
+
 }

+ 4 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreAfterSalesScrmMapper.java

@@ -91,7 +91,7 @@ public interface FsStoreAfterSalesScrmMapper
             "cu.phonenumber as company_usere_phonenumber,o.pay_money,o.id as orderId,o.create_time as orderCreateTime,o.user_phone," +
             "o.real_name as userName,o.item_json,o.user_address,o.pay_time as orderPayTime,o.pay_price,o.total_postage," +
             "fsps.bank_serial_no,fsps.bank_transaction_id,o.delivery_id as orderDeliveryId,o.delivery_name as orderDeliveryName,o.delivery_sn as orderDeliverySn," +
-            "o.status as orderStatus " +
+            "o.status as orderStatus,fsps.pay_code as payCode " +
             " from fs_store_after_sales_scrm s " +
             " INNER join fs_store_order_scrm o on o.order_code=s.order_code " +
             " left join fs_user u on s.user_id=u.user_id " +
@@ -99,6 +99,9 @@ public interface FsStoreAfterSalesScrmMapper
             " left join company_user cu on cu.user_id=s.company_user_id " +
             " left join fs_store_payment_scrm fsps on fsps.business_order_id = o.id and fsps.status in (-1,1) " +
             " where 1=1 " +
+            "<if test =\"maps.hfOrderCode != null and  maps.hfOrderCode!='' \"> " +
+              "and fsps.pay_code = #{maps.hfOrderCode} " +
+            "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and s.status = #{maps.status} " +
             "</if>" +

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreAfterSalesVO.java

@@ -143,4 +143,6 @@ public class FsStoreAfterSalesVO implements Serializable
     private String orderDeliverySn;
     private String orderDeliveryName;
     private String orderDeliveryId;
+
+    private String payCode;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderItemExportRefundZMVO.java

@@ -23,6 +23,9 @@ public class FsStoreOrderItemExportRefundZMVO implements Serializable  {
     @Excel(name = "订单号",sort = 1)
     private String orderCode;
 
+    @Excel(name = "支付单号",sort = 2)
+    private String payCode;
+
     @Excel(name = "订单状态", dictType = "store_order_status",sort = 10)
     private String status;
 

+ 7 - 1
fs-service/src/main/java/com/fs/ipad/IpadSendUtils.java

@@ -221,7 +221,7 @@ public class IpadSendUtils {
      * @param vo 调用接口参数
      * @return 返回的userid
      */
-    private Long userIds(BaseVo vo){
+    public Long userIds(BaseVo vo){
         if(vo.isRoom()){
             return chatIds(vo);
         }
@@ -562,4 +562,10 @@ public class IpadSendUtils {
         }
         return data.stream().map(WxWorkVid2UserIdRespDTO::getUser_id).collect(Collectors.toList());
     }
+    
+    public void sendTxtAtMsgVo(WxSendTextAtMsgTwoDTO dto, Long serverId){
+        WxWorkResponseDTO<WxSendTextAtMsgVo> result = wxWorkService.sendTextAtMsgTwo(dto, serverId);
+        log.info("发送@所有人返回数据:{}", result);
+        if(result.getErrcode() != 0) throw new BaseException("发送@所有人消息错误:" + result.getErrmsg());
+    }
 }

+ 31 - 0
fs-service/src/main/java/com/fs/ipad/vo/WxSendTextAtMsgVo.java

@@ -0,0 +1,31 @@
+package com.fs.ipad.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+
+@Data
+public class WxSendTextAtMsgVo {
+
+    private Long receiver;
+    private Long sender;
+    private List<atList> at_list;
+    private String sender_name;
+    private Long room_conversation_id;
+    private Integer is_room;
+    private Integer sendtime;
+    private Long msg_id;
+    private Long server_id;
+    private Long msgtype;
+    private String content;
+
+    @Data
+    public class atList {
+        private Long user_id;
+        private String nikeName;
+
+    }
+}
+
+

+ 3 - 0
fs-service/src/main/java/com/fs/live/mapper/LiveWatchLogMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
 import com.fs.live.domain.LiveWatchLog;
+import com.fs.live.vo.LiveWatchLogListVO;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -71,4 +72,6 @@ public interface LiveWatchLogMapper extends BaseMapper<LiveWatchLog> {
 
     List<LiveWatchLog> selectLiveWatchLogByLiveId(@Param("liveId")Long liveId);
 
+    List<LiveWatchLogListVO> selectLiveWatchLogListInfo(LiveWatchLog liveWatchLog);
+
 }

+ 8 - 0
fs-service/src/main/java/com/fs/live/service/ILiveWatchLogService.java

@@ -3,6 +3,7 @@ package com.fs.live.service;
 import java.util.List;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.live.domain.LiveWatchLog;
+import com.fs.live.vo.LiveWatchLogListVO;
 
 /**
  * 直播看课记录Service接口
@@ -58,4 +59,11 @@ public interface ILiveWatchLogService extends IService<LiveWatchLog>{
      * @return 结果
      */
     int deleteLiveWatchLogByLogId(Long logId);
+
+    /**
+     * 查询列表信息
+     * @param liveWatchLog
+     * @return
+     */
+    List<LiveWatchLogListVO> selectLiveWatchLogListInfo(LiveWatchLog liveWatchLog);
 }

+ 10 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveWatchLogServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.live.service.impl;
 import java.util.List;
 import com.fs.common.utils.DateUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.live.vo.LiveWatchLogListVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.live.mapper.LiveWatchLogMapper;
@@ -18,6 +19,9 @@ import com.fs.live.service.ILiveWatchLogService;
 @Service
 public class LiveWatchLogServiceImpl extends ServiceImpl<LiveWatchLogMapper, LiveWatchLog> implements ILiveWatchLogService {
 
+    @Autowired
+    private LiveWatchLogMapper liveWatchLogMapper;
+
     /**
      * 查询直播看课记录
      * 
@@ -42,6 +46,12 @@ public class LiveWatchLogServiceImpl extends ServiceImpl<LiveWatchLogMapper, Liv
         return baseMapper.selectLiveWatchLogList(liveWatchLog);
     }
 
+    @Override
+    public List<LiveWatchLogListVO> selectLiveWatchLogListInfo(LiveWatchLog liveWatchLog){
+
+        return liveWatchLogMapper.selectLiveWatchLogListInfo(liveWatchLog);
+    }
+
     /**
      * 新增直播看课记录
      * 

+ 6 - 0
fs-service/src/main/java/com/fs/live/vo/LiveAfterSalesVo.java

@@ -1,5 +1,6 @@
 package com.fs.live.vo;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
@@ -189,6 +190,11 @@ public class LiveAfterSalesVo {
     private String orderDeliverySn;
     private String orderDeliveryName;
     private String orderDeliveryId;
+    /**
+     * 用于查询汇付订单号
+     */
+    private String hfOrderCode;
 
+    private String payCode;
 
 }

+ 118 - 0
fs-service/src/main/java/com/fs/live/vo/LiveWatchLogListVO.java

@@ -0,0 +1,118 @@
+package com.fs.live.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author MixLiu
+ * @date 2025/12/15 下午3:40)
+ */
+
+@Data
+public class LiveWatchLogListVO {
+
+    /** 日志id */
+    private Long logId;
+
+    /** 用户userId */
+    @Excel(name = "用户userId")
+    private Long userId;
+
+    /** 直播间id */
+    @Excel(name = "直播间id")
+    private Long liveId;
+
+    /** 记录类型 1看课中 2完课 3待看课 4看课中断 */
+    @Excel(name = "记录类型 1看课中 2完课 3待看课 4看课中断")
+    private Integer logType;
+
+    /** 外部联系人id */
+    @Excel(name = "外部联系人id")
+    private Long externalContactId;
+
+    /** 销售id */
+    @Excel(name = "销售id")
+    private Long companyUserId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 完课时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "完课时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date finishTime;
+
+    /** sop最后创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "sop最后创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date sopCreateTime;
+
+    /** 发送小程序appid */
+    @Excel(name = "发送小程序appid")
+    private String sendAppId;
+
+    /** 日志创建来源:1、个人sop,2、群聊sop,3、一键群发 */
+    @Excel(name = "日志创建来源:1、个人sop,2、群聊sop,3、一键群发")
+    private Integer logSource;
+
+    /** 分享人企微id */
+    @Excel(name = "分享人企微id")
+    private String qwUserId;
+    /**
+     * 查看直播类型:1、直播,2、回放
+     */
+    private Integer watchType;
+
+    /**
+     * 企微主体id
+     */
+    private String corpId;
+
+    /**
+     * 直播购买
+     */
+    private Integer liveBuy;
+
+    /**
+     * 回放购买
+     */
+    private Integer replayBuy;
+
+    /**
+     * 会员昵称
+     */
+    private String userName;
+    /**
+     * 会员头像
+     */
+    private String userAvatar;
+
+    /**
+     * 外部联系人名称
+     */
+    private String qwExternalName;
+
+    /**
+     * 外部联系人头像
+     */
+    private String qwExternalAvatar;
+
+    /**
+     * 直播间名称
+     */
+    private String liveName;
+
+    /**
+     * 所属销售
+     */
+    private String companyUserName;
+
+    /**
+     * 企微用户
+     */
+    private String qwUserName;
+}

+ 2 - 0
fs-service/src/main/java/com/fs/qw/vo/QwSopTempSetting.java

@@ -44,6 +44,8 @@ public class QwSopTempSetting implements Serializable{
         private String addTag;
 
         private String delTag;
+        
+        private Integer isAtAll;
 
         @Override
         public Content clone() {

+ 3 - 0
fs-service/src/main/java/com/fs/sop/domain/QwSopTemp.java

@@ -150,4 +150,7 @@ public class QwSopTemp implements Serializable
 
     @TableField(exist = false)
     private String createByDeptName;
+    
+    @TableField(exist = false)
+    private String openIsAtAll;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/sop/domain/QwSopTempRules.java

@@ -83,4 +83,7 @@ public class QwSopTempRules{
     private Integer dayNum;
     @TableField(exist = false)
     private FsUserCourseVideoRedPackage red;
+    
+     /**是否@所有人  1是0否**/
+    private Integer isAtAll;
 }

+ 6 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java

@@ -467,6 +467,12 @@ public class QwSopTempServiceImpl implements IQwSopTempService {
                     rules.setTime(time);
                 }
 
+                if (temp.getOpenIsAtAll() != null && temp.getOpenIsAtAll().equals("1")){
+                    rules.setIsAtAll(1);
+                }else {
+                    rules.setIsAtAll(0);
+                }
+
                 rules.setContentType(2);
                 rules.setType(2);
                 rules.setCourseType(0);

+ 46 - 0
fs-service/src/main/java/com/fs/wxwork/dto/WxSendTextAtMsgTwoDTO.java

@@ -0,0 +1,46 @@
+package com.fs.wxwork.dto;
+
+import com.fs.ipad.vo.BaseVo;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class WxSendTextAtMsgTwoDTO extends BaseVo {
+    /**
+     * 消息的唯一标识符 (UUID)
+     */
+    private String uuid;
+
+    /**
+     * 要发送的人或群id
+     */
+    private Long send_userid;
+
+    /**
+     * 发送者用户 ID
+     */
+    private List<Contentva> contentva;
+    /**
+     * 是否为群组消息
+     * <p>
+     * true: 群组消息; false: 单聊消息
+     * </p>
+     */
+    private Boolean isRoom;
+
+    @Data
+    public static class Contentva {
+        private Integer msgtype;
+        private String content;
+        /**
+         * "msgtype":5,//@类型
+         * "vid":0 //填0就是所有人
+         * <p>
+         * "msgtype":5, //就是@人的类型
+         * "vid":788130xx38 //@人id
+         */
+        private Integer vid;
+    }
+
+}

+ 7 - 0
fs-service/src/main/java/com/fs/wxwork/service/WxWorkServiceNew.java

@@ -9,6 +9,7 @@ import com.fs.ipad.param.WxSendAtMsgParam;
 import com.fs.ipad.vo.WxGetSessionRoomListVo;
 import com.fs.ipad.vo.WxRoomUserListVo;
 import com.fs.ipad.vo.WxSendAtMsgVo;
+import com.fs.ipad.vo.WxSendTextAtMsgVo;
 import com.fs.qw.domain.QwIpadServer;
 import com.fs.qw.service.IQwIpadServerService;
 import com.fs.wxwork.dto.*;
@@ -232,4 +233,10 @@ public class WxWorkServiceNew {
         String url = getUrl(serverId) + "/RoomIdToChatId";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxWorkChatIdToRoomIdResp>>() {}, serverId);
     }
+    
+    
+    public WxWorkResponseDTO<WxSendTextAtMsgVo> sendTextAtMsgTwo(WxSendTextAtMsgTwoDTO param, Long serverId) {
+        String url = getUrl(serverId) + "/SendTextAtMsgTwo";
+        return WxWorkHttpUtil.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxSendTextAtMsgVo>>() {});
+    }
 }

+ 1 - 0
fs-service/src/main/resources/application-config-dev-jnlzjk.yml

@@ -87,6 +87,7 @@ cloud_host:
   company_name: 济南联志健康
   projectCode: LZJK
   spaceName:
+  volcengineUrl: https://jnlzvolcengine.ylrztop.com
 headerImg:
   imgUrl:
 

+ 1 - 0
fs-service/src/main/resources/application-config-druid-hsyy.yml

@@ -83,6 +83,7 @@ cloud_host:
   company_name: 河山医院
   projectCode: heshanyy
   spaceName:
+  volcengineUrl:
 #看课授权时显示的头像
 headerImg:
   imgUrl: https://hsyy-1348049832.cos.ap-chongqing.myqcloud.com/hsyy.jpg

+ 1 - 0
fs-service/src/main/resources/application-config-druid-jnlzjk.yml

@@ -88,6 +88,7 @@ cloud_host:
   company_name: 济南联志健康
   projectCode: LZJK
   spaceName:
+  volcengineUrl: https://jnlzvolcengine.ylrztop.com
 headerImg:
   imgUrl:
 

+ 1 - 0
fs-service/src/main/resources/application-config-druid-sxjz.yml

@@ -88,6 +88,7 @@ cloud_host:
   company_name: 今正科技
   projectCode: SXJZ
   spaceName:
+  volcengineUrl:
 #看课授权时显示的头像
 headerImg:
   imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png

+ 1 - 0
fs-service/src/main/resources/application-config-myhk.yml

@@ -88,6 +88,7 @@ cloud_host:
   company_name: 木易华康
   projectCode: MYHK
   spaceName: myhk-2114522511
+  volcengineUrl: https://myhkvolcengine.ylrztop.com
 #看课授权时显示的头像
 headerImg:
   imgUrl: https://fs-1346741853.cos.ap-chengdu.myqcloud.com/fs/20250323/6189704f2e134b84ad9c9e7c9999f103.jpg

+ 2 - 0
fs-service/src/main/resources/application-config-zkzh.yml

@@ -115,6 +115,8 @@ tencent_cloud_config:
 cloud_host:
   company_name: 中康
   projectCode: ZKZH
+  spaceName: sxzk-2114522511
+  volcengineUrl:
 headerImg:
   imgUrl: https://zkzh-2025.oss-cn-beijing.aliyuncs.com/fs/20250619/e31b5e051a474a7a9b4ad02575b46196.png
 

+ 1 - 1
fs-service/src/main/resources/application-druid-sxjz.yml

@@ -164,7 +164,7 @@ token:
 openIM:
     secret: openIM123
     userID: imAdmin
-    url: https://web.im.fbylive.com/api
+    url: https://web.im.xianhthj.cn/api
 #是否使用新im
 im:
     type: NONE

+ 2 - 1
fs-service/src/main/resources/mapper/live/LiveAfterSalesMapper.xml

@@ -68,7 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         las.order_status, las.create_time, las.is_del, las.user_id, las.consignee, las.phone_number, las.address, las.company_id, las.company_user_id, las.dept_id,
         cu.nick_name as company_user_nick_name, c.company_name,lo.order_id,lo.order_code,lo.user_phone,las.user_id,lo.item_json,lo.pay_time as orderPayTime,
         lo.user_address,lo.user_name,lo.pay_price,lo.total_postage,lop.bank_serial_no,lo.delivery_sn as orderDeliveryId,lo.delivery_name as orderDeliveryName,
-        lo.delivery_code as orderDeliverySn,lo.status as orderStatus,lop.bank_transaction_id,lo.pay_money
+        lo.delivery_code as orderDeliverySn,lo.status as orderStatus,lop.bank_transaction_id,lo.pay_money,lop.pay_code as payCode
         from live_after_sales las
         left join live_order lo on lo.order_id = las.order_id
         left join company_user cu on cu.user_id = las.company_user_id
@@ -79,6 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
 
         <where>
+            <if test="hfOrderCode != null and hfOrderCode != ''"> and lop.pay_code = #{hfOrderCode}</if>
             <if test="liveId != null and liveId != ''"> and las.live_id = #{liveId}</if>
             <if test="companyUserNickName != null and companyUserNickName != ''"> and cu.nick_name like concat(#{companyUserNickName},'%')</if>
             <if test="storeId != null and storeId != ''"> and las.store_id = #{storeId}</if>

+ 35 - 0
fs-service/src/main/resources/mapper/live/LiveWatchLogMapper.xml

@@ -210,4 +210,39 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectLiveWatchLogByLiveId" resultType="com.fs.live.domain.LiveWatchLog">
         select * from live_watch_log where live_id = #{liveId}
     </select>
+
+    <select id="selectLiveWatchLogListInfo"   parameterType="LiveWatchLog" resultType="com.fs.live.vo.LiveWatchLogListVO">
+        select
+        t2.nick_name as userName,
+        t2.avatar as userAvatar,
+        t3.live_name,
+        t4.name as qwExternalName,
+        t4.avatar as qwExternalAvatar,
+        t5.nick_name as companyUserName,
+        t6.qw_user_name,
+        t1.*
+        from live_watch_log t1
+        left join fs_user t2 on t1.user_id = t2.user_id
+        left join live t3 on t3.live_id = t1.live_id
+        left join qw_external_contact t4 on t4.id = t1.external_contact_id
+        left join company_user t5 on t5.user_id = t1.company_user_id
+        left join qw_user t6 on t6.id = t1.qw_user_id
+        <where>
+            <if test="userId != null "> and t1.user_id = #{userId}</if>
+            <if test="liveId != null "> and t1.live_id = #{liveId}</if>
+            <if test="logType != null "> and t1.log_type = #{logType}</if>
+            <if test="externalContactId != null "> and t1.external_contact_id = #{externalContactId}</if>
+            <if test="companyId != null "> and t1.company_id = #{companyId}</if>
+            <if test="companyUserId != null "> and t1.company_user_id = #{companyUserId}</if>
+            <if test="finishTime != null "> and t1.finish_time = #{finishTime}</if>
+            <if test="sopCreateTime != null "> and t1.sop_create_time = #{sopCreateTime}</if>
+            <if test="sendAppId != null  and sendAppId != ''"> and t1.send_app_id = #{sendAppId}</if>
+            <if test="logSource != null "> and t1.log_source = #{logSource}</if>
+            <if test="qwUserId != null  and qwUserId != ''"> and t1.qw_user_id = #{qwUserId}</if>
+            <if test="watchType != null">and t1.watch_type = #{watchType} </if>
+            <if test="corpId != null">and t1.corp_id = #{corpId} </if>
+            <if test="liveBuy != null">and t1.live_buy = #{liveBuy} </if>
+            <if test="replayBuy != null">and t1.replay_buy = #{replayBuy} </if>
+        </where>
+    </select>
 </mapper>

+ 5 - 0
fs-user-app/src/main/java/com/fs/app/controller/course/CourseQwController.java

@@ -371,6 +371,11 @@ public class CourseQwController extends AppBaseController {
         return courseVideoService.getVidByJob();
     }
 
+    @GetMapping("/testUpdateLineTwo")
+    public R testUpdateLineTwo() {
+        return courseVideoService.getVideoInfoByVid();
+    }
+
     @Autowired
     private IFsCourseTrafficLogService courseTrafficLogService;
 

+ 8 - 0
fs-user-app/src/main/java/com/fs/app/controller/course/CourseTransferController.java

@@ -71,4 +71,12 @@ public class CourseTransferController {
         return paymentService.TransferNotifyWithCompanyId(companyId,notifyData,request);
     }
 
+    @Autowired
+    private IFsCourseRedPacketLogService fsCourseRedPacketLogService;
+
+    @GetMapping("/getBillsByTransferBillNo")
+    public R getBillsByTransferBillNo(String transferBillNo){
+        return fsCourseRedPacketLogService.getBillsByTransferBillNo(transferBillNo);
+    }
+
 }