cgp 3 дней назад
Родитель
Сommit
933e03d85f

+ 21 - 20
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -20,7 +20,6 @@ import com.fs.course.domain.FsCourseLink;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.mapper.FsCourseLinkMapper;
-import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.feishu.domain.FeishuAccount;
 import com.fs.feishu.domain.FeishuLinkError;
@@ -48,6 +47,7 @@ import com.fs.qw.service.IRedPacketService;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qwApi.param.QwExternalContactHParam;
 import com.fs.sop.domain.QwSopLogs;
+import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.service.IQwSopLogsService;
 import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.system.service.ISysConfigService;
@@ -57,6 +57,7 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
@@ -117,6 +118,8 @@ public class IpadSendServer {
     private FeishuLinkErrorMapper feishuLinkErrorMapper;
     @Autowired
     private FeiShuService feiShuService;
+    @Autowired
+    private QwSopLogsMapper qwSopLogsMapper;
 
     //销售的个人飞书应用账户缓存的key
     private static final String FEISHU_COMPANY_USER_KEY = "feishu:account_company_user:";
@@ -329,10 +332,10 @@ public class IpadSendServer {
         }
     }
 
-    public void sendLink(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Long externalId) {
+    public void sendLink(BaseVo vo, QwSopCourseFinishTempSetting.Setting content,QwSopLogs qwSopLogs, Long externalId) {
         if ("18".equals(content.getContentType())){
             // 完善content里面的飞书注册链接
-            completeFeishuRegisterLink(vo, content, externalId);
+            completeFeishuRegisterLink(vo, content,qwSopLogs, externalId);
         }
         // 文本
         LinkVo linkVo = LinkVo.builder()
@@ -353,11 +356,12 @@ public class IpadSendServer {
     /**
      * 完善飞书注册链接
      * */
-    public QwSopCourseFinishTempSetting.Setting completeFeishuRegisterLink(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Long externalId) {
-        try {
+    public QwSopCourseFinishTempSetting.Setting completeFeishuRegisterLink(BaseVo vo, QwSopCourseFinishTempSetting.Setting content,QwSopLogs qwSopLogs,Long externalId) {
+
             //初始链接
             String initUrl = content.getLinkUrl();
             // 1. 从初始链接提取携带的短链
+        try {
             String shortLink = extractLastPathSegment(initUrl);
             FsCourseLink fsCourseLink = courseLinkMapper.selectFsCourseLinkByLink(shortLink);
             Long companyId = fsCourseLink.getCompanyId();
@@ -367,23 +371,26 @@ public class IpadSendServer {
             //从缓存取出docId;account
             String docIdKey=FEISHU_DOC_ID + externalId+ "_" + videoId;
             String feiShuDocId = redisCache.getCacheObject(docIdKey);
+            //根据初始链接组装真实链接
+            String completeFeiShuLinkUrl = replaceShortLinkInUrl(initUrl, feiShuDocId);
             if (StringUtils.isBlank(feiShuDocId)) {
-                //调用飞书API创建docId
+                //调用飞书API直接获取完整飞书链接
                 String feishuRegisterLink = feiShuService.getFeishuRegisterLink(videoId, companyId, courseId, companyUserId, shortLink);
                 content.setLinkUrl(feishuRegisterLink);
-                String docId = extractLastPathSegment(initUrl);
-                //缓存docId
-                redisCache.setCacheObject(docIdKey, docId);
+                //更新qwSopLogs
+                qwSopLogsService.updateLinkUrlInContentJson(qwSopLogs, completeFeiShuLinkUrl);
                 return content;
             }
+
             String clientKey = FEISHU_CLIENT+feiShuDocId;
             String accountStr = redisCache.getCacheObject(clientKey);
             FeishuAccount account = JSONUtil.toBean(accountStr, FeishuAccount.class);
 
             //如果缓存中的docId为空,则从feishu接口创建新的docId
             Client client = buildClient(account);
-            //根据初始链接组装真实链接
-            String completeFeiShuLinkUrl = replaceShortLinkInUrl(initUrl, feiShuDocId);
+
+            //更新qwSopLogs
+            qwSopLogsService.updateLinkUrlInContentJson(qwSopLogs, completeFeiShuLinkUrl);
             content.setLinkUrl(completeFeiShuLinkUrl);
             String authUrl = buildAuthLink(companyId, companyUserId, courseId, videoId, shortLink);
             // ============ 异步调用飞书API完善文档内容与文档权限 ============
@@ -396,9 +403,8 @@ public class IpadSendServer {
             return content;
         }catch (Exception e){
             log.error("ID:{}-完善飞书注册链接异常:{}", vo.getId(), e.getMessage());
-            throw new BaseException("完善飞书注册链接异常");
         }
-
+        return content;
     }
 
     //构造发送的飞书授权链接
@@ -429,11 +435,6 @@ public class IpadSendServer {
         return JSONUtil.toBean(json, CourseConfig.class);
     }
 
-    private void disablePersonalAccount(FeishuAccount account, String errorMsg) {
-        feishuAccountMapper.updateStatusAndErrorMsg(account.getId(), 0, errorMsg);
-        clearCompanyUserCache(account.getCompanyId(), account.getCompanyUserId());
-    }
-
     private void recordLinkError(Long videoId, Long companyId, Long courseId,
                                  Long companyUserId, String link, String errorInfo, Integer type) {
         FeishuLinkError error = new FeishuLinkError();
@@ -728,7 +729,7 @@ public class IpadSendServer {
                     break;
                 case "3":
                     // 链接
-                    sendLink(vo, content, externalUserId);
+                    sendLink(vo, content, qwSopLogs,externalUserId);
                     break;
                 case "4":
                 case "10":
@@ -820,7 +821,7 @@ public class IpadSendServer {
                     break;
                 case "18":
                     // 链接
-                    sendLink(vo, content,externalUserId);
+                    sendLink(vo, content,qwSopLogs,externalUserId);
                     break;
                 case "21":
                     content.setSendStatus(0);

+ 15 - 1
fs-service/src/main/java/com/fs/feishu/service/FeiShuService.java

@@ -55,6 +55,10 @@ public class FeiShuService {
 
     private static final String FEISHU_COMPANY_USER_KEY = "feishu:account_company_user:";
 
+    private static final String FEISHU_DOC_ID = "fei_shu_doc_id:";
+
+    private static final String FEISHU_CLIENT = "fei_shu_client:";
+
     // ==================== 获取销售个人账号(带缓存) ====================
 
     public List<FeishuAccount> getFeishuAccountCompanyUser(Long companyId, Long companyUserId) {
@@ -116,7 +120,6 @@ public class FeiShuService {
         if (userCourseVideo == null) {
             throw new CustomException("视频不存在: " + videoId);
         }
-
         // 1. 尝试销售个人账号创建文档
         List<FeishuAccount> personalAccounts = getFeishuAccountCompanyUser(companyId, companyUserId);
         if (!personalAccounts.isEmpty()) {
@@ -128,6 +131,17 @@ public class FeiShuService {
                     String authUrl = buildAuthLink(companyId, companyUserId, courseId, videoId, shortLink);
                     docApiService.createTextLinkBlock(client, docId, authUrl);
                     docApiService.changeDocumentPermissions(client, docId);
+                    if (StringUtils.isNotBlank(shortLink)){
+                        FsCourseLink fsCourseLink = courseLinkMapper.selectFsCourseLinkByLink(shortLink);
+                        //有视频短链+外部联系人id,需要缓存docId和account
+                        if (fsCourseLink.getQwExternalId()!=null){
+                            String docIdKey=FEISHU_DOC_ID + fsCourseLink.getQwExternalId()+ "_" + videoId;
+                            redisCache.setCacheObject(docIdKey, docId);
+                            String accountKey = FEISHU_CLIENT+docId;
+                            redisCache.setCacheObject(accountKey, account);
+                        }
+
+                    }
                     return "https://www.feishu.cn/docx/" + docId;
                 } catch (CustomException e) {
                     Integer code = e.getCode();

+ 2 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopLogsService.java

@@ -132,4 +132,6 @@ public interface IQwSopLogsService extends IService<QwSopLogs>
 
 
     void updateBatch(List<QwSopLogs> collect);
+
+    void updateLinkUrlInContentJson(QwSopLogs logs, String newLinkUrl);
 }

+ 73 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java

@@ -27,6 +27,7 @@ import com.fs.qw.param.SopMsgParam;
 import com.fs.qw.result.QwExternalContactByQwResult;
 import com.fs.qw.service.impl.AsyncSopTestService;
 import com.fs.qw.service.impl.QwExternalContactServiceImpl;
+import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qw.vo.QwSopTempSetting;
 import com.fs.qwApi.Result.QwAddMsgTemplateResult;
 import com.fs.qwApi.Result.QwGroupmsgSendResult;
@@ -47,12 +48,14 @@ import com.fs.sop.vo.QwSopLogsDoSendListTVO;
 import com.fs.sop.vo.QwSopLogsListCVO;
 import com.fs.system.service.ISysConfigService;
 import com.fs.voice.utils.StringUtil;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
 import java.time.ZoneId;
@@ -70,6 +73,7 @@ import java.util.stream.Collectors;
  * @author fs
  * @date 2024-08-05
  */
+@Slf4j
 @Service
 public class QwSopLogsServiceImpl extends ServiceImpl<QwSopLogsMapper, QwSopLogs> implements IQwSopLogsService
 {
@@ -2159,4 +2163,73 @@ public class QwSopLogsServiceImpl extends ServiceImpl<QwSopLogsMapper, QwSopLogs
     }
 
 
+    /**
+     * 更新指定 SOP 日志记录中第一个链接类型的 linkUrl
+     * 只记录错误日志,不抛出异常
+     *
+     * @param logs        QwSopLogs 对象(必须包含 id 和 contentJson)
+     * @param newLinkUrl  新的完整链接
+     */
+    @Transactional
+    public void updateLinkUrlInContentJson(QwSopLogs logs, String newLinkUrl) {
+        // 1. 入参校验
+        if (logs == null) {
+            log.error("updateLinkUrlInContentJson 失败:logs 对象为空");
+            return;
+        }
+        if (StringUtils.isBlank(newLinkUrl)) {
+            log.error("updateLinkUrlInContentJson 失败:newLinkUrl 为空,logsId={}", logs.getId());
+            return;
+        }
+
+        String contentJson = logs.getContentJson();
+        if (StringUtils.isBlank(contentJson)) {
+            log.error("content_json 为空,无法更新,logsId={}", logs.getId());
+            return;
+        }
+
+        // 2. 解析为对象
+        QwSopCourseFinishTempSetting settingObj;
+        try {
+            settingObj = JSONUtil.toBean(contentJson, QwSopCourseFinishTempSetting.class);
+        } catch (Exception e) {
+            log.error("解析 content_json 失败,logsId={}, error={}", logs.getId(), e.getMessage(), e);
+            return;
+        }
+
+        // 3. 遍历 setting 列表,找到第一个有 linkUrl 的项进行更新
+        boolean updated = false;
+        if (settingObj.getSetting() != null) {
+            for (QwSopCourseFinishTempSetting.Setting setting : settingObj.getSetting()) {
+                if (StringUtils.isNotBlank(setting.getLinkUrl())) {
+                    setting.setLinkUrl(newLinkUrl);
+                    updated = true;
+                    break; // 只更新第一个
+                }
+            }
+        }
+
+        if (!updated) {
+            log.warn("未找到可更新的 linkUrl 字段,logsId={}", logs.getId());
+            return;
+        }
+
+        // 4. 序列化回 JSON
+        String newContentJson = JSONUtil.toJsonStr(settingObj);
+        logs.setContentJson(newContentJson);
+
+        // 5. 更新数据库
+        try {
+            int rows = qwSopLogsMapper.updateQwSopLogs(logs);
+            if (rows != 1) {
+                log.error("更新 content_json 失败,影响行数={},logsId={}", rows, logs.getId());
+            } else {
+                log.info("成功更新 linkUrl,logsId={}", logs.getId());
+            }
+        } catch (Exception e) {
+            log.error("更新 content_json 时发生数据库异常,logsId={}, error={}", logs.getId(), e.getMessage(), e);
+        }
+    }
+
+
 }