Browse Source

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java

caoliqin 2 days ago
parent
commit
c5eb3b4bb6

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

@@ -249,5 +249,16 @@ public class FsUserCourseVideoController extends AppBaseController {
         return fsUserCourseVideoService.setWatchCourseTime(collect);
         return fsUserCourseVideoService.setWatchCourseTime(collect);
     }
     }
 
 
+    /**
+     * 获取跳转微信小程序的链接地址
+     * @param linkStr
+     * @return
+     */
+    @Login
+    @GetMapping("/getGotoWxAppLink")
+    @ApiOperation("获取跳转微信小程序的链接地址")
+    public ResponseResult<String> getGotoWxAppLink(String linkStr) {
+        return ResponseResult.ok(courseLinkService.getGotoWxAppLink(linkStr));
+    }
 
 
 }
 }

+ 32 - 10
fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsInfoController.java

@@ -32,10 +32,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
+import java.io.IOException;
+import java.util.*;
 import java.util.function.Predicate;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -112,13 +110,28 @@ public class SopUserLogsInfoController extends BaseController
                 });
                 });
             }
             }
 
 
+
+//            Predicate<SopUserLogsInfo> tagFilter = item ->
+//                    sopUserLogsInfo.getTagIds() == null ||
+//                            sopUserLogsInfo.getTagIds().isEmpty() ||
+//                            item.getTagIds().contains(sopUserLogsInfo.getTagIds());
+
+            Predicate<SopUserLogsInfo> tagFilter = item -> {
+                String queryTagIds = sopUserLogsInfo.getTagIds();
+                String itemTagIds = item.getTagIds();
+
+                if (queryTagIds == null || queryTagIds.trim().equals("[]")) {
+                    return true;
+                }
+                List<String> queryTags = parseTagIds(queryTagIds);
+                List<String> itemTags = parseTagIds(itemTagIds);
+
+                // 检查 itemTags 是否包含所有 queryTags(AND 关系)
+                return itemTags.containsAll(queryTags);
+            };
+
             // 优化过滤条件
             // 优化过滤条件
             boolean isRemarkEmpty = StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark());
             boolean isRemarkEmpty = StringUtil.strIsNullOrEmpty(sopUserLogsInfo.getRemark());
-            Predicate<SopUserLogsInfo> tagFilter = item ->
-                    sopUserLogsInfo.getTagIds() == null ||
-                            sopUserLogsInfo.getTagIds().isEmpty() ||
-                            item.getTagIds().contains(sopUserLogsInfo.getTagIds());
-
             Predicate<SopUserLogsInfo> remarkFilter = item ->
             Predicate<SopUserLogsInfo> remarkFilter = item ->
                     isRemarkEmpty ||
                     isRemarkEmpty ||
                             item.getRemark().contains(sopUserLogsInfo.getRemark());
                             item.getRemark().contains(sopUserLogsInfo.getRemark());
@@ -196,7 +209,16 @@ public class SopUserLogsInfoController extends BaseController
 //        }
 //        }
     }
     }
 
 
-
+    private List<String> parseTagIds(String jsonTagIds) {
+        if (jsonTagIds == null || jsonTagIds.trim().isEmpty() || jsonTagIds.equals("[]")) {
+            return Collections.emptyList();
+        }
+        // 去掉开头和结尾的 [ ],然后按 "," 分割
+        return Arrays.stream(jsonTagIds.replaceAll("[\\[\\]\"]", "").split(","))
+                .map(String::trim)
+                .filter(s -> !s.isEmpty())
+                .collect(Collectors.toList());
+    }
 //    /**
 //    /**
 //     * 导出sopUserLogsInfo列表
 //     * 导出sopUserLogsInfo列表
 //     */
 //     */

+ 15 - 9
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -635,7 +635,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
 
                         insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content, qwUserId,
                         insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content, qwUserId,
                                 companyUserId, companyId, qwUserByRedis.getWelcomeText(),qwUserByRedis.getQwUserName(),
                                 companyUserId, companyId, qwUserByRedis.getWelcomeText(),qwUserByRedis.getQwUserName(),
