diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntity.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntity.java index 6b57b55de8..924bacb2ed 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntity.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntity.java @@ -150,8 +150,28 @@ public class ThreadEntity extends AbstractThreadEntity { return getClient().equals(ClientEnum.WECHAT_MINI.name()); } + /** + * 检查会话是否曾经处于离线状态 + */ + public Boolean wasOffline() { + ThreadExtra extra = getThreadExtra(); + return extra != null && extra.isWasOffline(); + } + + /** + * 将当前会话标记为离线状态 + */ public ThreadEntity setOffline() { setStatus(ThreadProcessStatusEnum.OFFLINE.name()); + + // 更新extra信息,记录曾经处于离线状态 + ThreadExtra extra = getThreadExtra(); + if (extra == null) { + extra = new ThreadExtra(); + } + extra.setWasOffline(true); + setExtra(JSON.toJSONString(extra)); + return this; } diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadExtra.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadExtra.java index a2c65cc934..101917de06 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadExtra.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadExtra.java @@ -16,9 +16,19 @@ package com.bytedesk.core.thread; import java.io.Serializable; import lombok.Data; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.experimental.Accessors; @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) public class ThreadExtra implements Serializable { private static final long serialVersionUID = 1L; + + private boolean wasOffline; // 标记此会话是否曾经处于离线状态 } diff --git a/modules/service/src/main/java/com/bytedesk/service/queue/QueueEntity.java b/modules/service/src/main/java/com/bytedesk/service/queue/QueueEntity.java index f472cff397..de466cbdca 100644 --- a/modules/service/src/main/java/com/bytedesk/service/queue/QueueEntity.java +++ b/modules/service/src/main/java/com/bytedesk/service/queue/QueueEntity.java @@ -94,11 +94,13 @@ public class QueueEntity extends BaseEntity { } /** - * 获取请求时客服离线的人数 + * 获取请求时客服离线的人数(包括当前离线和曾经离线但已关闭的) */ public int getOfflineCount() { return (int) queueMembers.stream() - .filter(member -> member.getThread() != null && member.getThread().isOffline()) + .filter(member -> member.wasOffline() || + (member.getThread() != null && member.getThread().isOffline()) || + (member.getThread() != null && member.getThread().wasOffline())) .count(); } diff --git a/modules/service/src/main/java/com/bytedesk/service/queue_member/QueueMemberEntity.java b/modules/service/src/main/java/com/bytedesk/service/queue_member/QueueMemberEntity.java index 5007841af1..b839712413 100644 --- a/modules/service/src/main/java/com/bytedesk/service/queue_member/QueueMemberEntity.java +++ b/modules/service/src/main/java/com/bytedesk/service/queue_member/QueueMemberEntity.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-10-14 17:23:58 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2025-04-03 16:11:11 + * @LastEditTime: 2025-04-05 11:39:24 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -178,6 +178,10 @@ public class QueueMemberEntity extends BaseEntity { @Builder.Default @Column(name = "queue_workgroup", length = BytedeskConsts.COLUMN_EXTRA_LENGTH) private String workgroup = BytedeskConsts.EMPTY_JSON_STRING; + + @Builder.Default + @Column(name = "was_offline") + private boolean wasOffline = false; // 标记该会话是否曾处于离线状态 /** * 计算等待时间(秒) @@ -209,4 +213,18 @@ public class QueueMemberEntity extends BaseEntity { // 计算等待时间 this.waitTime = (int) Duration.between(enqueueTime, acceptTime).getSeconds(); } + + /** + * 标记为离线状态 + */ + public void markAsOffline() { + this.wasOffline = true; + } + + /** + * 检查是否曾经是离线状态 + */ + public boolean wasOffline() { + return this.wasOffline || (thread != null && thread.isOffline()); + } } diff --git a/modules/service/src/main/java/com/bytedesk/service/routing_strategy/AgentThreadRoutingStrategy.java b/modules/service/src/main/java/com/bytedesk/service/routing_strategy/AgentThreadRoutingStrategy.java index 50c208bfb5..5910c66011 100644 --- a/modules/service/src/main/java/com/bytedesk/service/routing_strategy/AgentThreadRoutingStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/routing_strategy/AgentThreadRoutingStrategy.java @@ -216,12 +216,17 @@ public class AgentThreadRoutingStrategy implements ThreadRoutingStrategy { thread.setOffline() .setUnreadCount(0) .setContent(agent.getMessageLeaveSettings().getMessageLeaveTip()); + + // 标记QueueMember为离线状态 + queueMemberEntity.markAsOffline(); + queueMemberRestService.save(queueMemberEntity); + ThreadEntity savedThread = threadService.save(thread); if (savedThread == null) { log.error("Failed to save thread {}", thread.getUid()); throw new RuntimeException("Failed to save thread " + thread.getUid()); } - // + // 查询最新一条消息,如果距离当前时间不超过30分钟,则直接使用之前的消息,否则创建新的消息 Optional messageOptional = messageRestService.findLatestByThreadUid(savedThread.getUid()); if (messageOptional.isPresent()) {