This commit is contained in:
jack ning
2025-03-11 09:16:06 +08:00
parent a290176b45
commit d6bed8436c
24 changed files with 1139 additions and 9 deletions

View File

@@ -0,0 +1,20 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-02-06 15:23:56
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-06 15:23:58
* @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.article_archive;
public enum ArticleArchiveAuditStatusEnum {
PENDING,
APPROVED,
REJECTED;
}

View File

@@ -0,0 +1,150 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-22 16:16:42
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-11 09:10: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.article_archive;
import java.time.LocalDateTime;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.BytedeskConsts;
import com.bytedesk.core.constant.TypeConsts;
import com.bytedesk.kbase.kbase.KbaseTypeEnum;
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({ ArticleArchiveEntityListener.class })
@Table(name = "bytedesk_kbase_article_archive")
public class ArticleArchiveEntity extends BaseEntity {
private static final long serialVersionUID = 1L;
private String title;
private String summary;
// private String coverImageUrl;
@Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT)
private String contentMarkdown;
@Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT)
private String contentHtml;
@Builder.Default
@Column(name = "article_archive_type", nullable = false)
private String type = KbaseTypeEnum.HELPCENTER.name();
// @Builder.Default
// @ManyToMany
// private List<Tag> tags = new ArrayList<>();
// @Builder.Default
// @ElementCollection
// @CollectionTable(name = "bytedesk_kbase_article_archive_tags")
// private List<String> tags = new ArrayList<>();
@Builder.Default
private String tags = BytedeskConsts.EMPTY_ARRAY_STRING;
@Builder.Default
@Column(name = "is_top")
private boolean top = false;
@Builder.Default
@Column(name = "is_published")
private boolean published = false;
@Builder.Default
@Column(name = "is_markdown")
private boolean markdown = false;
@Builder.Default
private int readCount = 0;
@Builder.Default
private int likeCount = 0;
// status 状态
@Builder.Default
private String status = ArticleArchiveStatusEnum.DRAFT.name();
// editor 编辑者
@Builder.Default
private String editor = BytedeskConsts.EMPTY_STRING;
// 有效开始日期
private LocalDateTime startDate;
// 有效结束日期
private LocalDateTime endDate;
// 是否需要审核
@Builder.Default
@Column(name = "need_audit")
private boolean needAudit = false;
// 审核状态
@Builder.Default
@Column(name = "audit_status")
private String auditStatus = ArticleArchiveAuditStatusEnum.PENDING.name();
// 审核意见
@Builder.Default
@Column(name = "audit_opinion")
private String auditOpinion = BytedeskConsts.EMPTY_STRING;
// 审核人
@Builder.Default
@Column(name = "audit_user")
private String auditUser = BytedeskConsts.EMPTY_STRING;
// 是否需要密码访问
@Builder.Default
@Column(name = "is_password_protected")
private boolean isPasswordProtected = false;
private String password;
private String categoryUid; // 文章分类。生成页面时,先查询分类,后通过分类查询相关文章。
private String kbUid; // 对应知识库
@Builder.Default
@Column(name = "create_user", length = 1024)
// @JdbcTypeCode(SqlTypes.JSON)
private String user = BytedeskConsts.EMPTY_JSON_STRING;
// public Document toDocument(@NonNull ArticleArchiveEntity article_archive) {
// return new Document(article_archive.getTitle() + article_archive.getContentMarkdown(),
// Map.of("categoryUid", article_archive.getCategoryUid(), "kbUid", article_archive.getKbUid()));
// }
}

View File