-                                groupChatMap, miniAppId);
+                                groupChatMap, miniAppId,config);
 
 
                     }
                     }
                 } catch (Exception e) {
                 } catch (Exception e) {
@@ -678,7 +678,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
     private void insertSopUserLogs(List<SopUserLogsInfo> sopUserLogsInfos, SopUserLogsVo logVo, Date sendTime,
     private void insertSopUserLogs(List<SopUserLogsInfo> sopUserLogsInfos, SopUserLogsVo logVo, Date sendTime,
                                    QwSopRuleTimeVO ruleTimeVO, QwSopTempSetting.Content content,
                                    QwSopRuleTimeVO ruleTimeVO, QwSopTempSetting.Content content,
                                    String qwUserId,String companyUserId,String companyId,String welcomeText,String qwUserName,
                                    String qwUserId,String companyUserId,String companyId,String welcomeText,String qwUserName,
-                                   Map<String, QwGroupChat> groupChatMap,String miniAppId) {
+                                   Map<String, QwGroupChat> groupChatMap,String miniAppId,CourseConfig config) {
         String formattedSendTime = sendTime.toInstant()
         String formattedSendTime = sendTime.toInstant()
                 .atZone(ZoneId.systemDefault())
                 .atZone(ZoneId.systemDefault())
                 .format(DATE_TIME_FORMATTER);
                 .format(DATE_TIME_FORMATTER);
@@ -704,7 +704,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             if (content.getIndex() == 0) {
             if (content.getIndex() == 0) {
                 QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, groupChat.getChatId(), groupChat.getName(), null, isOfficial, null);
                 QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, groupChat.getChatId(), groupChat.getName(), null, isOfficial, null);
                 handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
                 handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
-                        type, qwUserId, companyUserId, companyId, groupChat.getChatId(), welcomeText, qwUserName, null, true, miniAppId, groupChat);
+                        type, qwUserId, companyUserId, companyId, groupChat.getChatId(), welcomeText, qwUserName,
+                        null, true, miniAppId, groupChat,config);
             } else {
             } else {
                 if(groupChat.getChatUserList() != null && !groupChat.getChatUserList().isEmpty()){
                 if(groupChat.getChatUserList() != null && !groupChat.getChatUserList().isEmpty()){
                     groupChat.getChatUserList().forEach(user -> {
                     groupChat.getChatUserList().forEach(user -> {
@@ -712,7 +713,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                         ruleTimeVO.setRemark("客户群催课");
                         ruleTimeVO.setRemark("客户群催课");
                         QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, user.getUserId(), user.getName(), null, isOfficial, null);
                         QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, user.getUserId(), user.getName(), null, isOfficial, null);
                         handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
                         handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
-                                type, qwUserId, companyUserId, companyId, user.getId().toString(), welcomeText, qwUserName, null, false, miniAppId, groupChat);
+                                type, qwUserId, companyUserId, companyId, user.getId().toString(), welcomeText, qwUserName,
+                                null, false, miniAppId, groupChat,config);
                     });
                     });
                 }
                 }
             }
             }
@@ -725,7 +727,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     Long fsUserId = contactId.getFsUserId();
                     Long fsUserId = contactId.getFsUserId();
                     QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, contactId.getExternalContactId(), externalUserName, fsUserId, isOfficial, contactId.getExternalId());
                     QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, contactId.getExternalContactId(), externalUserName, fsUserId, isOfficial, contactId.getExternalId());
                     handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
                     handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
-                            type, qwUserId, companyUserId, companyId, externalId, welcomeText, qwUserName, fsUserId, false, miniAppId, null);
+                            type, qwUserId, companyUserId, companyId, externalId, welcomeText, qwUserName, fsUserId, false, miniAppId, null,config);
                 } catch (Exception e) {
                 } catch (Exception e) {
                     log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
                     log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
                 }
                 }
@@ -833,14 +835,16 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                                       SopUserLogsVo logVo, Date sendTime, Long courseId,
                                       SopUserLogsVo logVo, Date sendTime, Long courseId,
                                       Long videoId, int type, String qwUserId,
                                       Long videoId, int type, String qwUserId,
                                       String companyUserId, String companyId, String externalId, String welcomeText,
                                       String companyUserId, String companyId, String externalId, String welcomeText,
