xw 2 дней назад
Родитель
Сommit
2c5039fa08

+ 98 - 7
fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java

@@ -1,21 +1,25 @@
 package com.fs.qw.controller;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
-import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.fs.common.core.domain.R;
-import com.fs.common.exception.ServiceException;
-import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.qw.domain.QwContactWay;
 import com.fs.qw.param.QwExternalContactParam;
 import com.fs.qw.param.QwTagSearchParam;
 import com.fs.qw.param.ResignedTransferParam;
 import com.fs.qw.param.TransferParam;
+import com.fs.qw.service.IQwContactWayService;
 import com.fs.qw.service.IQwExternalContactInfoService;
-import com.fs.qw.service.IQwExternalContactInfoService;
+import com.fs.qw.service.IQwGroupChatUserService;
 import com.fs.qw.service.IQwTagService;
+import com.fs.course.service.IFsUserCompanyBindService;
+import com.fs.qw.param.UserWatchLogParam;
+import com.fs.course.vo.UserWatchLogListVo;
 import com.fs.qw.vo.QwExternalContactUnionIdExportVO;
 import com.fs.qw.vo.QwExternalContactVO;
 import com.google.gson.Gson;
@@ -31,6 +35,7 @@ import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -57,6 +62,15 @@ public class QwExternalContactController extends BaseController
     @Autowired
     private IQwExternalContactInfoService qwExternalContactInfoService;
 