@@ -0,0 +1,50 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-07-31 16:33:09
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-01-09 22:56:09
* @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.article_archive;
import org.apache.commons.lang3.SerializationUtils;
import org.springframework.stereotype.Component;
import com.bytedesk.core.config.BytedeskEventPublisher;
import com.bytedesk.core.utils.ApplicationContextHolder;
import com.bytedesk.kbase.article_archive.event.ArticleArchiveCreateEvent;
import com.bytedesk.kbase.article_archive.event.ArticleArchiveUpdateEvent;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostUpdate;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class ArticleArchiveEntityListener {
@PostPersist
public void onPostPersist(ArticleArchiveEntity article_archive) {
log.info("ArticleArchiveEntityListener: onPostPersist");
ArticleArchiveEntity clonedArticleArchive = SerializationUtils.clone(article_archive);
//
BytedeskEventPublisher publisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class);
publisher.publishEvent(new ArticleArchiveCreateEvent(this, clonedArticleArchive));
}
@PostUpdate
public void onPostUpdate(ArticleArchiveEntity article_archive) {
log.info("ArticleArchiveEntityListener: onPostUpdate");
ArticleArchiveEntity clonedArticleArchive = SerializationUtils.clone(article_archive);
//
BytedeskEventPublisher publisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class);
publisher.publishEvent(new ArticleArchiveUpdateEvent(this, clonedArticleArchive));
}
}

View File

@@ -0,0 +1,36 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-07-31 16:33:23
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-08-27 14:06:16
* @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.article_archive;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class ArticleArchiveEventListener {
// @EventListener
// public void onArticleArchiveCreateEvent(GenericApplicationEvent<ArticleArchiveCreateEvent> event) {
// log.info("Received ArticleArchive Create Event");
// }
// @EventListener
// public void onArticleArchiveUpdateEvent(GenericApplicationEvent<ArticleArchiveUpdateEvent> event) {
// log.info("Received ArticleArchive Update Event");
// }
}

View File

@@ -0,0 +1,48 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-11-06 21:43:58
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-11 09:12: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
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.kbase.article_archive;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;
import lombok.AllArgsConstructor;
@Component
@AllArgsConstructor
public class ArticleArchiveInitializer implements SmartInitializingSingleton {
// private final AuthorityRestService authorityService;
@Override
public void afterSingletonsInstantiated() {
// init();
}
// private void init() {
// for (PermissionEnum permission : PermissionEnum.values()) {
// String permissionValue = ArticleArchivePermissions.ARTICLE_ARCHIVE_PREFIX + permission.name();
// if (authorityService.existsByValue(permissionValue)) {
// continue;
// }
// AuthorityRequest authRequest = AuthorityRequest.builder()
// .name(I18Consts.I18N_PREFIX + permissionValue)
// .value(permissionValue)
// .description("Permission for " + permissionValue)
// .build();
// authRequest.setUid(permissionValue.toLowerCase());
// authorityService.create(authRequest);
// }
// }
}

View File

@@ -0,0 +1,25 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-11-05 17:07:03
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-11 09:13:25
* @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.article_archive;
public class ArticleArchivePermissions {
public static final String ARTICLE_ARCHIVE_PREFIX = "ARTICLE_ARCHIVE_";
// ArticleArchive permissions
public static final String ARTICLE_ARCHIVE_CREATE = "hasAuthority('ARTICLE_ARCHIVE_CREATE')";
public static final String ARTICLE_ARCHIVE_READ = "hasAuthority('ARTICLE_ARCHIVE_READ')";
public static final String ARTICLE_ARCHIVE_UPDATE = "hasAuthority('ARTICLE_ARCHIVE_UPDATE')";
public static final String ARTICLE_ARCHIVE_DELETE = "hasAuthority('ARTICLE_ARCHIVE_DELETE')";
public static final String ARTICLE_ARCHIVE_EXPORT = "hasAuthority('ARTICLE_ARCHIVE_EXPORT')";
}

View File

@@ -0,0 +1,25 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 22:59:32
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-07-23 11:46: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.
* 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.article_archive;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface ArticleArchiveRepository extends JpaRepository<ArticleArchiveEntity, Long>, JpaSpecificationExecutor<ArticleArchiveEntity> {
Optional<ArticleArchiveEntity> findByUid(String uid);
}

View File