-                                      String qwUserName, Long fsUserId, boolean isGroupChat, String miniAppId, QwGroupChat groupChat) {
+                                      String qwUserName, Long fsUserId, boolean isGroupChat, String miniAppId,
+                                      QwGroupChat groupChat,CourseConfig config) {
         switch (type) {
         switch (type) {
             case 1:
             case 1:
                 handleNormalMessage(sopLogs, content,companyUserId);
                 handleNormalMessage(sopLogs, content,companyUserId);
                 break;
                 break;
             case 2:
             case 2:
                 handleCourseMessage(sopLogs, content, logVo, sendTime, courseId, videoId,
                 handleCourseMessage(sopLogs, content, logVo, sendTime, courseId, videoId,
-                        qwUserId, companyUserId, companyId, externalId, welcomeText,qwUserName, fsUserId, isGroupChat, miniAppId, groupChat);
+                        qwUserId, companyUserId, companyId, externalId, welcomeText,qwUserName, fsUserId,
+                        isGroupChat, miniAppId, groupChat,config);
                 break;
                 break;
             case 3:
             case 3:
                 handleOrderMessage(sopLogs, content);
                 handleOrderMessage(sopLogs, content);
@@ -873,7 +877,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                                      SopUserLogsVo logVo, Date sendTime, Long courseId,
                                      SopUserLogsVo logVo, Date sendTime, Long courseId,
                                      Long videoId, String qwUserId, String companyUserId,
                                      Long videoId, String qwUserId, String companyUserId,
                                      String companyId, String externalId, String welcomeText, String qwUserName,
                                      String companyId, String externalId, String welcomeText, String qwUserName,
-                                     Long fsUserId, boolean isGroupChat, String miniAppId, QwGroupChat groupChat) {
+                                     Long fsUserId, boolean isGroupChat, String miniAppId, QwGroupChat groupChat,CourseConfig config) {
         // 深拷贝 Content 对象,避免使用 JSON
         // 深拷贝 Content 对象,避免使用 JSON
         QwSopTempSetting.Content clonedContent = deepCopyContent(content);
         QwSopTempSetting.Content clonedContent = deepCopyContent(content);
         if (clonedContent == null) {
         if (clonedContent == null) {
@@ -974,7 +978,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     setting.setMiniprogramPage(sortLink.replaceAll("^[\\s\\u2005]+", ""));
                     setting.setMiniprogramPage(sortLink.replaceAll("^[\\s\\u2005]+", ""));
 
 
                     try {
                     try {
-                        setting.setMiniprogramPicUrl(StringUtil.strIsNullOrEmpty(setting.getMiniprogramPicUrl())?"https://cos.his.cdwjyyh.com/fs/20250331/ec2b4e73be8048afbd526124a655ad56.png":setting.getMiniprogramPicUrl());
+                        setting.setMiniprogramPicUrl(StringUtil.strIsNullOrEmpty(setting.getMiniprogramPicUrl())? config.getSidebarImageUrl():setting.getMiniprogramPicUrl());
                     } catch (Exception e) {
                     } catch (Exception e) {
                         log.error("赋值-小程序封面地址失败-" + e);
                         log.error("赋值-小程序封面地址失败-" + e);
                     }
                     }
@@ -1241,6 +1245,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             log.error("CourseConfig is not loaded.");
             log.error("CourseConfig is not loaded.");
             return "";
             return "";
         }
         }
+
+
 //        if (StringUtils.isEmpty(config.getMiniprogramPage())){
 //        if (StringUtils.isEmpty(config.getMiniprogramPage())){
 //            log.error("miniprogramPage is not loaded.");
 //            log.error("miniprogramPage is not loaded.");
 //            return "";
 //            return "";

+ 2 - 0
fs-service/src/main/java/com/fs/common/param/LoginMaWxParam.java

@@ -53,4 +53,6 @@ public class LoginMaWxParam implements Serializable {
     @ApiModelProperty(value = "小程序授权类型")
     @ApiModelProperty(value = "小程序授权类型")
     private Integer authType;
     private Integer authType;
 
 
+    private String appId;
+
 }
 }

+ 1 - 0
fs-service/src/main/java/com/fs/course/config/CourseConfig.java

@@ -36,6 +36,7 @@ public class CourseConfig implements Serializable {
 
 
     private String companyUserQRCode;// 默认客服二维码图片
     private String companyUserQRCode;// 默认客服二维码图片
     private String courseLogo;//课程Logo
     private String courseLogo;//课程Logo
+    private String sidebarImageUrl;//侧边栏公共图
     private Integer delayStart;
     private Integer delayStart;
     private Integer delayEnd;
     private Integer delayEnd;
 
 

+ 9 - 0
fs-service/src/main/java/com/fs/course/service/IFsCourseLinkService.java

@@ -83,4 +83,13 @@ public interface IFsCourseLinkService
     R getRealLinkH5(String link);
     R getRealLinkH5(String link);
 
 
     R createRoomLink(FsCourseLinkRoomParam param, QwUser qwUser);
     R createRoomLink(FsCourseLinkRoomParam param, QwUser qwUser);
+
+    String testGetAppLink();
+
+    /**
+     * 获取跳转微信小程序的链接地址
+     * @param linkStr
+     * @return
+     */
+    String getGotoWxAppLink(String linkStr);
 }
 }

+ 162 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.course.service.impl;
 package com.fs.course.service.impl;
 
 
+import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.hutool.json.JSONUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
@@ -10,6 +11,7 @@ import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.date.DateUtil;
 import com.fs.common.utils.date.DateUtil;
 import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.config.cloud.CloudHostProper;
 import com.fs.config.cloud.CloudHostProper;
+import com.fs.core.config.WxMaConfiguration;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.*;
 import com.fs.course.domain.*;
 import com.fs.course.mapper.FsCourseDomainNameMapper;
 import com.fs.course.mapper.FsCourseDomainNameMapper;
@@ -20,6 +22,8 @@ import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.FsCourseLinkRoomParam;
 import com.fs.course.param.FsCourseLinkRoomParam;
 import com.fs.course.service.IFsCourseLinkService;
 import com.fs.course.service.IFsCourseLinkService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.service.IFsUserCourseService;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.utils.ConfigUtil;
 import com.fs.qw.domain.QwGroupChat;
 import com.fs.qw.domain.QwGroupChat;
 import com.fs.qw.domain.QwGroupChatUser;
 import com.fs.qw.domain.QwGroupChatUser;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.domain.QwUser;
@@ -32,13 +36,26 @@ import com.fs.system.service.ISysConfigService;
 import com.fs.voice.utils.StringUtil;
 import com.fs.voice.utils.StringUtil;
 import lombok.Synchronized;
 import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.mp.api.WxMpService;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZoneId;
@@ -661,4 +678,149 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
     }
     }
 
 
 
 
