|
@@ -72,6 +72,7 @@ import java.time.*;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.*;
|
|
import java.util.*;
|
|
import java.util.concurrent.*;
|
|
import java.util.concurrent.*;
|
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
import java.util.stream.Stream;
|
|
@@ -1189,142 +1190,593 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public R addUserTag(QwExternalContactAddTagParam param) throws JSONException {
|
|
public R addUserTag(QwExternalContactAddTagParam param) throws JSONException {
|
|
- int err = 0;
|
|
|
|
- int suc = 0;
|
|
|
|
- // 获取当前日期(只包含年月日)
|
|
|
|
|
|
+ // 获取当前日期和时间
|
|
LocalDate currentDate = LocalDate.now();
|
|
LocalDate currentDate = LocalDate.now();
|
|
- // 获取当前系统时间 (HH:mm)
|
|
|
|
LocalTime localTime = LocalTime.now();
|
|
LocalTime localTime = LocalTime.now();
|
|
|
|
|
|
- List<Long> userIds = param.getUserIds();
|
|
|
|
- for (Long userId : userIds) {
|
|
|
|
|
|
+ // 使用线程安全的计数器
|
|
|
|
+ AtomicInteger suc = new AtomicInteger(0);
|
|
|
|
+
|
|
|
|
+ List<String> failList = new CopyOnWriteArrayList<>(); // 记录失败客户的名字
|
|
|
|
|
|
- QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalContactById(userId);
|
|
|
|
- QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
|
|
|
|
- qwEditUserTagParam.setAdd_tag(param.getTagIds());
|
|
|
|
- qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
|
|
|
|
- qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
|
|
|
|
|
|
+ // 创建线程池
|
|
|
|
+ int threadCount = Math.min(8, Runtime.getRuntime().availableProcessors() * 2);
|
|
|
|
+ ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ // 使用线程安全的List来收集需要批量更新的数据
|
|
|
|
+ List<QwExternalContact> batchUpdateList = Collections.synchronizedList(new ArrayList<>());
|
|
|
|
|
|
|
|
+ // 存储Future对象以便检查所有任务完成情况
|
|
|
|
+ List<Future<?>> futures = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 1. 批量查询所有用户数据
|
|
|
|
+ List<QwExternalContact> contacts;
|
|
try {
|
|
try {
|
|
|
|
+ contacts = qwExternalContactMapper.selectQwExternalContactByIds(param.getUserIds());
|
|
|
|
+ if (contacts == null || contacts.isEmpty()) {
|
|
|
|
+ return R.error("成功:0,失败:" + param.getUserIds().size());
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ return R.error("批量查询用户数据失败:"+e.getMessage());
|
|
|
|
+ }
|
|
|
|
|
|
- QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());
|
|
|
|
- if (qwResult.getErrcode() == 0) {
|
|
|
|
|
|
+ // 直接遍历contacts而不是userIds
|
|
|
|
+ for (QwExternalContact qwExternalContact : contacts) {
|
|
|
|
+ futures.add(executor.submit(() -> {
|
|
|
|
+ try {
|
|
|
|
+ QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
|
|
|
|
+ qwEditUserTagParam.setAdd_tag(param.getTagIds());
|
|
|
|
+ qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
|
|
|
|
+ qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
|
|
|
|
+
|
|
|
|
+ QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());
|
|
|
|
+ if (qwResult.getErrcode() == 0) {
|
|
|
|
+ // 处理标签
|
|
|
|
+ String tagIds = qwExternalContact.getTagIds();
|
|
|
|
+ Set<String> uniqueIds = new HashSet<>();
|
|
|
|
+
|
|
|
|
+ if (tagIds != null && !tagIds.isEmpty()) {
|
|
|
|
+ List<String> parsedTags = JSON.parseArray(tagIds, String.class);
|
|
|
|
+ if (parsedTags != null && !parsedTags.isEmpty()) {
|
|
|
|
+ uniqueIds.addAll(parsedTags);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- //客户本身的标签集合+打的标签
|
|
|
|
- QwExternalContact qwExternal = new QwExternalContact();
|
|
|
|
- String tagIds = qwExternalContact.getTagIds();
|
|
|
|
|
|
+ if (param.getTagIds() != null && !param.getTagIds().isEmpty()) {
|
|
|
|
+ uniqueIds.addAll(param.getTagIds());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ QwExternalContact qwExternal = new QwExternalContact();
|
|
|
|
+ qwExternal.setTagIds(JSON.toJSONString(uniqueIds));
|
|
|
|
+ qwExternal.setId(qwExternalContact.getId());
|
|
|
|
|
|
- // 将标签字符串解析为 List //客户总标签
|
|
|
|
- List<String> tagIdsList = new ArrayList<>();
|
|
|
|
|
|
+ List<String> tagIdsList = new ArrayList<>();
|
|
|
|
+ if (qwExternal.getTagIds() != null && !qwExternal.getTagIds().isEmpty()) {
|
|
|
|
+ tagIdsList = JSON.parseArray(qwExternal.getTagIds(), String.class);
|
|
|
|
+ }
|
|
|
|
|
|
- Set<String> uniqueIds = new HashSet<>();
|
|
|
|
- if (tagIds != null && !tagIds.isEmpty()) {
|
|
|
|
- List<String> parsedTags = JSON.parseArray(tagIds, String.class);
|
|
|
|
- if (parsedTags != null && !parsedTags.isEmpty()) {
|
|
|
|
- uniqueIds.addAll(parsedTags);
|
|
|
|
|
|
+ logger.info("客户添加标签addUserTag:" + qwExternalContact.getName() +
|
|
|
|
+ "|公司" + qwExternalContact.getCorpId() +
|
|
|
|
+ "|员工" + qwExternalContact.getUserId() +
|
|
|
|
+ "|总标签" + tagIdsList);
|
|
|
|
+
|
|
|
|
+ // 插件sop处理
|
|
|
|
+ processTagsAll(qwExternalContact, qwExternalContact.getCorpId(),
|
|
|
|
+ tagIdsList, currentDate, localTime);
|
|
|
|
+
|
|
|
|
+ // 添加到批量更新列表
|
|
|
|
+ batchUpdateList.add(qwExternal);
|
|
|
|
+ suc.incrementAndGet();
|
|
|
|
+ } else {
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + getErrorMsg(qwResult.getErrcode()) + ")\n");
|
|
}
|
|
}
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("客户添加标签失败,userId: " + qwExternalContact.getId() +
|
|
|
|
+ ", externalUserId: " + qwExternalContact.getExternalUserId() +
|
|
|
|
+ ", 错误信息: " + e.getMessage());
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + e.getMessage() + ")\n");
|
|
}
|
|
}
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
|
|
- // 将 param 中的标签 ID 加入集合
|
|
|
|
- if (param.getTagIds() != null && !param.getTagIds().isEmpty()) {
|
|
|
|
- uniqueIds.addAll(param.getTagIds());
|
|
|
|
|
|
+ // 等待所有任务完成
|
|
|
|
+ for (Future<?> future : futures) {
|
|
|
|
+ try {
|
|
|
|
+ future.get();
|
|
|
|
+ } catch (InterruptedException | ExecutionException e) {
|
|
|
|
+ logger.error("任务执行异常: " + e.getMessage());
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 批量更新数据库
|
|
|
|
+ if (!batchUpdateList.isEmpty()) {
|
|
|
|
+ try {
|
|
|
|
+ // 分批处理,避免单次批量过大
|
|
|
|
+ int batchSize = 500; // 根据数据库性能调整
|
|
|
|
+ for (int i = 0; i < batchUpdateList.size(); i += batchSize) {
|
|
|
|
+ int end = Math.min(i + batchSize, batchUpdateList.size());
|
|
|
|
+ List<QwExternalContact> subList = batchUpdateList.subList(i, end);
|
|
|
|
+ qwExternalContactMapper.batchUpdateQwExternalContactByTags(subList);
|
|
}
|
|
}
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("批量更新失败: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- // 将唯一标签集合设置回 qwExternal
|
|
|
|
- qwExternal.setTagIds(JSON.toJSONString(uniqueIds));
|
|
|
|
|
|
+ // 关闭线程池
|
|
|
|
+ executor.shutdown();
|
|
|
|
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ failList.add("处理过程中发生异常:"+e.getMessage());
|
|
|
|
+ }finally {
|
|
|
|
+ // 7. 确保线程池关闭
|
|
|
|
+ try {
|
|
|
|
+ // 先尝试正常关闭
|
|
|
|
+ executor.shutdown();
|
|
|
|
+ if (!executor.awaitTermination(15, TimeUnit.SECONDS)) {
|
|
|
|
+ // 超时后强制关闭
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ logger.warn("线程池强制关闭");
|
|
|
|
+ }
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- if (qwExternal.getTagIds() != null && !qwExternal.getTagIds().isEmpty()) {
|
|
|
|
- tagIdsList = JSON.parseArray(qwExternal.getTagIds(), String.class);
|
|
|
|
- }
|
|
|
|
|
|
+ return R.ok("成功:" + suc.get() + ",失败:" + failList);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private String getErrorMsg(Integer code){
|
|
|
|
+
|
|
|
|
+ String msg="";
|
|
|
|
+ switch (code){
|
|
|
|
+ case 40003:
|
|
|
|
+ msg="无效的UserID(员工账号)";
|
|
|
|
+ break;
|
|
|
|
+ case 40096:
|
|
|
|
+ msg="不合法的外部联系人userid";
|
|
|
|
+ break;
|
|
|
|
+ case 45033:
|
|
|
|
+ msg="接口并发调用超过限制(**调用过于频繁请稍后再试**)";
|
|
|
|
+ break;
|
|
|
|
+ case 45035:
|
|
|
|
+ msg="当前客户有其他修改操作,请稍后重试(**比如其他地方修改客户信息**)";
|
|
|
|
+ break;
|
|
|
|
+ case 60020:
|
|
|
|
+ msg="不安全的访问IP";
|
|
|
|
+ break;
|
|
|
|
+ case 84061:
|
|
|
|
+ msg="不存在外部联系人的关系(**客户【不存在】于员工的好友列表中**)";
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ msg=code.toString();
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public R addTagByWatch(QwExtContactAddTagByWatchParam param) throws org.codehaus.jettison.json.JSONException {
|
|
|
|
|
|
- qwExternal.setId(userId);
|
|
|
|
|
|
|
|
- logger.info("客户添加标签addUserTag:"+qwExternalContact.getName()+"|公司"+qwExternalContact.getCorpId()+"|员工"+qwExternalContact.getUserId()+"|总标签"+tagIdsList);
|
|
|
|
|
|
|
|
- //插件sop
|
|
|
|
- processTagsAll(qwExternalContact,qwExternalContact.getCorpId(),tagIdsList,currentDate,localTime);
|
|
|
|
|
|
+ // 获取当前日期和时间
|
|
|
|
+ LocalDate currentDate = LocalDate.now();
|
|
|
|
+ LocalTime localTime = LocalTime.now();
|
|
|
|
+
|
|
|
|
+ // 使用线程安全的计数器
|
|
|
|
+ AtomicInteger suc = new AtomicInteger(0);
|
|
|
|
|
|
- //新客对话
|
|
|
|
-// processTagsAllByAiChat(qwExternalContact,param.getCorpId(),tagIdsList);
|
|
|
|
|
|
+ List<String> failList = new CopyOnWriteArrayList<>(); // 记录失败客户的名字
|
|
|
|
|
|
- suc++;
|
|
|
|
- qwExternalContactMapper.updateQwExternalContact(qwExternal);
|
|
|
|
|
|
+ // 创建线程池
|
|
|
|
+ int threadCount = Math.min(8, Runtime.getRuntime().availableProcessors() * 2);
|
|
|
|
+ ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ // 使用线程安全的List来收集需要批量更新的数据
|
|
|
|
+ List<QwExternalContact> batchUpdateList = Collections.synchronizedList(new ArrayList<>());
|
|
|
|
+
|
|
|
|
+ // 存储Future对象以便检查所有任务完成情况
|
|
|
|
+ List<Future<?>> futures = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 1. 批量查询所有用户数据
|
|
|
|
+ List<QwExternalContact> contacts;
|
|
|
|
+ try {
|
|
|
|
+ contacts = fsCourseWatchLogMapper.selectQwWatchLogFomExtContact(param.getLogIds());
|
|
|
|
+ if (contacts == null || contacts.isEmpty()) {
|
|
|
|
+ return R.error("成功:0,失败:" + param.getLogIds().size());
|
|
}
|
|
}
|
|
- else {
|
|
|
|
- err++;
|
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ return R.error("批量查询用户数据失败:"+e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 直接遍历contacts而不是userIds
|
|
|
|
+ for (QwExternalContact qwExternalContact : contacts) {
|
|
|
|
+ futures.add(executor.submit(() -> {
|
|
|
|
+ try {
|
|
|
|
+ QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
|
|
|
|
+ qwEditUserTagParam.setAdd_tag(param.getTagIds());
|
|
|
|
+ qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
|
|
|
|
+ qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
|
|
|
|
+
|
|
|
|
+ QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, qwExternalContact.getCorpId());
|
|
|
|
+ if (qwResult.getErrcode() == 0) {
|
|
|
|
+ // 处理标签
|
|
|
|
+ String tagIds = qwExternalContact.getTagIds();
|
|
|
|
+ Set<String> uniqueIds = new HashSet<>();
|
|
|
|
+
|
|
|
|
+ if (tagIds != null && !tagIds.isEmpty()) {
|
|
|
|
+ List<String> parsedTags = JSON.parseArray(tagIds, String.class);
|
|
|
|
+ if (parsedTags != null && !parsedTags.isEmpty()) {
|
|
|
|
+ uniqueIds.addAll(parsedTags);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (param.getTagIds() != null && !param.getTagIds().isEmpty()) {
|
|
|
|
+ uniqueIds.addAll(param.getTagIds());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ QwExternalContact qwExternal = new QwExternalContact();
|
|
|
|
+ qwExternal.setTagIds(JSON.toJSONString(uniqueIds));
|
|
|
|
+ qwExternal.setId(qwExternalContact.getId());
|
|
|
|
+
|
|
|
|
+ List<String> tagIdsList = new ArrayList<>();
|
|
|
|
+ if (qwExternal.getTagIds() != null && !qwExternal.getTagIds().isEmpty()) {
|
|
|
|
+ tagIdsList = JSON.parseArray(qwExternal.getTagIds(), String.class);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ logger.info("看课处客户添加标签addUserTag:" + qwExternalContact.getName() +
|
|
|
|
+ "|公司" + qwExternalContact.getCorpId() +
|
|
|
|
+ "|员工" + qwExternalContact.getUserId() +
|
|
|
|
+ "|总标签" + tagIdsList);
|
|
|
|
+
|
|
|
|
+ // 插件sop处理
|
|
|
|
+ processTagsAll(qwExternalContact, qwExternalContact.getCorpId(),
|
|
|
|
+ tagIdsList, currentDate, localTime);
|
|
|
|
+
|
|
|
|
+ // 添加到批量更新列表
|
|
|
|
+ batchUpdateList.add(qwExternal);
|
|
|
|
+ suc.incrementAndGet();
|
|
|
|
+ } else {
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + getErrorMsg(qwResult.getErrcode()) + ")\n");
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("看课处客户添加标签失败,userId: " + qwExternalContact.getId() +
|
|
|
|
+ ", externalUserId: " + qwExternalContact.getExternalUserId() +
|
|
|
|
+ ", 错误信息: " + e.getMessage());
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + e.getMessage() + ")\n");
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 等待所有任务完成
|
|
|
|
+ for (Future<?> future : futures) {
|
|
|
|
+ try {
|
|
|
|
+ future.get();
|
|
|
|
+ } catch (InterruptedException | ExecutionException e) {
|
|
|
|
+ logger.error("任务执行异常: " + e.getMessage());
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 批量更新数据库
|
|
|
|
+ if (!batchUpdateList.isEmpty()) {
|
|
|
|
+ try {
|
|
|
|
+ // 分批处理,避免单次批量过大
|
|
|
|
+ int batchSize = 500; // 根据数据库性能调整
|
|
|
|
+ for (int i = 0; i < batchUpdateList.size(); i += batchSize) {
|
|
|
|
+ int end = Math.min(i + batchSize, batchUpdateList.size());
|
|
|
|
+ List<QwExternalContact> subList = batchUpdateList.subList(i, end);
|
|
|
|
+ qwExternalContactMapper.batchUpdateQwExternalContactByTags(subList);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("批量更新失败: " + e.getMessage());
|
|
}
|
|
}
|
|
- }catch (Exception e){
|
|
|
|
- logger.error("客户添加标签失败:"+qwEditUserTagParam+e.getMessage());
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 关闭线程池
|
|
|
|
+ executor.shutdown();
|
|
|
|
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ failList.add("处理过程中发生异常:"+e.getMessage());
|
|
|
|
+ }finally {
|
|
|
|
+ // 7. 确保线程池关闭
|
|
|
|
+ try {
|
|
|
|
+ // 先尝试正常关闭
|
|
|
|
+ executor.shutdown();
|
|
|
|
+ if (!executor.awaitTermination(15, TimeUnit.SECONDS)) {
|
|
|
|
+ // 超时后强制关闭
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ logger.warn("线程池强制关闭");
|
|
|
|
+ }
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- return R.ok("成功:" + suc + ",失败:" + err);
|
|
|
|
|
|
+ return R.ok("成功:" + suc.get() + ",失败:" + failList);
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public R delUserTag(QwExternalContactAddTagParam param) {
|
|
public R delUserTag(QwExternalContactAddTagParam param) {
|
|
-
|
|
|
|
- // 获取当前日期(只包含年月日)
|
|
|
|
|
|
+ // 获取当前日期和时间
|
|
LocalDate currentDate = LocalDate.now();
|
|
LocalDate currentDate = LocalDate.now();
|
|
- // 获取当前系统时间 (HH:mm)
|
|
|
|
LocalTime localTime = LocalTime.now();
|
|
LocalTime localTime = LocalTime.now();
|
|
|
|
|
|
- int err = 0;
|
|
|
|
- int suc = 0;
|
|
|
|
- List<Long> userIds = param.getUserIds();
|
|
|
|
- for (Long userId : userIds) {
|
|
|
|
|
|
+ // 使用线程安全的计数器
|
|
|
|
+ AtomicInteger suc = new AtomicInteger(0);
|
|
|
|
+
|
|
|
|
+ List<String> failList = new CopyOnWriteArrayList<>(); // 记录失败客户的名字
|
|
|
|
|
|
- QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalContactById(userId);
|
|
|
|
|
|
+ // 创建线程池
|
|
|
|
+ int threadCount = Math.min(8, Runtime.getRuntime().availableProcessors() * 2);
|
|
|
|
+ ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
|
|
|
|
|
- QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
|
|
|
|
- qwEditUserTagParam.setRemove_tag(param.getTagIds());
|
|
|
|
- qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
|
|
|
|
- qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
|
|
|
|
|
|
|
|
|
|
+ try {
|
|
|
|
+ // 使用线程安全的List来收集需要批量更新的数据
|
|
|
|
+ List<QwExternalContact> batchUpdateList = Collections.synchronizedList(new ArrayList<>());
|
|
|
|
+
|
|
|
|
+ // 存储Future对象以便检查所有任务完成情况
|
|
|
|
+ List<Future<?>> futures = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 1. 批量查询所有用户数据
|
|
|
|
+ List<QwExternalContact> contacts;
|
|
try {
|
|
try {
|
|
- QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());
|
|
|
|
- if (qwResult.getErrcode() == 0) {
|
|
|
|
-
|
|
|
|
- String tagIds = qwExternalContact.getTagIds();
|
|
|
|
- if (tagIds != null && tagIds != "") {
|
|
|
|
- List<String> ids = JSON.parseArray(tagIds, String.class);
|
|
|
|
- for (String tagId : param.getTagIds()) {
|
|
|
|
- ids.removeIf(str -> str.equals(tagId));
|
|
|
|
|
|
+ contacts = qwExternalContactMapper.selectQwExternalContactByIds(param.getUserIds());
|
|
|
|
+ if (contacts == null || contacts.isEmpty()) {
|
|
|
|
+ return R.error("成功:0,失败:" + param.getUserIds().size());
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ return R.error("批量查询用户数据失败:"+e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 直接遍历contacts而不是userIds
|
|
|
|
+ for (QwExternalContact qwExternalContact : contacts) {
|
|
|
|
+ futures.add(executor.submit(() -> {
|
|
|
|
+ try {
|
|
|
|
+ QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
|
|
|
|
+ qwEditUserTagParam.setRemove_tag(param.getTagIds());
|
|
|
|
+ qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
|
|
|
|
+ qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
|
|
|
|
+
|
|
|
|
+ QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());
|
|
|
|
+ if (qwResult.getErrcode() == 0) {
|
|
|
|
+
|
|
|
|
+ String tagIds = qwExternalContact.getTagIds();
|
|
|
|
+ if (tagIds != null && tagIds != "") {
|
|
|
|
+ List<String> ids = JSON.parseArray(tagIds, String.class);
|
|
|
|
+ for (String tagId : param.getTagIds()) {
|
|
|
|
+ ids.removeIf(str -> str.equals(tagId));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ QwExternalContact qwExternal = new QwExternalContact();
|
|
|
|
+ qwExternal.setId(qwExternalContact.getId());
|
|
|
|
+ qwExternal.setTagIds(JSON.toJSONString(ids));
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ logger.info("客户移除标签delUserTag:"+qwExternalContact.getName()+"|公司"+qwExternalContact.getCorpId()+"|员工"+qwExternalContact.getUserId()+"|总标签"+ids);
|
|
|
|
+
|
|
|
|
+ //检查sop
|
|
|
|
+ processTagsAll(qwExternalContact,param.getCorpId(),ids,currentDate,localTime);
|
|
|
|
+
|
|
|
|
+ // 添加到批量更新列表
|
|
|
|
+ batchUpdateList.add(qwExternal);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ suc.incrementAndGet();
|
|
|
|
+ } else {
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + getErrorMsg(qwResult.getErrcode()) + ")\n");
|
|
}
|
|
}
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("客户移除标签delUserTag失败,userId: " + qwExternalContact.getId() +
|
|
|
|
+ ", externalUserId: " + qwExternalContact.getExternalUserId() +
|
|
|
|
+ ", 错误信息: " + e.getMessage());
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + e.getMessage() + ")\n");
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 等待所有任务完成
|
|
|
|
+ for (Future<?> future : futures) {
|
|
|
|
+ try {
|
|
|
|
+ future.get();
|
|
|
|
+ } catch (InterruptedException | ExecutionException e) {
|
|
|
|
+ logger.error("任务执行异常: " + e.getMessage());
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 批量更新数据库
|
|
|
|
+ if (!batchUpdateList.isEmpty()) {
|
|
|
|
+ try {
|
|
|
|
+ // 分批处理,避免单次批量过大
|
|
|
|
+ int batchSize = 500; // 根据数据库性能调整
|
|
|
|
+ for (int i = 0; i < batchUpdateList.size(); i += batchSize) {
|
|
|
|
+ int end = Math.min(i + batchSize, batchUpdateList.size());
|
|
|
|
+ List<QwExternalContact> subList = batchUpdateList.subList(i, end);
|
|
|
|
+ qwExternalContactMapper.batchUpdateQwExternalContactByTags(subList);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("批量更新失败: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 关闭线程池
|
|
|
|
+ executor.shutdown();
|
|
|
|
+
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ failList.add("处理过程中发生异常:"+e.getMessage());
|
|
|
|
+ }finally {
|
|
|
|
+
|
|
|
|
+ // 7. 确保线程池关闭
|
|
|
|
+ try {
|
|
|
|
+ // 先尝试正常关闭
|
|
|
|
+ executor.shutdown();
|
|
|
|
+ if (!executor.awaitTermination(15, TimeUnit.SECONDS)) {
|
|
|
|
+ // 超时后强制关闭
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ logger.warn("线程池强制关闭");
|
|
|
|
+ }
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ return R.ok("成功:" + suc.get() + ",失败:" + failList);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public R delTagByWatch(QwExtContactAddTagByWatchParam param) {
|
|
|
|
+ // 获取当前日期和时间
|
|
|
|
+ LocalDate currentDate = LocalDate.now();
|
|
|
|
+ LocalTime localTime = LocalTime.now();
|
|
|
|
+
|
|
|
|
+ // 使用线程安全的计数器
|
|
|
|
+ AtomicInteger suc = new AtomicInteger(0);
|
|
|
|
+
|
|
|
|
+ List<String> failList = new CopyOnWriteArrayList<>(); // 记录失败客户的名字
|
|
|
|
+
|
|
|
|
+ // 创建线程池
|
|
|
|
+ int threadCount = Math.min(8, Runtime.getRuntime().availableProcessors() * 2);
|
|
|
|
+ ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
|
|
|
|
|
- QwExternalContact qwExternal = new QwExternalContact();
|
|
|
|
- qwExternal.setId(userId);
|
|
|
|
- qwExternal.setTagIds(JSON.toJSONString(ids));
|
|
|
|
|
|
|
|
- qwExternalContactMapper.updateQwExternalContact(qwExternal);
|
|
|
|
|
|
+ try {
|
|
|
|
+ // 使用线程安全的List来收集需要批量更新的数据
|
|
|
|
+ List<QwExternalContact> batchUpdateList = Collections.synchronizedList(new ArrayList<>());
|
|
|
|
+
|
|
|
|
+ // 存储Future对象以便检查所有任务完成情况
|
|
|
|
+ List<Future<?>> futures = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 1. 批量查询所有用户数据
|
|
|
|
+ List<QwExternalContact> contacts;
|
|
|
|
+ try {
|
|
|
|
+ contacts = fsCourseWatchLogMapper.selectQwWatchLogFomExtContact(param.getLogIds());
|
|
|
|
+ if (contacts == null || contacts.isEmpty()) {
|
|
|
|
+ return R.error("成功:0,失败:" + param.getLogIds().size());
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ return R.error("批量查询用户数据失败:"+e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 直接遍历contacts而不是userIds
|
|
|
|
+ for (QwExternalContact qwExternalContact : contacts) {
|
|
|
|
+ futures.add(executor.submit(() -> {
|
|
|
|
+ try {
|
|
|
|
+ QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
|
|
|
|
+ qwEditUserTagParam.setRemove_tag(param.getTagIds());
|
|
|
|
+ qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
|
|
|
|
+ qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
|
|
|
|
+
|
|
|
|
+ QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, qwExternalContact.getCorpId());
|
|
|
|
+ if (qwResult.getErrcode() == 0) {
|
|
|
|
+
|
|
|
|
+ String tagIds = qwExternalContact.getTagIds();
|
|
|
|
+ if (tagIds != null && tagIds != "") {
|
|
|
|
+ List<String> ids = JSON.parseArray(tagIds, String.class);
|
|
|
|
+ for (String tagId : param.getTagIds()) {
|
|
|
|
+ ids.removeIf(str -> str.equals(tagId));
|
|
|
|
+ }
|
|
|
|
|
|
- logger.info("客户移除标签delUserTag:"+qwExternalContact.getName()+"|公司"+qwExternalContact.getCorpId()+"|员工"+qwExternalContact.getUserId()+"|总标签"+ids);
|
|
|
|
|
|
+ QwExternalContact qwExternal = new QwExternalContact();
|
|
|
|
+ qwExternal.setId(qwExternalContact.getId());
|
|
|
|
+ qwExternal.setTagIds(JSON.toJSONString(ids));
|
|
|
|
|
|
- //检查sop
|
|
|
|
- processTagsAll(qwExternalContact,param.getCorpId(),ids,currentDate,localTime);
|
|
|
|
|
|
|
|
- //新客对话
|
|
|
|
-// processTagsAllByAiChat(qwExternalContact,param.getCorpId(),ids);
|
|
|
|
|
|
+ logger.info("看课处客户移除标签delUserTag:"+qwExternalContact.getName()+"|公司"+qwExternalContact.getCorpId()+"|员工"+qwExternalContact.getUserId()+"|总标签"+ids);
|
|
|
|
+
|
|
|
|
+ //检查sop
|
|
|
|
+ processTagsAll(qwExternalContact,qwExternalContact.getCorpId(),ids,currentDate,localTime);
|
|
|
|
+
|
|
|
|
+ // 添加到批量更新列表
|
|
|
|
+ batchUpdateList.add(qwExternal);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ suc.incrementAndGet();
|
|
|
|
+ } else {
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + getErrorMsg(qwResult.getErrcode()) + ")\n");
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("看课处客户移除标签delUserTag失败,userId: " + qwExternalContact.getId() +
|
|
|
|
+ ", externalUserId: " + qwExternalContact.getExternalUserId() +
|
|
|
|
+ ", 错误信息: " + e.getMessage());
|
|
|
|
+ failList.add("【"+qwExternalContact.getName()+"】" + "原因:(" + e.getMessage() + ")\n");
|
|
}
|
|
}
|
|
- suc++;
|
|
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
|
- err++;
|
|
|
|
|
|
+
|
|
|
|
+ // 等待所有任务完成
|
|
|
|
+ for (Future<?> future : futures) {
|
|
|
|
+ try {
|
|
|
|
+ future.get();
|
|
|
|
+ } catch (InterruptedException | ExecutionException e) {
|
|
|
|
+ logger.error("任务执行异常: " + e.getMessage());
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- }catch (Exception e){
|
|
|
|
- logger.error("移除标签失败:"+qwEditUserTagParam+e.getMessage());
|
|
|
|
|
|
+ // 批量更新数据库
|
|
|
|
+ if (!batchUpdateList.isEmpty()) {
|
|
|
|
+ try {
|
|
|
|
+ // 分批处理,避免单次批量过大
|
|
|
|
+ int batchSize = 500; // 根据数据库性能调整
|
|
|
|
+ for (int i = 0; i < batchUpdateList.size(); i += batchSize) {
|
|
|
|
+ int end = Math.min(i + batchSize, batchUpdateList.size());
|
|
|
|
+ List<QwExternalContact> subList = batchUpdateList.subList(i, end);
|
|
|
|
+ qwExternalContactMapper.batchUpdateQwExternalContactByTags(subList);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ logger.error("批量更新失败: " + e.getMessage());
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 关闭线程池
|
|
|
|
+ executor.shutdown();
|
|
|
|
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ failList.add("处理过程中发生异常:"+e.getMessage());
|
|
|
|
+ }finally {
|
|
|
|
+
|
|
|
|
+ // 7. 确保线程池关闭
|
|
|
|
+ try {
|
|
|
|
+ // 先尝试正常关闭
|
|
|
|
+ executor.shutdown();
|
|
|
|
+ if (!executor.awaitTermination(15, TimeUnit.SECONDS)) {
|
|
|
|
+ // 超时后强制关闭
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ logger.warn("线程池强制关闭");
|
|
|
|
+ }
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ executor.shutdownNow();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- return R.ok("成功:" + suc + ",失败:" + err);
|
|
|
|
|
|
+ return R.ok("成功:" + suc.get() + ",失败:" + failList);
|
|
}
|
|
}
|
|
|
|
|
|
public void insertQwExternalByMq(Long ExtId){
|
|
public void insertQwExternalByMq(Long ExtId){
|