@@ -0,0 +1,101 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 22:59:48
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-07 09:34:22
* @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.article_archive;
import java.time.LocalDateTime;
import com.bytedesk.core.base.BaseRequest;
import com.bytedesk.core.constant.BytedeskConsts;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Data
@Builder
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class ArticleArchiveRequest extends BaseRequest {
private String title;
private String summary;
// private String coverImageUrl;
private String contentMarkdown;
private String contentHtml;
// search.html 搜索用
private String content;
// @Builder.Default
// private MessageTypeEnum contentType = MessageTypeEnum.TEXT;
@Builder.Default
private String tags = BytedeskConsts.EMPTY_ARRAY_STRING;
private LocalDateTime startDate;
private LocalDateTime endDate;
@Builder.Default
private Boolean top = false;
@Builder.Default
private Boolean published = false;
@Builder.Default
private Boolean markdown = false;
@Builder.Default
private Integer readCount = 0;
@Builder.Default
private Integer likeCount = 0;
// status 状态
@Builder.Default
private String status = ArticleArchiveStatusEnum.DRAFT.name();
// editor 编辑者
@Builder.Default
private String editor = BytedeskConsts.EMPTY_STRING;
// 是否需要审核
@Builder.Default
private Boolean needAudit = false;
// 审核状态
@Builder.Default
private String auditStatus = ArticleArchiveAuditStatusEnum.PENDING.name();
// 审核意见
@Builder.Default
private String auditOpinion = BytedeskConsts.EMPTY_STRING;
// 审核人
@Builder.Default
private String auditUser = BytedeskConsts.EMPTY_STRING;
private String categoryUid;
private String kbUid;
private String userUid;
}

View File

@@ -0,0 +1,99 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 23:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-10 13:57: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.article_archive;
import java.time.LocalDateTime;
import com.bytedesk.core.base.BaseResponse;
import com.bytedesk.core.rbac.user.UserProtobuf;
import com.bytedesk.kbase.kbase.KbaseTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Data
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class ArticleArchiveResponse extends BaseResponse {
private String title;
private String summary;
// private String coverImageUrl;
private String contentMarkdown;
private String contentHtml;
private KbaseTypeEnum type;
private String tags;
// 有效开始日期
private LocalDateTime startDate;
// 有效结束日期
private LocalDateTime endDate;
private Boolean top;
private Boolean published;
private Boolean markdown;
private Integer readCount;
private Integer likeCount = 0;
// status 状态
private String status;
// editor 编辑者
private String editor;
// 是否需要审核
private Boolean needAudit;
// 审核状态
private String auditStatus;
// 审核意见
private String auditOpinion;
// 审核人
private String auditUser;
private String categoryUid;
private String kbUid;
// private String orgUid;
// private LocalDateTime createdAt;
// private LocalDateTime updatedAt;
private UserProtobuf user;
// public String getCreatedAt() {
// return BdDateUtils.formatDatetimeToString(createdAt);
// }
// public String getUpdatedAt() {
// return BdDateUtils.formatDatetimeToString(updatedAt);
// }
}

View File

@@ -0,0 +1,101 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 22:59:07
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-05 16:38:28
* @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.article_archive;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.bytedesk.core.base.BaseRestController;
import com.bytedesk.core.utils.JsonResult;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
@RestController
@RequestMapping("/api/v1/article_archive")
@AllArgsConstructor
public class ArticleArchiveRestController extends BaseRestController<ArticleArchiveRequest> {
private final ArticleArchiveRestService article_archiveService;
// @PreAuthorize(RolePermissions.ROLE_ADMIN)
@Override
public ResponseEntity<?> queryByOrg(ArticleArchiveRequest request) {
Page<ArticleArchiveResponse> page = article_archiveService.queryByOrg(request);
return ResponseEntity.ok(JsonResult.success(page));
}
@Override
public ResponseEntity<?> queryByUser(ArticleArchiveRequest request) {
Page<ArticleArchiveResponse> page = article_archiveService.queryByUser(request);
return ResponseEntity.ok(JsonResult.success(page));
}
// query detail
@GetMapping("/query/detail")
public ResponseEntity<?> queryDetail(ArticleArchiveRequest request) {
ArticleArchiveResponse article_archive = article_archiveService.queryDetail(request);
if (article_archive == null) {
return ResponseEntity.ok(JsonResult.error("article_archive not found"));
}
return ResponseEntity.ok(JsonResult.success(article_archive));
}
@Override
public ResponseEntity<?> create(@RequestBody ArticleArchiveRequest request) {
ArticleArchiveResponse article_archive = article_archiveService.create(request);
return ResponseEntity.ok(JsonResult.success(article_archive));
}
@Override
public ResponseEntity<?> update(@RequestBody ArticleArchiveRequest request) {
ArticleArchiveResponse article_archive = article_archiveService.update(request);
return ResponseEntity.ok(JsonResult.success(article_archive));
}
@Override
public ResponseEntity<?> delete(@RequestBody ArticleArchiveRequest request) {
article_archiveService.delete(request);
return ResponseEntity.ok(JsonResult.success("delete success", request.getUid()));
}
@Override
public Object export(ArticleArchiveRequest request, HttpServletResponse response) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'export'");
}
@Override
public ResponseEntity<?> queryByUid(ArticleArchiveRequest request) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'queryByUid'");
}
}