+    /**
+     *
+     * 生成跳转微信小程序的链接 base
+     *
+     * @param appid 微信appid
+     * @param path  跳转页面路径
+     * @param query 需要传参的String
+     * @return
+     */
+    public String getWxAppLink(String appid, String path, String query) {
+
+        StringBuilder wxAppLink = new StringBuilder("weixin://dl/business/?");
+        try {
+            wxAppLink.append("appid=").append(appid);
+            wxAppLink.append("&path=").append(path);
+            String encodedQuery =  URLEncoder.encode(URLEncoder.encode(query, StandardCharsets.UTF_8.toString()));
+            wxAppLink.append("&query=").append(encodedQuery);
+//            wxAppLink.append("&env_version=trial");
+//            if(StringUtils.isNotBlank(envVersion)){
+//                wxAppLink.append("&env_version=").append(envVersion);
+//            }
+
+        } catch (UnsupportedEncodingException e) {
+            log.error("生成跳转微信小程序的链接失败" + e.getMessage());
+            return "生成失败";
+        }
+        return wxAppLink.toString();
+
+    }
+
+    @Override
+    public String testGetAppLink() {
+        String pageLink = "/pages_course/video.html?course\\u003d{\\\"companyId\\\":100,\\\"companyUserId\\\":2020,\\\"corpId\\\":\\\"ww51717e2b71d5e2d3\\\",\\\"courseId\\\":63,\\\"link\\\":\\\"1943203055923101696\\\",\\\"linkType\\\":3,\\\"qwExternalId\\\":20812637,\\\"qwUserId\\\":\\\"9112\\\",\\\"videoId\\\":400}";
+        String miniprogramAppid = "wx76cb55db092a41ae";
+        if (StringUtils.isNotBlank(pageLink)) {
+
+            //解析pageLink
+            String[] split = pageLink.split("\\?");
+            if (split.length == 2 && split[0].length() > 0 && split[1].length() > 0) {
+                //处理页面路径
+                String pageUrl =split[0];
+                if(pageUrl.startsWith("/")){
+                    pageUrl = pageUrl.substring(1);
+                }
+                if(pageUrl.contains(".html")){
+                    pageUrl = pageUrl.replace(".html", "");
+                }
+                //处理参数
+                String query = split[1];
+                query = query.replace("\\u003d", "=");
+                String wxAppLink = getWxAppLink(miniprogramAppid, pageUrl, query);
+                return wxAppLink;
+            } else {
+                return "页面链接错误,获取失败";
+            }
+        }
+        return pageLink;
+
+    }
+
+    /**
+     * 获取跳转微信小程序的链接地址
+     * @param linkStr
+     * @return
+     */
+    @Override
+    public String getGotoWxAppLink(String linkStr) {
+//        CloseableHttpClient client = null;
+//        try {
+//            client = HttpClients.createDefault();
+//            String[] split = linkStr.split("\\?");
+//            if (split.length == 2 && split[0].length() > 0 && split[1].length() > 0) {
+//                //处理页面路径
+//                String pageUrl = split[0];
+//                if (pageUrl.startsWith("/")) {
+//                    pageUrl = pageUrl.substring(1);
+//                }
+//                //处理参数
+//                String query = split[1];
+//                String json = configService.selectConfigByKey("course.config");
+//                CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+//                String miniprogramAppid = config.getMiniprogramAppid();
+//                if (StringUtils.isBlank(miniprogramAppid)) {
+//                    return "未配置点播小程序id";
+//                }
+//                if(StringUtils.isBlank(code)){
+//                    return "参数错误,请传入code";
+//                }
+//                //获取微信token
+//                final WxMaService wxService = WxMaConfiguration.getMaService("wx76cb55db092a41ae");
+//                String token = wxService.getAccessToken();
+//                HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/wxa/generate_urllink?access_token=" + token);
+//                JSONObject bodyObj = new JSONObject();
+//                bodyObj.put("path", pageUrl);
+//                bodyObj.put("query", query);
+//                log.info("微信小程序请求参数打印:{}", bodyObj.toJSONString());
+//                StringEntity entity = new StringEntity(bodyObj.toJSONString(),"UTF-8");
+//                httpPost.setEntity(entity);
+//                httpPost.setHeader("Content-type", "application/json");
+//                HttpEntity response = client.execute(httpPost).getEntity();
+//                String responseString = EntityUtils.toString(response);
+//                log.info("微信小程序接口响应数据:{}", responseString);
+//                JSONObject jsonObject = JSONObject.parseObject(responseString);
+//                if(null != jsonObject && !jsonObject.isEmpty() && jsonObject.containsKey("url_link")){
+//                    return jsonObject.getString("url_link");
+//                }
+//            } else {
+//                return "页面链接错误,获取失败";
+//            }
+//
+//        } catch (WxErrorException e) {
+//            throw new RuntimeException(e);
+//        } catch (ClientProtocolException e) {
+//            throw new RuntimeException(e);
+//        } catch (IOException e) {
+//            throw new RuntimeException(e);
+//        }
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+        String miniprogramAppid = config.getMiniprogramAppid();
+        if (StringUtils.isBlank(miniprogramAppid)) {
+                    return "未配置点播小程序id";
+                }
+//        String envVersion = "trial";
+//        String envVersion = version;
+        if (StringUtils.isNotBlank(linkStr)) {
+            //解析pageLink
+            String[] split = linkStr.split("\\?");
+            if (split.length == 2 && split[0].length() > 0 && split[1].length() > 0) {
+                //处理页面路径
+                String pageUrl =split[0];
+                if(pageUrl.startsWith("/")){
+                    pageUrl = pageUrl.substring(1);
+                }
+                //处理参数
+                String query = split[1];
+//                query = query.replace("\\u003d", "=");
+                String wxAppLink = getWxAppLink(miniprogramAppid, pageUrl, query);
+                return wxAppLink;
+            } else {
+                return "页面链接错误,获取失败";
+            }
+        }
+        return "";
+    }
 }
 }