+    @Autowired
+    private IQwContactWayService qwContactWayService;
+
+    @Autowired
+    private IQwGroupChatUserService qwGroupChatUserService;
+
+    @Autowired
+    private IFsUserCompanyBindService fsUserCompanyBindService;
+
     QwExternalContactController(IQwExternalContactService qwExternalContactService,IQwTagService iQwTagService){
         this.qwExternalContactService=qwExternalContactService;
         this.iQwTagService=iQwTagService;
@@ -70,11 +84,32 @@ public class QwExternalContactController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(QwExternalContactParam qwExternalContact)
     {
+        if (qwExternalContact.getFsUserId() == null
+                && qwExternalContact.getExtId() == null
+                && qwExternalContact.getId() == null
+                && StringUtils.isEmpty(qwExternalContact.getExternalUserId())) {
+            return getDataTable(new ArrayList<>());
+        }
+
+        QwContactWay qwContactWay = new QwContactWay();
+        if (qwExternalContact.getCompanyId() != null) {
+            qwContactWay.setCompanyId(qwExternalContact.getCompanyId());
+        }
+        List<QwContactWay> wayList = qwContactWayService.selectQwContactWayList(qwContactWay);
+
         startPage();
-        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVONewSys(qwExternalContact);
-        list.forEach(item->{
+        if (StringUtils.isNotEmpty(qwExternalContact.getStatuses())) {
+            String[] split = qwExternalContact.getStatuses().split(",");
+            qwExternalContact.setStatusCondition(split);
+        }
+        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+        list.forEach(item -> {
+            if (StringUtils.isNotEmpty(item.getExternalUserId())) {
+                List<String> chatNameList = qwGroupChatUserService.selectChatNameByUserId(item.getExternalUserId());
+                item.setChatNames(chatNameList);
+            }
 
-            if (!Objects.equals(item.getTagIds(), "[]") && item.getTagIds()!=null) {
+            if (!Objects.equals(item.getTagIds(), "[]") && item.getTagIds() != null) {
                 QwTagSearchParam param = new QwTagSearchParam();
                 Gson gson = new Gson();
                 List<String> tagIds = gson.fromJson(
@@ -87,11 +122,67 @@ public class QwExternalContactController extends BaseController
 
                 item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
             }
+
+            if (StringUtils.isNotEmpty(item.getState()) && !wayList.isEmpty()) {
+                item.setState(item.getState() + "-" + getContactWayNameStream(item.getState(), wayList));
+            }
         });
+        if (StringUtils.isNotEmpty(qwExternalContact.getChatName())) {
+            list = list.stream()
+                    .filter(item -> item.getChatNames() != null && !item.getChatNames().isEmpty())
+                    .collect(Collectors.toList());
+        }
 
         return getDataTable(list);
     }
 
+    public String getContactWayNameStream(String configStr, List<QwContactWay> wayList) {
+        if (configStr == null || wayList == null || wayList.isEmpty()) {
+            return null;
+        }
+
+        return wayList.stream()
+                .filter(way -> way.getId() != null &&
+                        way.getId().toString().equals(extractLastValue(configStr)))
+                .map(QwContactWay::getName)
+                .findFirst()
+                .orElse(null);
+    }
+
+    private String extractLastValue(String input) {
+        if (input == null || input.isEmpty()) {
+            return null;
+        }
+
+        int lastColonIndex = input.lastIndexOf(":");
+        if (lastColonIndex == -1) {
+            return input;
+        }
+
+        return input.substring(lastColonIndex + 1);
+    }
+
+    /**
+     * 重粉看课记录查询
+     */
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:list')")
+    @GetMapping("/getWatchLogList")
+    public TableDataInfo getWatchLogList(UserWatchLogParam param) {
+        startPage();
+        List<UserWatchLogListVo> list = fsUserCompanyBindService.getWatchLogList(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * 重粉看课历史 - 综合信息查询(关联销售 + 课程进度)
+     */
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:list')")
+    @GetMapping("/getRepeatCourseHistory")
+    public AjaxResult getRepeatCourseHistory(@RequestParam Long fsUserId,
+                                             @RequestParam(required = false) Long companyId) {
+        return AjaxResult.success(fsUserCompanyBindService.getRepeatCourseHistory(fsUserId, companyId));
+    }
+
     /**
      * 导出企业微信客户列表
      */

+ 60 - 9
fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyBindServiceImpl.java

@@ -15,6 +15,7 @@ import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.course.mapper.FsUserCompanyBindMapper;
 import com.fs.course.mapper.FsUserCourseMapper;
 import com.fs.course.service.IFsUserCompanyBindService;
+import com.fs.course.support.CourseProjectEquivalence;
 import com.fs.course.vo.CourseProgressResultVO;
 import com.fs.course.vo.RelatedSalesResultVO;
 import com.fs.course.vo.RepeatCourseHistoryVO;
@@ -35,7 +36,13 @@ import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * 用户客服关联Service业务层处理
@@ -158,12 +165,10 @@ public class FsUserCompanyBindServiceImpl extends ServiceImpl<FsUserCompanyBindM
                     return false;
                 }
             }
-            if (qwExternalContact.getUserRepeat() == 0) {
-                Integer i = baseMapper.selectCount(new QueryWrapper<FsUserCompanyBind>().eq("fs_user_id", fsUserId));
-                if (i > 1) {
-                    qwExternalContact.setUserRepeat(1);
-                    qwExternalContactMapper.updateById(qwExternalContact);
-                }
+            if (qwExternalContact.getUserRepeat() == 0 && project != 0
+                    && isRepeatWatchByProject(fsUserId, project, qwUserId)) {
+                qwExternalContact.setUserRepeat(1);
+                qwExternalContactMapper.updateById(qwExternalContact);
             }
             // 当前登录账号名称
             FsUserCompanyBind one = baseMapper.selectOne(new QueryWrapper<FsUserCompanyBind>()
@@ -283,15 +288,15 @@ public class FsUserCompanyBindServiceImpl extends ServiceImpl<FsUserCompanyBindM
             vo.setName(contact.getName());
             vo.setAvatar(contact.getAvatar());
             vo.setRemark(contact.getRemark());
-            vo.setUserRepeat(contact.getUserRepeat());
         }
+        vo.setUserRepeat(isUserRepeatByProject(fsUserId) ? 1 : 0);
 
         // 2. 查询关联销售(单条SQL + GROUP BY 优化)
         List<RelatedSalesResultVO> salesResults = baseMapper.getRelatedSalesByFsUserId(fsUserId);
         List<RepeatCourseHistoryVO.RelatedSalesVO> salesList = new ArrayList<>();
         for (RelatedSalesResultVO r : salesResults) {
             RepeatCourseHistoryVO.RelatedSalesVO s = new RepeatCourseHistoryVO.RelatedSalesVO();
-            boolean hasPermission = r.getCorpId() == null || permittedCorpIds.contains(r.getCorpId());
+            boolean hasPermission = hasCorpPermission(companyId, permittedCorpIds, r.getCorpId());
             s.setHasPermission(hasPermission);
             if (hasPermission) {
                 s.setQwUserName(r.getQwUserName());
@@ -322,7 +327,7 @@ public class FsUserCompanyBindServiceImpl extends ServiceImpl<FsUserCompanyBindM
             cp.setLatestSection(c.getLatestSection());
             cp.setLatestTime(c.getLatestTime());
             cp.setFinished(total > 0 && watched >= total);
-            boolean hasPermission = c.getCorpId() == null || permittedCorpIds.contains(c.getCorpId());
+            boolean hasPermission = hasCorpPermission(companyId, permittedCorpIds, c.getCorpId());
             cp.setHasPermission(hasPermission);
             if (hasPermission) {
                 cp.setQwUserName(c.getQwUserName());
@@ -353,4 +358,50 @@ public class FsUserCompanyBindServiceImpl extends ServiceImpl<FsUserCompanyBindM
         }
         return corpIds;
     }
+
+    private boolean hasCorpPermission(Long companyId, List<String> permittedCorpIds, String corpId) {
+        if (companyId == null) {
+            return true;
+        }
+        return corpId == null || permittedCorpIds.contains(corpId);
+    }
+
+    /**
+     * 按项目判重:同一项目(含等价项目)下存在至少两个不同企微销售则视为看课重粉。
+     */
+    private boolean isUserRepeatByProject(Long fsUserId) {
+        List<FsUserCompanyBind> binds = baseMapper.selectList(
+                new QueryWrapper<FsUserCompanyBind>()
+                        .eq("fs_user_id", fsUserId)
+                        .isNotNull("project_id")
+                        .ne("project_id", 0)
+                        .isNotNull("qw_user_id"));
+        if (binds.isEmpty()) {
+            return false;
+        }
+        Map<String, Set<Long>> groupToQwUsers = new HashMap<>();
+        for (FsUserCompanyBind bind : binds) {
+            String groupKey = CourseProjectEquivalence.equivalentProjectIds(bind.getProjectId())
+                    .stream().sorted().map(String::valueOf).collect(Collectors.joining(","));
+            groupToQwUsers.computeIfAbsent(groupKey, k -> new HashSet<>()).add(bind.getQwUserId());
+        }
+        return groupToQwUsers.values().stream().anyMatch(qwUserIds -> qwUserIds.size() >= 2);
+    }
+
+    private boolean isRepeatWatchByProject(Long fsUserId, Long projectId, Long currentQwUserId) {
+        List<Long> equivalentProjectIds = CourseProjectEquivalence.equivalentProjectIds(projectId);
+        List<FsUserCompanyBind> binds = baseMapper.selectList(
+                new QueryWrapper<FsUserCompanyBind>()
+                        .eq("fs_user_id", fsUserId)
+                        .in("project_id", equivalentProjectIds)
+                        .isNotNull("qw_user_id"));
+        Set<Long> qwUserIds = binds.stream()
+                .map(FsUserCompanyBind::getQwUserId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (currentQwUserId != null) {
+            qwUserIds.add(currentQwUserId);
+        }
+        return qwUserIds.size() >= 2;
+    }
 }

+ 2 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java

@@ -296,6 +296,8 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
             "            <if test=\"isBind == 'noBind' \"> and ec.customer_id is null </if> \n" +
             "            <if test=\"isBindMini == 'isBindMini' \"> and ec.fs_user_id is not null </if> \n" +
             "            <if test=\"isBindMini == 'noBindMini' \"> and ec.fs_user_id is null </if> \n" +
+            "            <if test=\"extId != null\"> and ec.id = #{extId}</if>\n" +
+            "            <if test=\"fsUserId != null\"> and ec.fs_user_id = #{fsUserId}</if>\n" +
             "            <if test=\"lossTime != null \"> and DATE(ec.loss_time) = DATE(#{lossTime})</if>\n" +
             "            <if test=\"createTime != null \">and DATE(ec.create_time) = DATE(#{createTime})</if>\n" +
             "            <if test=\"delTime != null \"> and DATE(ec.del_time) = DATE(#{delTime})</if>\n" +