View File

@@ -0,0 +1,41 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 22:59:07
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-10-30 10:06:45
* @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.article_archive;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.bytedesk.core.utils.JsonResult;
import lombok.AllArgsConstructor;
@RestController
@RequestMapping("/visitor/api/v1/article_archive")
@AllArgsConstructor
public class ArticleArchiveRestControllerVisitor {
private final ArticleArchiveRestService article_archiveService;
@RequestMapping("/search")
public ResponseEntity<?> searchKb(ArticleArchiveRequest request) {
Page<ArticleArchiveResponse> page = article_archiveService.queryByOrg(request);
return ResponseEntity.ok(JsonResult.success(page));
}
}

View File

@@ -0,0 +1,173 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 22:59:18
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-11 09:10: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
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.kbase.article_archive;
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 com.alibaba.fastjson2.JSON;
import com.bytedesk.core.base.BaseRestService;
import com.bytedesk.core.rbac.auth.AuthService;
import com.bytedesk.core.rbac.user.UserEntity;
import com.bytedesk.core.rbac.user.UserProtobuf;
import com.bytedesk.core.uid.UidUtils;
import com.bytedesk.core.utils.ConvertUtils;
import com.bytedesk.kbase.utils.KbaseConvertUtils;
import lombok.AllArgsConstructor;
@Service
@AllArgsConstructor
public class ArticleArchiveRestService extends BaseRestService<ArticleArchiveEntity, ArticleArchiveRequest, ArticleArchiveResponse> {
private final ArticleArchiveRepository article_archiveRepository;
private final ModelMapper modelMapper;
private final UidUtils uidUtils;
private final AuthService authService;
@Override
public Page<ArticleArchiveResponse> queryByOrg(ArticleArchiveRequest request) {
Pageable pageable = request.getPageable();
Specification<ArticleArchiveEntity> spec = ArticleArchiveSpecification.search(request);
Page<ArticleArchiveEntity> page = article_archiveRepository.findAll(spec, pageable);
return page.map(this::convertToResponse);
}
@Override
public Page<ArticleArchiveResponse> queryByUser(ArticleArchiveRequest request) {
UserEntity user = authService.getUser();
if (user == null) {
throw new RuntimeException("user not found");
}
String userUid = user.getUid();
//
request.setUserUid(userUid);
//
return queryByOrg(request);
}
// query detail
public ArticleArchiveResponse queryDetail(ArticleArchiveRequest request) {
Optional<ArticleArchiveEntity> optional = findByUid(request.getUid());
if (optional.isPresent()) {
return convertToResponse(optional.get());
}
return null;
}
@Cacheable(value = "article_archive", key="#uid", unless = "#result == null")
@Override
public Optional<ArticleArchiveEntity> findByUid(String uid) {
return article_archiveRepository.findByUid(uid);
}
@Override
public ArticleArchiveResponse create(ArticleArchiveRequest request) {
UserEntity user = authService.getUser();
if (user == null) {
throw new RuntimeException("user not found");
}
ArticleArchiveEntity entity = modelMapper.map(request, ArticleArchiveEntity.class);
entity.setUid(uidUtils.getUid());
//
UserProtobuf userProtobuf = ConvertUtils.convertToUserProtobuf(user);
entity.setUser(JSON.toJSONString(userProtobuf));
entity.setOrgUid(user.getOrgUid());
//
ArticleArchiveEntity savedArticleArchive = save(entity);
if (savedArticleArchive == null) {
throw new RuntimeException("article_archive save failed");
}
//
return convertToResponse(savedArticleArchive);
}
@Override
public ArticleArchiveResponse update(ArticleArchiveRequest request) {
Optional<ArticleArchiveEntity> optional = findByUid(request.getUid());
if (optional.isPresent()) {
ArticleArchiveEntity entity = optional.get();
// modelMapper.map(request, entity);
entity.setTitle(request.getTitle());
entity.setSummary(request.getSummary());
entity.setContentHtml(request.getContentHtml());
entity.setContentMarkdown(request.getContentMarkdown());
entity.setCategoryUid(request.getCategoryUid());
//
ArticleArchiveEntity savedArticleArchive = save(entity);
if (savedArticleArchive == null) {
throw new RuntimeException("article_archive save failed");
}
//
return convertToResponse(savedArticleArchive);
} else {
throw new RuntimeException("article_archive not found");
}
}
@Override
public ArticleArchiveEntity save(ArticleArchiveEntity entity) {
try {
return article_archiveRepository.save(entity);
} catch (ObjectOptimisticLockingFailureException e) {
handleOptimisticLockingFailureException(e, entity);
}
return null;
}
@Override
public void deleteByUid(String uid) {
Optional<ArticleArchiveEntity> optional = findByUid(uid);
if (optional.isPresent()) {
optional.get().setDeleted(true);
save(optional.get());
}
}
@Override
public void delete(ArticleArchiveRequest entity) {
deleteByUid(entity.getUid());
}
@Override
public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, ArticleArchiveEntity entity) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'handleOptimisticLockingFailureException'");
}
@Override
public ArticleArchiveResponse convertToResponse(ArticleArchiveEntity entity) {
return KbaseConvertUtils.convertToArticleArchiveResponse(entity);
}
@Override
public ArticleArchiveResponse queryByUid(ArticleArchiveRequest request) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'queryByUid'");
}
}

