diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqEntity.java b/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqEntity.java index edbb91c5d5..d3cabe6a84 100644 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqEntity.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqEntity.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-22 16:16:42 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2025-03-07 09:41:57 + * @LastEditTime: 2025-03-07 09:44:18 * @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. @@ -29,6 +29,8 @@ import jakarta.persistence.Column; import jakarta.persistence.Convert; import jakarta.persistence.Entity; import jakarta.persistence.EntityListeners; +import jakarta.persistence.FetchType; +import jakarta.persistence.ManyToMany; import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Builder; @@ -71,7 +73,10 @@ public class FaqEntity extends BaseEntity { @Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT) private List answerList = new ArrayList<>(); - // TODO: 支持设置关联问题 + // 支持设置关联问题 + @Builder.Default + @ManyToMany(fetch = FetchType.LAZY) + private List relatedFaqs = new ArrayList<>(); @Builder.Default diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqRequest.java b/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqRequest.java index 2616b9aa54..db99c0ca68 100644 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqRequest.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-03-22 22:59:48 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2025-03-07 09:34:39 + * @LastEditTime: 2025-03-07 09:45:38 * @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. @@ -14,6 +14,8 @@ package com.bytedesk.kbase.faq; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import com.bytedesk.core.base.BaseRequest; @@ -34,6 +36,12 @@ public class FaqRequest extends BaseRequest { private String answer; + @Builder.Default + private List answerList = new ArrayList<>(); + + @Builder.Default + private List relatedFaqUids = new ArrayList<>(); + private String type; // 是否有效 diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqResponse.java b/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqResponse.java index 149bd9c83f..8d7562e084 100644 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqResponse.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/faq/FaqResponse.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-03-22 23:00:00 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2025-03-07 09:39:20 + * @LastEditTime: 2025-03-07 09:46:14 * @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. @@ -14,6 +14,7 @@ package com.bytedesk.kbase.faq; import java.time.LocalDateTime; +import java.util.List; import com.bytedesk.core.base.BaseResponse; @@ -34,6 +35,10 @@ public class FaqResponse extends BaseResponse { private String answer; + private List answerList; + + private List relatedFaqs; + private String type; private Integer viewCount; diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/settings/ServiceSettings.java b/modules/kbase/src/main/java/com/bytedesk/kbase/settings/ServiceSettings.java index 9db7b9e1b8..05951580b6 100644 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/settings/ServiceSettings.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/settings/ServiceSettings.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-14 10:45:08 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2025-02-28 13:38:13 + * @LastEditTime: 2025-03-07 10:11:57 * @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. @@ -177,6 +177,35 @@ public class ServiceSettings implements Serializable { @ManyToMany(fetch = FetchType.LAZY) private List shortcutFaqs = new ArrayList<>(); + // 满足一定触发条件下,机器人支持主动触发某个任务或者回复某些话术。 + // 例如:1、长时间访客无消息,机器人主动发问或者触发任务,主动暖场; + // 2、满足一定条件,自动触发某个任务。 + + // 主动触发设置 + @Builder.Default + private boolean enableProactiveTrigger = false; // 是否启用主动触发 + + @Builder.Default + private int noResponseTimeout = 300; // 访客无响应超时时间(秒),默认5分钟 + + @Builder.Default + @Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT) + private String proactiveMessage = "您好,看起来您有一段时间没有互动了。请问还需要帮助吗?"; // 主动发送的消息内容 + + @Builder.Default + private int maxProactiveCount = 3; // 最大主动触发次数,防止打扰用户 + + @Builder.Default + private int proactiveInterval = 600; // 两次主动触发的最小间隔(秒),默认10分钟 + + @Builder.Default + @Column(length = BytedeskConsts.COLUMN_EXTRA_LENGTH) + private String triggerConditions = BytedeskConsts.EMPTY_JSON_STRING; // 触发条件配置,JSON格式 + + @Builder.Default + @ManyToMany(fetch = FetchType.LAZY) + private List proactiveFaqs = new ArrayList<>(); // 主动推送的常见问题列表 + @NotBlank @Builder.Default private boolean showLogo = true; diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEntity.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEntity.java new file mode 100644 index 0000000000..4cd32f8646 --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEntity.java @@ -0,0 +1,63 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-05-11 18:14:28 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-07 10:03:35 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import com.bytedesk.core.base.BaseEntity; +import com.bytedesk.core.enums.LevelEnum; +import com.bytedesk.core.enums.PlatformEnum; +import com.bytedesk.core.message.MessageTypeEnum; +import com.bytedesk.core.thread.ThreadTypeEnum; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Entity +@Data +@Builder +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@NoArgsConstructor +// @EntityListeners({UnansweredEntityListener.class}) +@Table(name = "bytedesk_kbase_unanswered") +public class UnansweredEntity extends BaseEntity { + + private String content; + + @Builder.Default + @Column(name = "unanswered_type", nullable = false) + private String type = MessageTypeEnum.TEXT.name(); + + @Builder.Default + private String level = LevelEnum.ORGANIZATION.name(); + + @Builder.Default + private String platform = PlatformEnum.BYTEDESK.name(); + + private String threadUid; + + private String threadTopic; + + private String messageUid; + + private String userUid; +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEntityListener.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEntityListener.java new file mode 100644 index 0000000000..39521ff895 --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEntityListener.java @@ -0,0 +1,37 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2025-02-25 09:52:34 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-06 18:14:18 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * + * Copyright (c) 2025 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import org.springframework.stereotype.Component; + +import jakarta.persistence.PostPersist; +import jakarta.persistence.PostUpdate; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class UnansweredEntityListener { + + @PostPersist + public void onPostPersist(UnansweredEntity unanswered) { + log.info("onPostPersist: {}", unanswered); + } + + @PostUpdate + public void onPostUpdate(UnansweredEntity unanswered) { + log.info("onPostUpdate: {}", unanswered); + } + +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEventListener.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEventListener.java new file mode 100644 index 0000000000..e932e267dd --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredEventListener.java @@ -0,0 +1,27 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2025-02-25 09:44:18 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-02-25 09:54:17 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * + * Copyright (c) 2025 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import org.springframework.stereotype.Component; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +@AllArgsConstructor +public class UnansweredEventListener { + +} + diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredExcel.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredExcel.java new file mode 100644 index 0000000000..e5ef962a5c --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredExcel.java @@ -0,0 +1,40 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-08-01 06:18:10 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-03 23:09:02 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; + +import lombok.Data; + +/** + * https://github.com/alibaba/easyexcel + */ +@Data +public class UnansweredExcel { + + @ExcelProperty(index = 0, value = "Name") + @ColumnWidth(20) + private String name; + + @ExcelProperty(index = 1, value = "Type") + @ColumnWidth(20) + private String type; + + @ExcelProperty(index = 2, value = "Color") + @ColumnWidth(20) + private String color; + + +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredPermissions.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredPermissions.java new file mode 100644 index 0000000000..2e95ff4990 --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredPermissions.java @@ -0,0 +1,29 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-11-05 16:58:18 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2024-11-08 13:40:08 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +public class UnansweredPermissions { + + public static final String UNANSWERED_PREFIX = "UNANSWERED_"; + // Unanswered permissions + public static final String UNANSWERED_CREATE = "hasAuthority('UNANSWERED_CREATE')"; + public static final String UNANSWERED_READ = "hasAuthority('UNANSWERED_READ')"; + public static final String UNANSWERED_UPDATE = "hasAuthority('UNANSWERED_UPDATE')"; + public static final String UNANSWERED_DELETE = "hasAuthority('UNANSWERED_DELETE')"; + public static final String UNANSWERED_EXPORT = "hasAuthority('UNANSWERED_EXPORT')"; + + // + + +} \ No newline at end of file diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRepository.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRepository.java new file mode 100644 index 0000000000..138558739f --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRepository.java @@ -0,0 +1,26 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-05-11 18:25:55 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2024-10-24 18:20:39 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface UnansweredRepository extends JpaRepository, JpaSpecificationExecutor { + + Optional findByUid(String uid); + + // Boolean existsByPlatform(String platform); +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRequest.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRequest.java new file mode 100644 index 0000000000..c029a1c322 --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRequest.java @@ -0,0 +1,56 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-05-11 18:26:04 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-07 09:55:36 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import com.bytedesk.core.base.BaseRequest; +import com.bytedesk.core.enums.LevelEnum; +import com.bytedesk.core.enums.PlatformEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Data +@Builder +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@AllArgsConstructor +@NoArgsConstructor +public class UnansweredRequest extends BaseRequest { + + // private String content; + + // @Builder.Default + // private String type = UnansweredTypeEnum.CUSTOMER.name(); + + // @Builder.Default + // private String color = "red"; + + @Builder.Default + private String level = LevelEnum.ORGANIZATION.name(); + + @Builder.Default + private String platform = PlatformEnum.BYTEDESK.name(); + + private String threadUid; + + private String threadTopic; + + private String messageUid; + + // private String userUid; +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredResponse.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredResponse.java new file mode 100644 index 0000000000..eaf774fc80 --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredResponse.java @@ -0,0 +1,42 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-05-11 18:26:12 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2024-10-24 18:18:57 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import java.time.LocalDateTime; + +import com.bytedesk.core.base.BaseResponse; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Data +@Builder +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@AllArgsConstructor +@NoArgsConstructor +public class UnansweredResponse extends BaseResponse { + + private String name; + + private String type; + + private String color; + + private LocalDateTime createdAt; +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRestController.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRestController.java new file mode 100644 index 0000000000..429dce8ac8 --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRestController.java @@ -0,0 +1,89 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-05-11 18:25:36 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-05 16:37:26 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bytedesk.core.base.BaseRestController; +import com.bytedesk.core.rbac.role.RolePermissions; +import com.bytedesk.core.utils.JsonResult; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; + +@RestController +@RequestMapping("/api/v1/unanswered") +@AllArgsConstructor +public class UnansweredRestController extends BaseRestController { + + private final UnansweredRestService unansweredService; + + @PreAuthorize(RolePermissions.ROLE_ADMIN) + @Override + public ResponseEntity queryByOrg(UnansweredRequest request) { + + Page unanswereds = unansweredService.queryByOrg(request); + + return ResponseEntity.ok(JsonResult.success(unanswereds)); + } + + @Override + public ResponseEntity queryByUser(UnansweredRequest request) { + + Page unanswereds = unansweredService.queryByUser(request); + + return ResponseEntity.ok(JsonResult.success(unanswereds)); + } + + @Override + public ResponseEntity create(UnansweredRequest request) { + + UnansweredResponse unanswered = unansweredService.create(request); + + return ResponseEntity.ok(JsonResult.success(unanswered)); + } + + @Override + public ResponseEntity update(UnansweredRequest request) { + + UnansweredResponse unanswered = unansweredService.update(request); + + return ResponseEntity.ok(JsonResult.success(unanswered)); + } + + @Override + public ResponseEntity delete(UnansweredRequest request) { + + unansweredService.delete(request); + + return ResponseEntity.ok(JsonResult.success()); + } + + @Override + public Object export(UnansweredRequest request, HttpServletResponse response) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'export'"); + } + + @Override + public ResponseEntity queryByUid(UnansweredRequest request) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'queryByUid'"); + } + +} \ No newline at end of file diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRestService.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRestService.java new file mode 100644 index 0000000000..508f0278dc --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredRestService.java @@ -0,0 +1,169 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-05-11 18:25:45 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-07 09:54:37 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import java.util.Optional; + +import org.modelmapper.ModelMapper; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.ObjectOptimisticLockingFailureException; +import org.springframework.stereotype.Service; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Recover; +import org.springframework.retry.annotation.Retryable; + +import com.bytedesk.core.base.BaseRestService; +import com.bytedesk.core.rbac.auth.AuthService; +import com.bytedesk.core.rbac.user.UserEntity; +import com.bytedesk.core.uid.UidUtils; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@AllArgsConstructor +public class UnansweredRestService extends BaseRestService { + + private final UnansweredRepository unansweredRepository; + + private final ModelMapper modelMapper; + + private final UidUtils uidUtils; + + private final AuthService authService; + + @Override + public Page queryByOrg(UnansweredRequest request) { + Pageable pageable = request.getPageable(); + Specification spec = UnansweredSpecification.search(request); + Page page = unansweredRepository.findAll(spec, pageable); + return page.map(this::convertToResponse); + } + + @Override + public Page queryByUser(UnansweredRequest request) { + UserEntity user = authService.getUser(); + if (user == null) { + throw new RuntimeException("user not found"); + } + request.setUserUid(user.getUid()); + // + return queryByOrg(request); + } + + @Cacheable(value = "unanswered", key = "#uid", unless="#result==null") + @Override + public Optional findByUid(String uid) { + return unansweredRepository.findByUid(uid); + } + + @Override + public UnansweredResponse create(UnansweredRequest request) { + UserEntity user = authService.getUser(); + if (user == null) { + throw new RuntimeException("user not found"); + } + request.setUserUid(user.getUid()); + + UnansweredEntity entity = modelMapper.map(request, UnansweredEntity.class); + entity.setUid(uidUtils.getUid()); + // + entity.setOrgUid(user.getOrgUid()); + + UnansweredEntity savedEntity = save(entity); + if (savedEntity == null) { + throw new RuntimeException("Create unanswered failed"); + } + return convertToResponse(savedEntity); + } + + @Override + public UnansweredResponse update(UnansweredRequest request) { + Optional optional = unansweredRepository.findByUid(request.getUid()); + if (optional.isPresent()) { + UnansweredEntity entity = optional.get(); + modelMapper.map(request, entity); + // + UnansweredEntity savedEntity = save(entity); + if (savedEntity == null) { + throw new RuntimeException("Update unanswered failed"); + } + return convertToResponse(savedEntity); + } + else { + throw new RuntimeException("Unanswered not found"); + } + } + + /** + * 保存标签,失败时自动重试 + * maxAttempts: 最大重试次数(包括第一次尝试) + * backoff: 重试延迟,multiplier是延迟倍数 + * recover: 当重试次数用完后的回调方法 + */ + @Retryable( + value = { Exception.class }, + maxAttempts = 3, + backoff = @Backoff(delay = 1000, multiplier = 2) + ) + @Override + public UnansweredEntity save(UnansweredEntity entity) { + // log.info("Attempting to save unanswered: {}", entity.getName()); + return unansweredRepository.save(entity); + } + + /** + * 重试失败后的回调方法 + */ + @Recover + public UnansweredEntity recover(Exception e, UnansweredEntity entity) { + // log.error("Failed to save unanswered after 3 attempts: {}", entity.getName(), e); + // 可以在这里添加告警通知 + throw new RuntimeException("Failed to save unanswered after retries: " + e.getMessage()); + } + + @Override + public void deleteByUid(String uid) { + Optional optional = unansweredRepository.findByUid(uid); + if (optional.isPresent()) { + optional.get().setDeleted(true); + save(optional.get()); + // unansweredRepository.delete(optional.get()); + } + else { + throw new RuntimeException("Unanswered not found"); + } + } + + @Override + public void delete(UnansweredRequest request) { + deleteByUid(request.getUid()); + } + + @Override + public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, UnansweredEntity entity) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'handleOptimisticLockingFailureException'"); + } + + @Override + public UnansweredResponse convertToResponse(UnansweredEntity entity) { + return modelMapper.map(entity, UnansweredResponse.class); + } + +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredSpecification.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredSpecification.java new file mode 100644 index 0000000000..26172ed82c --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredSpecification.java @@ -0,0 +1,43 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-07-09 22:19:21 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-07 09:55:59 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.jpa.domain.Specification; +import org.springframework.util.StringUtils; + +import com.bytedesk.core.base.BaseSpecification; + +import jakarta.persistence.criteria.Predicate; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class UnansweredSpecification extends BaseSpecification { + + public static Specification search(UnansweredRequest request) { + // log.info("request: {}", request); + return (root, query, criteriaBuilder) -> { + List predicates = new ArrayList<>(); + predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid())); + // + if (StringUtils.hasText(request.getUserUid())) { + predicates.add(criteriaBuilder.equal(root.get("userUid"), request.getUserUid())); + } + // + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); + }; + } +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredTypeEnum.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredTypeEnum.java new file mode 100644 index 0000000000..678b6398c3 --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/UnansweredTypeEnum.java @@ -0,0 +1,19 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-07-23 17:02:46 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2024-07-23 17:02:48 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered; + +public enum UnansweredTypeEnum { + THREAD, + CUSTOMER +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredCreateEvent.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredCreateEvent.java new file mode 100644 index 0000000000..d43d753d3c --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredCreateEvent.java @@ -0,0 +1,36 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2025-02-25 09:59:29 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-07 09:51:52 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * + * Copyright (c) 2025 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered.event; + +import org.springframework.context.ApplicationEvent; + +import com.bytedesk.kbase.unanswered.UnansweredEntity; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class UnansweredCreateEvent extends ApplicationEvent { + + private static final long serialVersionUID = 1L; + + private UnansweredEntity unanswered; + + public UnansweredCreateEvent(UnansweredEntity unanswered) { + super(unanswered); + this.unanswered = unanswered; + } + +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredDeleteEvent.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredDeleteEvent.java new file mode 100644 index 0000000000..db26c1bcde --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredDeleteEvent.java @@ -0,0 +1,35 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2025-02-25 12:31:16 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-03-07 09:51:56 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * + * Copyright (c) 2025 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered.event; + +import org.springframework.context.ApplicationEvent; + +import com.bytedesk.kbase.unanswered.UnansweredEntity; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class UnansweredDeleteEvent extends ApplicationEvent { + + private static final long serialVersionUID = 1L; + + private UnansweredEntity unanswered; + + public UnansweredDeleteEvent(UnansweredEntity unanswered) { + super(unanswered); + this.unanswered = unanswered; + } +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredUpdateEvent.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredUpdateEvent.java new file mode 100644 index 0000000000..5327431ebb --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/event/UnansweredUpdateEvent.java @@ -0,0 +1,36 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2025-02-25 09:59:29 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2025-02-25 10:01:00 + * @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. + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * + * Copyright (c) 2025 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.kbase.unanswered.event; + +import org.springframework.context.ApplicationEvent; + +import com.bytedesk.kbase.unanswered.UnansweredEntity; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class UnansweredUpdateEvent extends ApplicationEvent { + + private static final long serialVersionUID = 1L; + + private UnansweredEntity unanswered; + + public UnansweredUpdateEvent(UnansweredEntity unanswered) { + super(unanswered); + this.unanswered = unanswered; + } + +} diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/package-info.java b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/package-info.java new file mode 100644 index 0000000000..9d23f86c1f --- /dev/null +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/unanswered/package-info.java @@ -0,0 +1,8 @@ +/** + * ByteDesk 标签管理包 + * 提供标签的CRUD、搜索等功能 + */ +@NonNullApi +package com.bytedesk.kbase.unanswered; + +import org.springframework.lang.NonNullApi;