+ 11 - 3
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -1736,6 +1736,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Override
     @Override
     public R createMiniLink(FsCourseLinkMiniParam param) {
     public R createMiniLink(FsCourseLinkMiniParam param) {
 
 
+
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+
         QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
         QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
 
 
         if (qwUser==null||qwUser.getCompanyId()==null||qwUser.getCompanyUserId()==null){
         if (qwUser==null||qwUser.getCompanyId()==null||qwUser.getCompanyUserId()==null){
@@ -1757,7 +1761,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         JSONObject news = new JSONObject(true);
         JSONObject news = new JSONObject(true);
         news.put("miniprogramAppid", qwCompany.getMiniAppId());
         news.put("miniprogramAppid", qwCompany.getMiniAppId());
         news.put("miniprogramTitle", param.getTitle());
         news.put("miniprogramTitle", param.getTitle());
-        news.put("miniprogramPicUrl", "https://cos.his.cdwjyyh.com/fs/20250523/9c8af5735d784847818cada7fa776a7b.jpg");
+        news.put("miniprogramPicUrl", config.getSidebarImageUrl());
         news.put("miniprogramPage", linkByMiniApp);
         news.put("miniprogramPage", linkByMiniApp);
 
 
         return R.ok().put("data",news);
         return R.ok().put("data",news);
@@ -1801,7 +1805,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         JSONObject news = new JSONObject(true); // true 表示保持字段顺序
         JSONObject news = new JSONObject(true); // true 表示保持字段顺序
         news.put("linkTitle", param.getTitle());
         news.put("linkTitle", param.getTitle());
         news.put("linkDescribe", param.getTitle());
         news.put("linkDescribe", param.getTitle());
-        news.put("linkImageUrl", "https://cos.his.cdwjyyh.com/fs/20250523/9c8af5735d784847818cada7fa776a7b.jpg");
+        news.put("linkImageUrl", config.getSidebarImageUrl());
         news.put("linkUrl", linkByCartLink);
         news.put("linkUrl", linkByCartLink);
 
 
         return R.ok().put("data",news);
         return R.ok().put("data",news);
@@ -2011,6 +2015,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
 
     @Override
     @Override
     public R createRoomMiniLink(FsCourseLinkMiniParam param) {
     public R createRoomMiniLink(FsCourseLinkMiniParam param) {
+
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+
         QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
         QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
 
 
         if (qwUser==null||qwUser.getCompanyId()==null||qwUser.getCompanyUserId()==null){
         if (qwUser==null||qwUser.getCompanyId()==null||qwUser.getCompanyUserId()==null){
@@ -2029,7 +2037,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         JSONObject news = new JSONObject(true);
         JSONObject news = new JSONObject(true);
         news.put("miniprogramAppid", qwCompany.getMiniAppId());
         news.put("miniprogramAppid", qwCompany.getMiniAppId());
         news.put("miniprogramTitle", param.getTitle());
         news.put("miniprogramTitle", param.getTitle());
-        news.put("miniprogramPicUrl", "https://cos.his.cdwjyyh.com/fs/20250523/9c8af5735d784847818cada7fa776a7b.jpg");
+        news.put("miniprogramPicUrl", config.getSidebarImageUrl());
         news.put("miniprogramPage", linkByMiniApp);
         news.put("miniprogramPage", linkByMiniApp);
 
 
         return R.ok().put("data",news);
         return R.ok().put("data",news);

+ 77 - 22
fs-service/src/main/java/com/fs/statis/domain/FsStatisEveryDayWatch.java

@@ -1,15 +1,15 @@
 package com.fs.statis.domain;
 package com.fs.statis.domain;
 
 
+import com.fs.common.annotation.Excel;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Builder;
 import lombok.Data;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
 
 
-import java.time.LocalDateTime;
+import java.time.LocalDate;
 
 
 /**
 /**
- * 每日统计数据实体类
- * 对应表 fs_statis_every_day_watch
+ * 销售观看统计实体类
  */
  */
 @Data
 @Data
 @NoArgsConstructor
 @NoArgsConstructor
@@ -20,86 +20,141 @@ public class FsStatisEveryDayWatch {
     /**
     /**
      * 主键ID
      * 主键ID
      */
      */
-    private Integer id;
+    private Long id;
+
+    /**
+     * 部门
+     */
+    private Long deptId;
 
 
     /**
     /**
      * 数据日期
      * 数据日期
      */
      */
-    private LocalDateTime dataDate;
+    @Excel(name = "日期")
+    private LocalDate dataDate;
 
 
     /**
     /**
-     * 训练营id
+     * 部门名称
+     */
+    private String deptName;
+
+    /**
+     * 销售id
+     */
+    private Long companyUserId;
+    /**
+     * 销售名称
      */
      */
-    private Integer periodId;
+    private String companyUserName;
 
 
     /**
     /**
      * 训练营人数
      * 训练营人数
      */
      */
-    private Integer periodNum;
+    @Excel(name = "训练营人数")
+    private Long trainCampNum;
+
+    /**
+     * 发课数
+     */
+    @Excel(name = "发课数")
+    private Long sendNum;
 
 
     /**
     /**
      * 未报名人数
      * 未报名人数
      */
      */
-    private Integer notRegNum;
+    @Excel(name = "未报名人数")
+    private Long notRegisteredNum;
 
 
     /**
     /**
      * 已报名人数
      * 已报名人数
      */
      */
-    private Integer registeredNum;
+    @Excel(name = "已报名人数")
+    private Long registeredNum;
+    /**
+     * 完课人数
+     */
+    @Excel(name = "完课人数")
+    private Long completedNum;
+    /**
+     * 看课中断数
+     */
+    @Excel(name = "看课中断数")
+    private Long interruptNum;
+
+    /**
+     * 企微重粉
+     */
+    @Excel(name = "企微重粉")
+    private Long qwRepeatNum;
+
+    /**
+     * 小程序(看课)重粉
+     */
+    @Excel(name = "小程序(看课)重粉")
+    private Long userRepeatNum;
 
 
     /**
     /**
      * 报名率
      * 报名率
      */
      */
+    @Excel(name = "上线率")
     private Float regRate;
     private Float regRate;
 
 
     /**
     /**
      * 完课率
      * 完课率
      */
      */
-    private Float completedRate;
+    @Excel(name = "完课率")
+    private Float finishedRate;
 
 
     /**
     /**
      * 未上线-总数
      * 未上线-总数
      */
      */
-    private Integer offlineTotal;
+    private Long offlineTotal;
 
 
     /**
     /**
      * 未上线-未参与
      * 未上线-未参与
      */
      */
-    private Integer offlineNotRegNum;
+    private Long offlineNotPart;
 
 
     /**
     /**
-     * 未上线-未观看
+     * 未上线-未观看 (原SQL注释为'为观看',推测应为'未观看')
      */
      */
-    private Integer offlineNotWatchNum;
+    private Long offlineNotWatched;
 
 
     /**
     /**
      * 已上线-总数
      * 已上线-总数
      */
      */
-    private Integer onlineTotal;
+    private Long onlineTotal;
 
 
     /**
     /**
      * 已上线-上线率
      * 已上线-上线率
      */
      */
-    private Float onlineRate;
+    private Float onlineOnlineRate;
 
 
     /**
     /**
      * 已上线-完播率
      * 已上线-完播率
      */
      */
-    private Float onlineCompletedRate;
+    private Float onlinePlaybackCompleRate;
 
 
     /**
     /**
      * 已上线-未完播
      * 已上线-未完播
      */
      */
-    private Integer onlineNotCompRateNum;
+    private Long onlineIncompletePlayback;
 
 
     /**
     /**
      * 已上线-已完播
      * 已上线-已完播
      */
      */
-    private Integer onlineCompletedNum;
+    private Long onlineCompletePlayback;
 
 
     /**
     /**
-     * 销售id
+     * 营期id
+     */
+    private String periodId;
+
+    /**
+     * 营期名称
      */
      */
-    private Integer companyUserId;
+    private String periodName;
+
 
 
+    private String sopId;
 }
 }

+ 2 - 2
fs-service/src/main/resources/mapper/sop/QwSopLogsMapper.xml

@@ -741,10 +741,10 @@
         ORDER BY send_time desc
         ORDER BY send_time desc
     </select>
     </select>
     <select id="queryPeriodNameById" resultType="java.lang.String">
     <select id="queryPeriodNameById" resultType="java.lang.String">
-        select concat(qw_user_key,'-',start_time) from sop_user_logs where id=#{periodId}
+        select concat(qw_user_id,'-',start_time) from sop_user_logs where id=#{periodId}
     </select>
     </select>
     <select id="queryAllPeriod" resultType="com.fs.sop.domain.QwSopLogs">
     <select id="queryAllPeriod" resultType="com.fs.sop.domain.QwSopLogs">
-        select id,concat(qw_user_key,'-',start_time) as sop_title from sop_user_logs
+        select id,concat(qw_user_id,'-',start_time) as sop_title from sop_user_logs
     </select>
     </select>
     <select id="selectQwSopLogsCountByQwUserId" resultType="java.lang.Long">
     <select id="selectQwSopLogsCountByQwUserId" resultType="java.lang.Long">
         select count(1) from qw_sop_logs
         select count(1) from qw_sop_logs

+ 3 - 0
fs-user-course/src/main/java/com/fs/course/controller/WxCompanyUserController.java

@@ -96,6 +96,9 @@ public class WxCompanyUserController extends AppBaseController {
         if (company.getCourseMiniAppId() == null) {
         if (company.getCourseMiniAppId() == null) {
             return R.error("小程序参数错误!");
             return R.error("小程序参数错误!");
         }
         }
+//        if (!param.getAppId().equals(company.getCourseMiniAppId())){
+//            return R.error("无权限,");
+//        }
 
 
         final WxMaService wxService = WxMaConfiguration.getMaService(company.getCourseMiniAppId());
         final WxMaService wxService = WxMaConfiguration.getMaService(company.getCourseMiniAppId());
         try {
         try {

+ 82 - 0
fs-user-course/src/main/java/com/fs/course/controller/WxPayController.java

@@ -0,0 +1,82 @@
+package com.fs.course.controller;
+
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.course.service.IFsCourseRedPacketLogService;
+import com.fs.course.service.IFsUserCourseOrderService;
+import com.fs.course.service.IFsUserVipOrderService;
+import com.fs.his.param.WxSendRedPacketParam;
+import com.fs.his.service.IFsInquiryOrderService;
+import com.fs.his.service.IFsPackageOrderService;
+import com.fs.his.service.IFsStoreOrderService;
+import com.fs.his.service.IFsStorePaymentService;
+import com.fs.sop.service.ISopUserLogsInfoService;
+import com.fs.system.service.ISysConfigService;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.service.WxPayService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Api("微信支付接口")
+@RestController
+@RequestMapping("/app/wxpay")
+public class WxPayController {
+    protected final Logger logger = LoggerFactory.getLogger(BaseController.class);
+    @Autowired
+    private WxPayService wxPayService;
+    @Autowired
+    private IFsInquiryOrderService inquiryOrderService;
+    @Autowired
+    private IFsStoreOrderService storeOrderService;
+    @Autowired
+    private IFsPackageOrderService packageOrderService;
+
+    @Autowired
+    private IFsUserCourseOrderService courseOrderService;
+
+    @Autowired
+    private IFsUserVipOrderService userVipOrderService;
+    @Autowired
+    private IFsStorePaymentService  paymentService;
+    @Autowired
+    private IFsCourseRedPacketLogService redPacketLogService;
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    private ISopUserLogsInfoService iSopUserLogsInfoService;
+
+    @PostMapping("/sendRedPacket")
+    public R sendRedPacket(@RequestBody WxSendRedPacketParam param){
+       return paymentService.sendRedPacketTest(param);
+    }
+
+    @PostMapping( "/TransferNotify")
+    public String TransferNotify(@RequestBody String notifyData,HttpServletRequest request, HttpServletResponse response) throws Exception {
+        return paymentService.transferNotify(notifyData,request);
+    }
+
+
+    @PostMapping( "/v3TransferNotify")
+    public String v3TransferNotify(@RequestBody String notifyData,HttpServletRequest request, HttpServletResponse response) throws Exception {
+        return paymentService.v3TransferNotify(notifyData,request);
+    }
+
+    @GetMapping("/test")
+    public void test(){
+        iSopUserLogsInfoService.updateSopUserInfoByExternalId(1L,123456L);
+    }
+
+
+
+}