View File

@@ -0,0 +1,68 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-07-31 17:52:12
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-07-31 19:08: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.article_archive;
import java.util.Optional;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import com.bytedesk.kbase.kbase.KbaseEntity;
import com.bytedesk.kbase.kbase.KbaseRestService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* Controller for "/article_archive".
*/
@Slf4j
@Controller
@RequestMapping("/article_archive")
@RequiredArgsConstructor
public class ArticleArchiveRouteController {
private final ArticleArchiveRestService article_archiveService;
private final KbaseRestService knowledgebaseService;
//
@RequestMapping("/{kbUid:.+}/{article_archiveUid:.+}")
public String index(Model model, @PathVariable("kbUid") String kbUid, @PathVariable("article_archiveUid") String article_archiveUid) {
log.info("kbUid {}, article_archiveUid: {}", kbUid, article_archiveUid);
//
Optional<ArticleArchiveEntity> article_archiveOptional = article_archiveService.findByUid(article_archiveUid);
if (article_archiveOptional.isPresent()) {
model.addAttribute("article_archive", article_archiveOptional.get());
} else {
return "redirect:/404";
}
//
Optional<KbaseEntity> knowledgebaseOptional = knowledgebaseService.findByUid(kbUid);
if (knowledgebaseOptional.isPresent()) {
model.addAttribute("knowledgebase", knowledgebaseOptional.get());
} else {
return "redirect:/404";
}
// TODO: 生成静态页面,考虑语言切换
//
return "kbase/zh/article_archive";
}
}

View File

@@ -0,0 +1,60 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-06-08 12:30:14
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-01 10:46: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.article_archive;
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 ArticleArchiveSpecification extends BaseSpecification {
public static Specification<ArticleArchiveEntity> search(ArticleArchiveRequest request) {
log.info("request: {}", request);
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
// predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
predicates.add(criteriaBuilder.equal(root.get("deleted"), false));
if (StringUtils.hasText(request.getOrgUid())) {
predicates.add(criteriaBuilder.equal(root.get("orgUid"), request.getOrgUid()));
}
if (StringUtils.hasText(request.getTitle())) {
predicates.add(criteriaBuilder.like(root.get("title"), "%" + request.getTitle() + "%"));
}
if (StringUtils.hasText(request.getContent())) {
predicates.add(criteriaBuilder.like(root.get("contentHtml"), "%" + request.getContent() + "%"));
}
if (StringUtils.hasText(request.getContent())) {
predicates.add(criteriaBuilder.like(root.get("contentMarkdown"), "%" + request.getContent() + "%"));
}
if (StringUtils.hasText(request.getCategoryUid())) {
predicates.add(criteriaBuilder.equal(root.get("categoryUid"), request.getCategoryUid()));
}
if (StringUtils.hasText(request.getKbUid())) {
predicates.add(criteriaBuilder.equal(root.get("kbUid"), request.getKbUid()));
}
if (StringUtils.hasText(request.getUserUid())) {
predicates.add(criteriaBuilder.equal(root.get("userUid"), request.getUserUid()));
}
//
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
}
}

View File

@@ -0,0 +1,21 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-03-01 09:51:18
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-01 09:51:21
* @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.article_archive;
public enum ArticleArchiveStatusEnum {
DRAFT,
PUBLISHED,
EDITING,
REJECTED
}

View File

@@ -0,0 +1,36 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-07-31 16:33:45
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-07-31 16:37:19
* @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.article_archive.event;
import org.springframework.context.ApplicationEvent;
import com.bytedesk.kbase.article_archive.ArticleArchiveEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper=false)
public class ArticleArchiveCreateEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private ArticleArchiveEntity article_archive;
public ArticleArchiveCreateEvent(Object source, ArticleArchiveEntity article_archive) {
super(source);
this.article_archive = article_archive;
}
}

View File

@@ -0,0 +1,35 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2024-07-31 16:33:59
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-07-31 16:38:22
* @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.article_archive.event;
import org.springframework.context.ApplicationEvent;
import com.bytedesk.kbase.article_archive.ArticleArchiveEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class ArticleArchiveUpdateEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private ArticleArchiveEntity article_archive;
public ArticleArchiveUpdateEvent(Object source, ArticleArchiveEntity article_archive) {
super(source);
this.article_archive = article_archive;
}
}

View File

@@ -0,0 +1,8 @@
/**
* ByteDesk 文章管理包
* 提供文章的CRUD、搜索等功能
*/
@NonNullApi
package com.bytedesk.kbase.article_archive;
import org.springframework.lang.NonNullApi;

View File

@@ -0,0 +1,26 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2025-01-21 11:15:43
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-01-21 11:16:22
* @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.
-->
# 帮助文档
- 帮助文档
- 帮助文档分类
- 帮助文档标签
- 帮助文档搜索
- 帮助文档导出
- 帮助文档导入
- 帮助文档分享
- 帮助文档权限
- 帮助文档评论
- 帮助文档点赞
- 帮助文档收藏

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-02-25 21:13:58
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-25 21:49:35
* @LastEditTime: 2025-03-11 09:09:45
* @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.
@@ -18,6 +18,8 @@ import org.modelmapper.ModelMapper;
import com.bytedesk.core.rbac.user.UserProtobuf;
import com.bytedesk.kbase.article.ArticleEntity;
import com.bytedesk.kbase.article.ArticleResponse;
import com.bytedesk.kbase.article_archive.ArticleArchiveEntity;
import com.bytedesk.kbase.article_archive.ArticleArchiveResponse;
public class KbaseConvertUtils {
@@ -30,4 +32,10 @@ public class KbaseConvertUtils {
articleResponse.setUser(UserProtobuf.parseFrom(entity.getUser()));
return articleResponse;
}
public static ArticleArchiveResponse convertToArticleArchiveResponse(ArticleArchiveEntity entity) {
ArticleArchiveResponse articleResponse = modelMapper.map(entity, ArticleArchiveResponse.class);
articleResponse.setUser(UserProtobuf.parseFrom(entity.getUser()));
return articleResponse;
}
}