mirror of
https://gitee.com/270580156/weiyu.git
synced 2026-05-17 20:57:51 +00:00
update
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 19:56: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.core.host;
|
||||
|
||||
import com.bytedesk.core.base.BaseEntity;
|
||||
import com.bytedesk.core.constant.I18Consts;
|
||||
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;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* Host entity for content categorization and organization
|
||||
* Provides host functionality for various system entities
|
||||
*
|
||||
* Database Table: bytedesk_core_host
|
||||
* Purpose: Stores host definitions, colors, and organization settings
|
||||
*/
|
||||
@Entity
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
// @EntityListeners({HostEntityListener.class})
|
||||
@Table(name = "bytedesk_core_host")
|
||||
public class HostEntity extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Name of the host
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Description of the host
|
||||
*/
|
||||
@Builder.Default
|
||||
private String description = I18Consts.I18N_DESCRIPTION;
|
||||
|
||||
/**
|
||||
* Type of host (CUSTOMER, TICKET, ARTICLE, etc.)
|
||||
*/
|
||||
@Builder.Default
|
||||
@Column(name = "host_type")
|
||||
private String type = HostTypeEnum.CUSTOMER.name();
|
||||
|
||||
/**
|
||||
* Color theme for the host display
|
||||
*/
|
||||
@Builder.Default
|
||||
@Column(name = "host_color")
|
||||
private String color = "red";
|
||||
|
||||
/**
|
||||
* Display order of the host
|
||||
*/
|
||||
@Builder.Default
|
||||
@Column(name = "host_order")
|
||||
private Integer order = 0;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2025-02-25 09:44:18
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-06-04 15:50:06
|
||||
* @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.core.host;
|
||||
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.bytedesk.core.rbac.organization.OrganizationEntity;
|
||||
import com.bytedesk.core.rbac.organization.event.OrganizationCreateEvent;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class HostEventListener {
|
||||
|
||||
private final HostRestService hostRestService;
|
||||
|
||||
@Order(3)
|
||||
@EventListener
|
||||
public void onOrganizationCreateEvent(OrganizationCreateEvent event) {
|
||||
OrganizationEntity organization = (OrganizationEntity) event.getSource();
|
||||
String orgUid = organization.getUid();
|
||||
log.info("thread - organization created: {}", organization.getName());
|
||||
hostRestService.initHosts(orgUid);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2025-03-11 08:54:35
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-06-04 17:12: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
|
||||
*
|
||||
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host;
|
||||
|
||||
// import com.bytedesk.core.constant.I18Consts;
|
||||
|
||||
public class HostInitData {
|
||||
|
||||
/**
|
||||
* Technical Support Hosts
|
||||
* 技术支持标签
|
||||
*/
|
||||
public static final String[] TECHNICAL_SUPPORT = {
|
||||
// I18Consts.I18N_PREFIX + "thread.host.technical_support", // parent
|
||||
"技术支持", // parent
|
||||
};
|
||||
|
||||
/**
|
||||
* Service Request Hosts
|
||||
* 服务请求标签
|
||||
*/
|
||||
public static final String[] SERVICE_REQUEST = {
|
||||
// I18Consts.I18N_PREFIX + "thread.host.service_request", // parent
|
||||
"服务请求", // parent
|
||||
};
|
||||
|
||||
/**
|
||||
* Consultation Hosts
|
||||
* 咨询标签
|
||||
*/
|
||||
public static final String[] CONSULTATION = {
|
||||
// I18Consts.I18N_PREFIX + "thread.host.consultation", // parent
|
||||
"咨询", // parent
|
||||
};
|
||||
|
||||
/**
|
||||
* Complaint & Suggestion Hosts
|
||||
* 投诉与建议标签
|
||||
*/
|
||||
public static final String[] COMPLAINT_SUGGESTION = {
|
||||
// I18Consts.I18N_PREFIX + "thread.host.complaint_suggestion", // parent
|
||||
"投诉建议", // parent
|
||||
};
|
||||
|
||||
/**
|
||||
* Operation & Maintenance Hosts
|
||||
* 运维标签
|
||||
*/
|
||||
public static final String[] OPERATION_MAINTENANCE = {
|
||||
// I18Consts.I18N_PREFIX + "thread.host.operation_maintenance", // parent
|
||||
"运维", // parent
|
||||
// 其他
|
||||
// I18Consts.I18N_PREFIX + "thread.host.other",
|
||||
"其他",
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method to determine if a host is a parent host
|
||||
*
|
||||
* @param host The host key to check
|
||||
* @return true if it's a parent host
|
||||
*/
|
||||
public static boolean isParentHost(String host) {
|
||||
return !host.contains(".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get parent host key for a child host
|
||||
*
|
||||
* @param childHost The child host key
|
||||
* @return The parent host key
|
||||
*/
|
||||
public static String getParentHost(String childHost) {
|
||||
if (isParentHost(childHost)) {
|
||||
return null;
|
||||
}
|
||||
// 由于已将常量转为中文,此方法可能需要重新实现
|
||||
// 这里仅保留基本结构,具体实现需要根据新的标签体系来调整
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all hosts as a single array
|
||||
*
|
||||
* @return Array containing all hosts
|
||||
*/
|
||||
public static String[] getAllHosts() {
|
||||
int totalLength = TECHNICAL_SUPPORT.length + SERVICE_REQUEST.length +
|
||||
CONSULTATION.length + COMPLAINT_SUGGESTION.length +
|
||||
OPERATION_MAINTENANCE.length;
|
||||
|
||||
String[] allHosts = new String[totalLength];
|
||||
int index = 0;
|
||||
|
||||
System.arraycopy(TECHNICAL_SUPPORT, 0, allHosts, index, TECHNICAL_SUPPORT.length);
|
||||
index += TECHNICAL_SUPPORT.length;
|
||||
|
||||
System.arraycopy(SERVICE_REQUEST, 0, allHosts, index, SERVICE_REQUEST.length);
|
||||
index += SERVICE_REQUEST.length;
|
||||
|
||||
System.arraycopy(CONSULTATION, 0, allHosts, index, CONSULTATION.length);
|
||||
index += CONSULTATION.length;
|
||||
|
||||
System.arraycopy(COMPLAINT_SUGGESTION, 0, allHosts, index, COMPLAINT_SUGGESTION.length);
|
||||
index += COMPLAINT_SUGGESTION.length;
|
||||
|
||||
System.arraycopy(OPERATION_MAINTENANCE, 0, allHosts, index, OPERATION_MAINTENANCE.length);
|
||||
|
||||
return allHosts;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:25:55
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-06-20 12:52:47
|
||||
* @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.core.host;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface HostRepository extends JpaRepository<HostEntity, Long>, JpaSpecificationExecutor<HostEntity> {
|
||||
|
||||
Optional<HostEntity> findByUid(String uid);
|
||||
|
||||
Boolean existsByUid(String uid);
|
||||
|
||||
Optional<HostEntity> findByNameAndOrgUidAndTypeAndDeletedFalse(String name, String orgUid, String type);
|
||||
|
||||
// Boolean existsByPlatform(String platform);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:26:04
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-06-20 14:24:05
|
||||
* @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.core.host;
|
||||
|
||||
import com.bytedesk.core.base.BaseRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class HostRequest extends BaseRequest {
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
// @Builder.Default
|
||||
// private String type = HostTypeEnum.CUSTOMER.name();
|
||||
|
||||
private String color;
|
||||
|
||||
private Integer order;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:26:12
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-06-04 15:36: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.core.host;
|
||||
|
||||
|
||||
import com.bytedesk.core.base.BaseResponse;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class HostResponse extends BaseResponse {
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private String type;
|
||||
|
||||
private String color;
|
||||
|
||||
private Integer order;
|
||||
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:25:36
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 19:55:50
|
||||
* @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.core.host;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
// import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.context.annotation.Description;
|
||||
|
||||
import com.bytedesk.core.annotation.ActionAnnotation;
|
||||
import com.bytedesk.core.base.BaseRestController;
|
||||
import com.bytedesk.core.utils.JsonResult;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/host")
|
||||
@AllArgsConstructor
|
||||
@Tag(name = "Host Management", description = "Host management APIs for organizing and categorizing content with hosts")
|
||||
@Description("Host Management Controller - Content host and categorization APIs")
|
||||
public class HostRestController extends BaseRestController<HostRequest> {
|
||||
|
||||
private final HostRestService hostRestService;
|
||||
|
||||
// @PreAuthorize(RolePermissions.ROLE_ADMIN)
|
||||
@ActionAnnotation(title = "Host", action = "org query", description = "query host by org")
|
||||
@Operation(summary = "Query Hosts by Organization", description = "Retrieve hosts for the current organization")
|
||||
@Override
|
||||
public ResponseEntity<?> queryByOrg(HostRequest request) {
|
||||
|
||||
Page<HostResponse> hosts = hostRestService.queryByOrg(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(hosts));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "Host", action = "user query", description = "query host by user")
|
||||
@Operation(summary = "Query Hosts by User", description = "Retrieve hosts for the current user")
|
||||
@Override
|
||||
public ResponseEntity<?> queryByUser(HostRequest request) {
|
||||
|
||||
Page<HostResponse> hosts = hostRestService.queryByUser(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(hosts));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "Host", action = "query detail", description = "query host by uid")
|
||||
@Operation(summary = "Query Host by UID", description = "Retrieve a specific host by its unique identifier")
|
||||
@Override
|
||||
public ResponseEntity<?> queryByUid(HostRequest request) {
|
||||
|
||||
HostResponse host = hostRestService.queryByUid(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(host));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "Host", action = "create", description = "create host")
|
||||
@Operation(summary = "Create Host", description = "Create a new host")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_CREATE')")
|
||||
public ResponseEntity<?> create(HostRequest request) {
|
||||
|
||||
HostResponse host = hostRestService.create(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(host));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "Host", action = "update", description = "update host")
|
||||
@Operation(summary = "Update Host", description = "Update an existing host")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_UPDATE')")
|
||||
public ResponseEntity<?> update(HostRequest request) {
|
||||
|
||||
HostResponse host = hostRestService.update(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(host));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "Host", action = "delete", description = "delete host")
|
||||
@Operation(summary = "Delete Host", description = "Delete a host")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_DELETE')")
|
||||
public ResponseEntity<?> delete(HostRequest request) {
|
||||
|
||||
hostRestService.delete(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success());
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "Host", action = "export", description = "export host")
|
||||
@Operation(summary = "Export Hosts", description = "Export hosts to Excel format")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_EXPORT')")
|
||||
@GetMapping("/export")
|
||||
public Object export(HostRequest request, HttpServletResponse response) {
|
||||
return exportTemplate(
|
||||
request,
|
||||
response,
|
||||
hostRestService,
|
||||
HostExcel.class,
|
||||
"Host",
|
||||
"host"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:25:45
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-02 11:05: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.core.host;
|
||||
|
||||
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.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import com.bytedesk.core.base.BaseRestServiceWithExcel;
|
||||
import com.bytedesk.core.constant.BytedeskConsts;
|
||||
import com.bytedesk.core.enums.LevelEnum;
|
||||
import com.bytedesk.core.rbac.auth.AuthService;
|
||||
import com.bytedesk.core.rbac.user.UserEntity;
|
||||
import com.bytedesk.core.uid.UidUtils;
|
||||
import com.bytedesk.core.utils.Utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class HostRestService extends BaseRestServiceWithExcel<HostEntity, HostRequest, HostResponse, HostExcel> {
|
||||
|
||||
private final HostRepository hostRepository;
|
||||
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
private final UidUtils uidUtils;
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
@Override
|
||||
public Page<HostEntity> queryByOrgEntity(HostRequest request) {
|
||||
Pageable pageable = request.getPageable();
|
||||
Specification<HostEntity> spec = HostSpecification.search(request);
|
||||
return hostRepository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<HostResponse> queryByOrg(HostRequest request) {
|
||||
Page<HostEntity> page = queryByOrgEntity(request);
|
||||
return page.map(this::convertToResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<HostResponse> queryByUser(HostRequest request) {
|
||||
UserEntity user = authService.getUser();
|
||||
if (user == null) {
|
||||
throw new RuntimeException("login first");
|
||||
}
|
||||
request.setUserUid(user.getUid());
|
||||
//
|
||||
return queryByOrg(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostResponse queryByUid(HostRequest request) {
|
||||
Optional<HostEntity> optional = findByUid(request.getUid());
|
||||
if (optional.isPresent()) {
|
||||
HostEntity entity = optional.get();
|
||||
return convertToResponse(entity);
|
||||
} else {
|
||||
throw new RuntimeException("Host not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Cacheable(value = "host", key = "#uid", unless="#result==null")
|
||||
@Override
|
||||
public Optional<HostEntity> findByUid(String uid) {
|
||||
return hostRepository.findByUid(uid);
|
||||
}
|
||||
|
||||
@Cacheable(value = "host", key = "#name + '_' + #orgUid + '_' + #type", unless="#result==null")
|
||||
public Optional<HostEntity> findByNameAndOrgUidAndType(String name, String orgUid, String type) {
|
||||
return hostRepository.findByNameAndOrgUidAndTypeAndDeletedFalse(name, orgUid, type);
|
||||
}
|
||||
|
||||
public Boolean existsByUid(String uid) {
|
||||
return hostRepository.existsByUid(uid);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public HostResponse create(HostRequest request) {
|
||||
// 判断是否已经存在
|
||||
if (StringUtils.hasText(request.getUid()) && existsByUid(request.getUid())) {
|
||||
return convertToResponse(findByUid(request.getUid()).get());
|
||||
}
|
||||
// 检查name+orgUid+type是否已经存在
|
||||
if (StringUtils.hasText(request.getName()) && StringUtils.hasText(request.getOrgUid()) && StringUtils.hasText(request.getType())) {
|
||||
Optional<HostEntity> host = findByNameAndOrgUidAndType(request.getName(), request.getOrgUid(), request.getType());
|
||||
if (host.isPresent()) {
|
||||
return convertToResponse(host.get());
|
||||
}
|
||||
}
|
||||
//
|
||||
UserEntity user = authService.getUser();
|
||||
if (user != null) {
|
||||
request.setUserUid(user.getUid());
|
||||
}
|
||||
//
|
||||
HostEntity entity = modelMapper.map(request, HostEntity.class);
|
||||
if (!StringUtils.hasText(request.getUid())) {
|
||||
entity.setUid(uidUtils.getUid());
|
||||
}
|
||||
//
|
||||
HostEntity savedEntity = save(entity);
|
||||
if (savedEntity == null) {
|
||||
throw new RuntimeException("Create host failed");
|
||||
}
|
||||
return convertToResponse(savedEntity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public HostResponse update(HostRequest request) {
|
||||
Optional<HostEntity> optional = hostRepository.findByUid(request.getUid());
|
||||
if (optional.isPresent()) {
|
||||
HostEntity entity = optional.get();
|
||||
modelMapper.map(request, entity);
|
||||
//
|
||||
HostEntity savedEntity = save(entity);
|
||||
if (savedEntity == null) {
|
||||
throw new RuntimeException("Update host failed");
|
||||
}
|
||||
return convertToResponse(savedEntity);
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Host not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HostEntity doSave(HostEntity entity) {
|
||||
return hostRepository.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostEntity handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, HostEntity entity) {
|
||||
try {
|
||||
Optional<HostEntity> latest = hostRepository.findByUid(entity.getUid());
|
||||
if (latest.isPresent()) {
|
||||
HostEntity latestEntity = latest.get();
|
||||
// 合并需要保留的数据
|
||||
latestEntity.setName(entity.getName());
|
||||
// latestEntity.setOrder(entity.getOrder());
|
||||
// latestEntity.setDeleted(entity.isDeleted());
|
||||
return hostRepository.save(latestEntity);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("无法处理乐观锁冲突: {}", ex.getMessage(), ex);
|
||||
throw new RuntimeException("无法处理乐观锁冲突: " + ex.getMessage(), ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void deleteByUid(String uid) {
|
||||
Optional<HostEntity> optional = hostRepository.findByUid(uid);
|
||||
if (optional.isPresent()) {
|
||||
optional.get().setDeleted(true);
|
||||
save(optional.get());
|
||||
// hostRepository.delete(optional.get());
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Host not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(HostRequest request) {
|
||||
deleteByUid(request.getUid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostResponse convertToResponse(HostEntity entity) {
|
||||
return modelMapper.map(entity, HostResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostExcel convertToExcel(HostEntity entity) {
|
||||
return modelMapper.map(entity, HostExcel.class);
|
||||
}
|
||||
|
||||
public void initHosts(String orgUid) {
|
||||
// log.info("initThreadHost");
|
||||
for (String host : HostInitData.getAllHosts()) {
|
||||
HostRequest hostRequest = HostRequest.builder()
|
||||
.uid(Utils.formatUid(orgUid, host))
|
||||
.name(host)
|
||||
.order(0)
|
||||
.type(HostTypeEnum.THREAD.name())
|
||||
.level(LevelEnum.ORGANIZATION.name())
|
||||
.platform(BytedeskConsts.PLATFORM_BYTEDESK)
|
||||
.orgUid(orgUid)
|
||||
.build();
|
||||
create(hostRequest);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 20:36:13
|
||||
* @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.core.server;
|
||||
|
||||
import com.bytedesk.core.base.BaseEntity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Server entity for monitoring server resources and status
|
||||
* Provides server monitoring functionality for system administration
|
||||
*
|
||||
* Database Table: bytedesk_core_server
|
||||
* Purpose: Stores server information, resource usage, and monitoring data
|
||||
*/
|
||||
@Entity
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table(name = "bytedesk_core_server")
|
||||
public class ServerEntity extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Server hostname or identifier
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private String serverName;
|
||||
|
||||
/**
|
||||
* Server IP address
|
||||
*/
|
||||
private String serverIp;
|
||||
|
||||
/**
|
||||
* Server type (APPLICATION, DATABASE, CACHE, etc.)
|
||||
*/
|
||||
@Builder.Default
|
||||
@Column(name = "server_type")
|
||||
private String type = ServerTypeEnum.APPLICATION.name();
|
||||
|
||||
/**
|
||||
* Server status (ONLINE, OFFLINE, MAINTENANCE, etc.)
|
||||
*/
|
||||
@Builder.Default
|
||||
@Column(name = "server_status")
|
||||
private String status = ServerStatusEnum.ONLINE.name();
|
||||
|
||||
/**
|
||||
* Server description
|
||||
*/
|
||||
@Column(name = "server_description")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* CPU usage percentage (0-100)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double cpuUsage = 0.0;
|
||||
|
||||
/**
|
||||
* Memory usage percentage (0-100)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double memoryUsage = 0.0;
|
||||
|
||||
/**
|
||||
* Total memory in MB
|
||||
*/
|
||||
private Long totalMemoryMb;
|
||||
|
||||
/**
|
||||
* Used memory in MB
|
||||
*/
|
||||
private Long usedMemoryMb;
|
||||
|
||||
/**
|
||||
* Disk usage percentage (0-100)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double diskUsage = 0.0;
|
||||
|
||||
/**
|
||||
* Total disk space in GB
|
||||
*/
|
||||
private Long totalDiskGb;
|
||||
|
||||
/**
|
||||
* Used disk space in GB
|
||||
*/
|
||||
private Long usedDiskGb;
|
||||
|
||||
/**
|
||||
* Server uptime in seconds
|
||||
*/
|
||||
private Long uptimeSeconds;
|
||||
|
||||
/**
|
||||
* Server start time
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
|
||||
/**
|
||||
* Last heartbeat time
|
||||
*/
|
||||
private LocalDateTime lastHeartbeat;
|
||||
|
||||
/**
|
||||
* Server port (if applicable)
|
||||
*/
|
||||
private Integer serverPort;
|
||||
|
||||
/**
|
||||
* Operating system information
|
||||
*/
|
||||
private String osInfo;
|
||||
|
||||
/**
|
||||
* Java version (if applicable)
|
||||
*/
|
||||
private String javaVersion;
|
||||
|
||||
/**
|
||||
* Application version
|
||||
*/
|
||||
private String appVersion;
|
||||
|
||||
/**
|
||||
* Environment (DEV, TEST, PROD, etc.)
|
||||
*/
|
||||
@Builder.Default
|
||||
private String environment = "DEV";
|
||||
|
||||
/**
|
||||
* Server location or data center
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* Monitoring enabled flag
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean monitoringEnabled = true;
|
||||
|
||||
/**
|
||||
* Alert threshold for CPU usage
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double cpuAlertThreshold = 80.0;
|
||||
|
||||
/**
|
||||
* Alert threshold for memory usage
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double memoryAlertThreshold = 80.0;
|
||||
|
||||
/**
|
||||
* Alert threshold for disk usage
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double diskAlertThreshold = 85.0;
|
||||
}
|
||||
@@ -11,14 +11,14 @@
|
||||
*
|
||||
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host;
|
||||
package com.bytedesk.core.server;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.SerializationUtils;
|
||||
|
||||
import com.bytedesk.core.config.BytedeskEventPublisher;
|
||||
import com.bytedesk.core.host.event.HostCreateEvent;
|
||||
import com.bytedesk.core.host.event.HostUpdateEvent;
|
||||
import com.bytedesk.core.server.event.ServerCreateEvent;
|
||||
import com.bytedesk.core.server.event.ServerUpdateEvent;
|
||||
import com.bytedesk.core.utils.ApplicationContextHolder;
|
||||
|
||||
import jakarta.persistence.PostPersist;
|
||||
@@ -28,24 +28,24 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class HostEntityListener {
|
||||
public class ServerEntityListener {
|
||||
|
||||
@PostPersist
|
||||
public void onPostPersist(HostEntity host) {
|
||||
log.info("onPostPersist: {}", host);
|
||||
HostEntity cloneHost = SerializationUtils.clone(host);
|
||||
public void onPostPersist(ServerEntity server) {
|
||||
log.info("onPostPersist: {}", server);
|
||||
ServerEntity cloneServer = SerializationUtils.clone(server);
|
||||
//
|
||||
BytedeskEventPublisher bytedeskEventPublisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class);
|
||||
bytedeskEventPublisher.publishEvent(new HostCreateEvent(cloneHost));
|
||||
bytedeskEventPublisher.publishEvent(new ServerCreateEvent(cloneServer));
|
||||
}
|
||||
|
||||
@PostUpdate
|
||||
public void onPostUpdate(HostEntity host) {
|
||||
log.info("onPostUpdate: {}", host);
|
||||
HostEntity cloneHost = SerializationUtils.clone(host);
|
||||
public void onPostUpdate(ServerEntity server) {
|
||||
log.info("onPostUpdate: {}", server);
|
||||
ServerEntity cloneServer = SerializationUtils.clone(server);
|
||||
//
|
||||
BytedeskEventPublisher bytedeskEventPublisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class);
|
||||
bytedeskEventPublisher.publishEvent(new HostUpdateEvent(cloneHost));
|
||||
bytedeskEventPublisher.publishEvent(new ServerUpdateEvent(cloneServer));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +1,28 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-07-23 17:02:46
|
||||
* @Date: 2025-02-25 09:44:18
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-03-11 08:57:11
|
||||
* @LastEditTime: 2025-07-24 20:45:51
|
||||
* @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.
|
||||
* 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.
|
||||
*
|
||||
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host;
|
||||
package com.bytedesk.core.server;
|
||||
|
||||
public enum HostTypeEnum {
|
||||
THREAD,
|
||||
CUSTOMER,
|
||||
TICKET
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class ServerEventListener {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-08-01 06:18:10
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-04 18:00:51
|
||||
* @LastEditTime: 2025-07-24 20:37: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.
|
||||
@@ -11,12 +11,9 @@
|
||||
* 联系:270580156@qq.com
|
||||
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
package com.bytedesk.core.server;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.format.DateTimeFormat;
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
|
||||
import lombok.Data;
|
||||
@@ -25,23 +22,14 @@ import lombok.Data;
|
||||
* https://github.com/alibaba/easyexcel
|
||||
*/
|
||||
@Data
|
||||
public class HostExcel {
|
||||
public class ServerExcel {
|
||||
|
||||
@ExcelProperty(index = 0, value = "标签名称")
|
||||
@ExcelProperty(index = 0, value = "服务器名称")
|
||||
@ColumnWidth(20)
|
||||
private String name;
|
||||
private String serverName;
|
||||
|
||||
@ExcelProperty(index = 1, value = "类型")
|
||||
@ExcelProperty(index = 1, value = "服务器IP")
|
||||
@ColumnWidth(20)
|
||||
private String type;
|
||||
|
||||
@ExcelProperty(index = 2, value = "颜色")
|
||||
@ColumnWidth(20)
|
||||
private String color;
|
||||
|
||||
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
|
||||
@ExcelProperty(value = "创建时间", converter = com.bytedesk.core.converter.ZonedDateTimeConverter.class)
|
||||
@ColumnWidth(25)
|
||||
private ZonedDateTime createdAt;
|
||||
private String serverIp;
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-11-06 21:43:58
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-06-04 17:09:29
|
||||
* @LastEditTime: 2025-07-24 20:36: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.
|
||||
@@ -11,32 +11,25 @@
|
||||
* 联系:270580156@qq.com
|
||||
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host;
|
||||
package com.bytedesk.core.server;
|
||||
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.bytedesk.core.constant.BytedeskConsts;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class HostInitializer implements SmartInitializingSingleton {
|
||||
|
||||
private final HostRestService hostRestService;
|
||||
public class ServerInitializer implements SmartInitializingSingleton {
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
initPermissions();
|
||||
// 创建默认的工单分类
|
||||
String orgUid = BytedeskConsts.DEFAULT_ORGANIZATION_UID;
|
||||
hostRestService.initHosts(orgUid);
|
||||
}
|
||||
|
||||
private void initPermissions() {
|
||||
// for (PermissionEnum permission : PermissionEnum.values()) {
|
||||
// String permissionValue = HostPermissions.ARTICLE_PREFIX + permission.name();
|
||||
// String permissionValue = ServerPermissions.ARTICLE_PREFIX + permission.name();
|
||||
// authorityService.createForPlatform(permissionValue);
|
||||
// }
|
||||
}
|
||||
@@ -11,10 +11,10 @@
|
||||
* 联系:270580156@qq.com
|
||||
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host;
|
||||
package com.bytedesk.core.server;
|
||||
|
||||
import com.bytedesk.core.base.BasePermissions;
|
||||
|
||||
public class HostPermissions extends BasePermissions {
|
||||
public class ServerPermissions extends BasePermissions {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 19:56: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.core.server;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Repository for ServerEntity
|
||||
* Provides database operations for server monitoring data
|
||||
*/
|
||||
@Repository
|
||||
public interface ServerRepository extends JpaRepository<ServerEntity, Long>, JpaSpecificationExecutor<ServerEntity> {
|
||||
|
||||
/**
|
||||
* Find server by UID
|
||||
* @param uid server UID
|
||||
* @return Optional<ServerEntity>
|
||||
*/
|
||||
Optional<ServerEntity> findByUid(String uid);
|
||||
|
||||
/**
|
||||
* Find server by server name and organization UID
|
||||
* @param serverName server name
|
||||
* @param orgUid organization UID
|
||||
* @return Optional<ServerEntity>
|
||||
*/
|
||||
Optional<ServerEntity> findByServerNameAndOrgUidAndDeletedFalse(String serverName, String orgUid);
|
||||
|
||||
/**
|
||||
* Find servers by organization UID
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
List<ServerEntity> findByOrgUidAndDeletedFalseOrderByCreatedAtDesc(String orgUid);
|
||||
|
||||
/**
|
||||
* Find servers by type
|
||||
* @param type server type
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
List<ServerEntity> findByTypeAndOrgUidAndDeletedFalse(String type, String orgUid);
|
||||
|
||||
/**
|
||||
* Find servers by status
|
||||
* @param status server status
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
List<ServerEntity> findByStatusAndOrgUidAndDeletedFalse(String status, String orgUid);
|
||||
|
||||
/**
|
||||
* Find servers with high resource usage
|
||||
* @param orgUid organization UID
|
||||
* @param cpuThreshold CPU usage threshold
|
||||
* @param memoryThreshold memory usage threshold
|
||||
* @param diskThreshold disk usage threshold
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
@Query("SELECT s FROM ServerEntity s WHERE s.orgUid = :orgUid AND s.deleted = false " +
|
||||
"AND (s.cpuUsage >= :cpuThreshold OR s.memoryUsage >= :memoryThreshold OR s.diskUsage >= :diskThreshold)")
|
||||
List<ServerEntity> findServersWithHighUsage(@Param("orgUid") String orgUid,
|
||||
@Param("cpuThreshold") Double cpuThreshold,
|
||||
@Param("memoryThreshold") Double memoryThreshold,
|
||||
@Param("diskThreshold") Double diskThreshold);
|
||||
|
||||
/**
|
||||
* Find servers that haven't sent heartbeat recently
|
||||
* @param orgUid organization UID
|
||||
* @param cutoffTime cutoff time for heartbeat
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
@Query("SELECT s FROM ServerEntity s WHERE s.orgUid = :orgUid AND s.deleted = false " +
|
||||
"AND (s.lastHeartbeat IS NULL OR s.lastHeartbeat < :cutoffTime)")
|
||||
List<ServerEntity> findServersWithoutRecentHeartbeat(@Param("orgUid") String orgUid,
|
||||
@Param("cutoffTime") LocalDateTime cutoffTime);
|
||||
|
||||
/**
|
||||
* Count servers by status
|
||||
* @param status server status
|
||||
* @param orgUid organization UID
|
||||
* @return count
|
||||
*/
|
||||
long countByStatusAndOrgUidAndDeletedFalse(String status, String orgUid);
|
||||
|
||||
/**
|
||||
* Count servers by type
|
||||
* @param type server type
|
||||
* @param orgUid organization UID
|
||||
* @return count
|
||||
*/
|
||||
long countByTypeAndOrgUidAndDeletedFalse(String type, String orgUid);
|
||||
|
||||
/**
|
||||
* Find servers by environment
|
||||
* @param environment environment (DEV, TEST, PROD, etc.)
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
List<ServerEntity> findByEnvironmentAndOrgUidAndDeletedFalse(String environment, String orgUid);
|
||||
|
||||
/**
|
||||
* Find servers by location
|
||||
* @param location server location
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
List<ServerEntity> findByLocationAndOrgUidAndDeletedFalse(String location, String orgUid);
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 20:36:13
|
||||
* @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.core.server;
|
||||
|
||||
import com.bytedesk.core.base.BaseRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Server request DTO
|
||||
* Used for server monitoring operations
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ServerRequest extends BaseRequest {
|
||||
|
||||
/**
|
||||
* Server hostname or identifier
|
||||
*/
|
||||
private String serverName;
|
||||
|
||||
/**
|
||||
* Server IP address
|
||||
*/
|
||||
private String serverIp;
|
||||
|
||||
/**
|
||||
* Server type (APPLICATION, DATABASE, CACHE, etc.)
|
||||
*/
|
||||
@Builder.Default
|
||||
private String serverType = ServerTypeEnum.APPLICATION.name();
|
||||
|
||||
/**
|
||||
* Server status (ONLINE, OFFLINE, MAINTENANCE, etc.)
|
||||
*/
|
||||
@Builder.Default
|
||||
private String serverStatus = ServerStatusEnum.ONLINE.name();
|
||||
|
||||
/**
|
||||
* Server description
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* CPU usage percentage (0-100)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double cpuUsage = 0.0;
|
||||
|
||||
/**
|
||||
* Memory usage percentage (0-100)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double memoryUsage = 0.0;
|
||||
|
||||
/**
|
||||
* Total memory in MB
|
||||
*/
|
||||
private Long totalMemoryMb;
|
||||
|
||||
/**
|
||||
* Used memory in MB
|
||||
*/
|
||||
private Long usedMemoryMb;
|
||||
|
||||
/**
|
||||
* Disk usage percentage (0-100)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double diskUsage = 0.0;
|
||||
|
||||
/**
|
||||
* Total disk space in GB
|
||||
*/
|
||||
private Long totalDiskGb;
|
||||
|
||||
/**
|
||||
* Used disk space in GB
|
||||
*/
|
||||
private Long usedDiskGb;
|
||||
|
||||
/**
|
||||
* Server uptime in seconds
|
||||
*/
|
||||
private Long uptimeSeconds;
|
||||
|
||||
/**
|
||||
* Server start time
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
|
||||
/**
|
||||
* Last heartbeat time
|
||||
*/
|
||||
private LocalDateTime lastHeartbeat;
|
||||
|
||||
/**
|
||||
* Server port (if applicable)
|
||||
*/
|
||||
private Integer serverPort;
|
||||
|
||||
/**
|
||||
* Operating system information
|
||||
*/
|
||||
private String osInfo;
|
||||
|
||||
/**
|
||||
* Java version (if applicable)
|
||||
*/
|
||||
private String javaVersion;
|
||||
|
||||
/**
|
||||
* Application version
|
||||
*/
|
||||
private String appVersion;
|
||||
|
||||
/**
|
||||
* Environment (DEV, TEST, PROD, etc.)
|
||||
*/
|
||||
@Builder.Default
|
||||
private String environment = "DEV";
|
||||
|
||||
/**
|
||||
* Server location or data center
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* Monitoring enabled flag
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean monitoringEnabled = true;
|
||||
|
||||
/**
|
||||
* Alert threshold for CPU usage
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double cpuAlertThreshold = 80.0;
|
||||
|
||||
/**
|
||||
* Alert threshold for memory usage
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double memoryAlertThreshold = 80.0;
|
||||
|
||||
/**
|
||||
* Alert threshold for disk usage
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double diskAlertThreshold = 85.0;
|
||||
|
||||
/**
|
||||
* Search filters
|
||||
*/
|
||||
private String serverTypeFilter;
|
||||
private String serverStatusFilter;
|
||||
private String environmentFilter;
|
||||
private String locationFilter;
|
||||
private Boolean highUsageFilter; // true to show only servers with high resource usage
|
||||
private Boolean offlineFilter; // true to show only offline servers
|
||||
private Integer heartbeatThresholdMinutes; // minutes threshold for heartbeat check
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 20:48:23
|
||||
* @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.core.server;
|
||||
|
||||
import com.bytedesk.core.base.BaseResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Server response DTO
|
||||
* Used for server monitoring operations
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ServerResponse extends BaseResponse {
|
||||
|
||||
/**
|
||||
* Server hostname or identifier
|
||||
*/
|
||||
private String serverName;
|
||||
|
||||
/**
|
||||
* Server IP address
|
||||
*/
|
||||
private String serverIp;
|
||||
|
||||
/**
|
||||
* Server type (APPLICATION, DATABASE, CACHE, etc.)
|
||||
*/
|
||||
private String serverType;
|
||||
|
||||
/**
|
||||
* Server type display name
|
||||
*/
|
||||
private String serverTypeDisplay;
|
||||
|
||||
/**
|
||||
* Server status (ONLINE, OFFLINE, MAINTENANCE, etc.)
|
||||
*/
|
||||
private String serverStatus;
|
||||
|
||||
/**
|
||||
* Server status display name
|
||||
*/
|
||||
private String serverStatusDisplay;
|
||||
|
||||
/**
|
||||
* Server description
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* CPU usage percentage (0-100)
|
||||
*/
|
||||
private Double cpuUsage;
|
||||
|
||||
/**
|
||||
* Memory usage percentage (0-100)
|
||||
*/
|
||||
private Double memoryUsage;
|
||||
|
||||
/**
|
||||
* Total memory in MB
|
||||
*/
|
||||
private Long totalMemoryMb;
|
||||
|
||||
/**
|
||||
* Used memory in MB
|
||||
*/
|
||||
private Long usedMemoryMb;
|
||||
|
||||
/**
|
||||
* Disk usage percentage (0-100)
|
||||
*/
|
||||
private Double diskUsage;
|
||||
|
||||
/**
|
||||
* Total disk space in GB
|
||||
*/
|
||||
private Long totalDiskGb;
|
||||
|
||||
/**
|
||||
* Used disk space in GB
|
||||
*/
|
||||
private Long usedDiskGb;
|
||||
|
||||
/**
|
||||
* Server uptime in seconds
|
||||
*/
|
||||
private Long uptimeSeconds;
|
||||
|
||||
/**
|
||||
* Server uptime formatted string (e.g., "2 days 3 hours 45 minutes")
|
||||
*/
|
||||
// private String uptimeFormatted;
|
||||
|
||||
/**
|
||||
* Server start time
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
|
||||
/**
|
||||
* Server start time formatted string
|
||||
*/
|
||||
private String startTimeFormatted;
|
||||
|
||||
/**
|
||||
* Last heartbeat time
|
||||
*/
|
||||
private LocalDateTime lastHeartbeat;
|
||||
|
||||
/**
|
||||
* Last heartbeat time formatted string
|
||||
*/
|
||||
private String lastHeartbeatFormatted;
|
||||
|
||||
/**
|
||||
* Server port (if applicable)
|
||||
*/
|
||||
private Integer serverPort;
|
||||
|
||||
/**
|
||||
* Operating system information
|
||||
*/
|
||||
private String osInfo;
|
||||
|
||||
/**
|
||||
* Java version (if applicable)
|
||||
*/
|
||||
private String javaVersion;
|
||||
|
||||
/**
|
||||
* Application version
|
||||
*/
|
||||
private String appVersion;
|
||||
|
||||
/**
|
||||
* Environment (DEV, TEST, PROD, etc.)
|
||||
*/
|
||||
private String environment;
|
||||
|
||||
/**
|
||||
* Server location or data center
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* Monitoring enabled flag
|
||||
*/
|
||||
private Boolean monitoringEnabled;
|
||||
|
||||
/**
|
||||
* Alert threshold for CPU usage
|
||||
*/
|
||||
private Double cpuAlertThreshold;
|
||||
|
||||
/**
|
||||
* Alert threshold for memory usage
|
||||
*/
|
||||
private Double memoryAlertThreshold;
|
||||
|
||||
/**
|
||||
* Alert threshold for disk usage
|
||||
*/
|
||||
private Double diskAlertThreshold;
|
||||
|
||||
/**
|
||||
* Health status indicators
|
||||
*/
|
||||
private Boolean isHealthy;
|
||||
private Boolean isOperational;
|
||||
private Boolean hasHighCpuUsage;
|
||||
private Boolean hasHighMemoryUsage;
|
||||
private Boolean hasHighDiskUsage;
|
||||
private Boolean hasRecentHeartbeat;
|
||||
|
||||
/**
|
||||
* Status color for UI display
|
||||
*/
|
||||
// private String statusColor;
|
||||
|
||||
/**
|
||||
* Status icon for UI display
|
||||
*/
|
||||
// private String statusIcon;
|
||||
|
||||
/**
|
||||
* Get formatted uptime string
|
||||
* @return formatted uptime string
|
||||
*/
|
||||
public String getUptimeFormatted() {
|
||||
if (uptimeSeconds == null || uptimeSeconds <= 0) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
long days = uptimeSeconds / 86400;
|
||||
long hours = (uptimeSeconds % 86400) / 3600;
|
||||
long minutes = (uptimeSeconds % 3600) / 60;
|
||||
|
||||
if (days > 0) {
|
||||
return String.format("%d days %d hours %d minutes", days, hours, minutes);
|
||||
} else if (hours > 0) {
|
||||
return String.format("%d hours %d minutes", hours, minutes);
|
||||
} else {
|
||||
return String.format("%d minutes", minutes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status color for UI display
|
||||
* @return status color
|
||||
*/
|
||||
public String getStatusColor() {
|
||||
if (serverStatus == null) {
|
||||
return "gray";
|
||||
}
|
||||
|
||||
switch (serverStatus) {
|
||||
case "ONLINE":
|
||||
return "green";
|
||||
case "OFFLINE":
|
||||
return "red";
|
||||
case "MAINTENANCE":
|
||||
return "orange";
|
||||
case "WARNING":
|
||||
return "yellow";
|
||||
case "OVERLOADED":
|
||||
return "red";
|
||||
case "ERROR":
|
||||
return "red";
|
||||
case "STARTING":
|
||||
case "STOPPING":
|
||||
case "RESTARTING":
|
||||
return "blue";
|
||||
default:
|
||||
return "gray";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status icon for UI display
|
||||
* @return status icon
|
||||
*/
|
||||
public String getStatusIcon() {
|
||||
if (serverStatus == null) {
|
||||
return "question-circle";
|
||||
}
|
||||
|
||||
switch (serverStatus) {
|
||||
case "ONLINE":
|
||||
return "check-circle";
|
||||
case "OFFLINE":
|
||||
return "times-circle";
|
||||
case "MAINTENANCE":
|
||||
return "wrench";
|
||||
case "WARNING":
|
||||
return "exclamation-triangle";
|
||||
case "OVERLOADED":
|
||||
return "exclamation-circle";
|
||||
case "ERROR":
|
||||
return "times-circle";
|
||||
case "STARTING":
|
||||
return "play-circle";
|
||||
case "STOPPING":
|
||||
return "stop-circle";
|
||||
case "RESTARTING":
|
||||
return "sync";
|
||||
default:
|
||||
return "question-circle";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if server has high resource usage
|
||||
* @return true if any resource usage is high
|
||||
*/
|
||||
public Boolean getHasHighResourceUsage() {
|
||||
return (cpuUsage != null && cpuUsage > 80) ||
|
||||
(memoryUsage != null && memoryUsage > 80) ||
|
||||
(diskUsage != null && diskUsage > 85);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:25:36
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 20:43: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.core.server;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
// import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.context.annotation.Description;
|
||||
|
||||
import com.bytedesk.core.annotation.ActionAnnotation;
|
||||
import com.bytedesk.core.base.BaseRestController;
|
||||
import com.bytedesk.core.utils.JsonResult;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/server")
|
||||
@AllArgsConstructor
|
||||
@Tag(name = "Server Management", description = "Server management APIs for organizing and categorizing content with servers")
|
||||
@Description("Server Management Controller - Content server and categorization APIs")
|
||||
public class ServerRestController extends BaseRestController<ServerRequest> {
|
||||
|
||||
private final ServerRestService serverRestService;
|
||||
|
||||
// @PreAuthorize(RolePermissions.ROLE_ADMIN)
|
||||
@ActionAnnotation(title = "标签", action = "组织查询", description = "query server by org")
|
||||
@Operation(summary = "Query Servers by Organization", description = "Retrieve servers for the current organization")
|
||||
@Override
|
||||
public ResponseEntity<?> queryByOrg(ServerRequest request) {
|
||||
|
||||
Page<ServerResponse> servers = serverRestService.queryByOrg(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(servers));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "标签", action = "用户查询", description = "query server by user")
|
||||
@Operation(summary = "Query Servers by User", description = "Retrieve servers for the current user")
|
||||
@Override
|
||||
public ResponseEntity<?> queryByUser(ServerRequest request) {
|
||||
|
||||
Page<ServerResponse> servers = serverRestService.queryByUser(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(servers));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "标签", action = "查询详情", description = "query server by uid")
|
||||
@Operation(summary = "Query Server by UID", description = "Retrieve a specific server by its unique identifier")
|
||||
@Override
|
||||
public ResponseEntity<?> queryByUid(ServerRequest request) {
|
||||
|
||||
ServerResponse server = serverRestService.queryByUid(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(server));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "标签", action = "新建", description = "create server")
|
||||
@Operation(summary = "Create Server", description = "Create a new server")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_CREATE')")
|
||||
public ResponseEntity<?> create(ServerRequest request) {
|
||||
|
||||
ServerResponse server = serverRestService.create(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(server));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "标签", action = "更新", description = "update server")
|
||||
@Operation(summary = "Update Server", description = "Update an existing server")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_UPDATE')")
|
||||
public ResponseEntity<?> update(ServerRequest request) {
|
||||
|
||||
ServerResponse server = serverRestService.update(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success(server));
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "标签", action = "删除", description = "delete server")
|
||||
@Operation(summary = "Delete Server", description = "Delete a server")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_DELETE')")
|
||||
public ResponseEntity<?> delete(ServerRequest request) {
|
||||
|
||||
serverRestService.delete(request);
|
||||
|
||||
return ResponseEntity.ok(JsonResult.success());
|
||||
}
|
||||
|
||||
@ActionAnnotation(title = "标签", action = "导出", description = "export server")
|
||||
@Operation(summary = "Export Servers", description = "Export servers to Excel format")
|
||||
@Override
|
||||
// @PreAuthorize("hasAuthority('TAG_EXPORT')")
|
||||
@GetMapping("/export")
|
||||
public Object export(ServerRequest request, HttpServletResponse response) {
|
||||
return exportTemplate(
|
||||
request,
|
||||
response,
|
||||
serverRestService,
|
||||
ServerExcel.class,
|
||||
"标签",
|
||||
"server"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 20:36:13
|
||||
* @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.core.server;
|
||||
|
||||
import com.bytedesk.core.base.BaseRestService;
|
||||
import com.bytedesk.core.uid.UidUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.orm.ObjectOptimisticLockingFailureException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* REST service for server monitoring operations
|
||||
* Provides CRUD operations and business logic for server management
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class ServerRestService extends BaseRestService<ServerEntity, ServerRequest, ServerResponse> {
|
||||
|
||||
private final ServerRepository serverRepository;
|
||||
private final ServerService serverService;
|
||||
private final ModelMapper modelMapper;
|
||||
private final UidUtils uidUtils;
|
||||
|
||||
// Helper method for internal use
|
||||
private Page<ServerEntity> queryByOrgEntity(ServerRequest request) {
|
||||
Pageable pageable = request.getPageable();
|
||||
// TODO: Implement ServerSpecification.search(request)
|
||||
return serverRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ServerResponse> queryByOrg(ServerRequest request) {
|
||||
Page<ServerEntity> page = queryByOrgEntity(request);
|
||||
return page.map(this::convertToResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ServerResponse> queryByUser(ServerRequest request) {
|
||||
// For server monitoring, user query is same as org query
|
||||
return queryByOrg(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerResponse queryByUid(ServerRequest request) {
|
||||
Optional<ServerEntity> optional = findByUid(request.getUid());
|
||||
if (optional.isPresent()) {
|
||||
ServerEntity entity = optional.get();
|
||||
return convertToResponse(entity);
|
||||
} else {
|
||||
throw new RuntimeException("Server not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Cacheable(value = "server", key = "#uid", unless="#result==null")
|
||||
@Override
|
||||
public Optional<ServerEntity> findByUid(String uid) {
|
||||
return serverRepository.findByUid(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerResponse create(ServerRequest request) {
|
||||
ServerEntity entity = convertToEntity(request);
|
||||
entity.setUid(uidUtils.getUid());
|
||||
entity.setCreatedAt(ZonedDateTime.now());
|
||||
entity.setUpdatedAt(ZonedDateTime.now());
|
||||
|
||||
ServerEntity savedEntity = serverService.createServer(entity);
|
||||
return convertToResponse(savedEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerResponse update(ServerRequest request) {
|
||||
Optional<ServerEntity> optional = serverRepository.findByUid(request.getUid());
|
||||
if (optional.isPresent()) {
|
||||
ServerEntity existingEntity = optional.get();
|
||||
updateEntityFromRequest(existingEntity, request);
|
||||
existingEntity.setUpdatedAt(ZonedDateTime.now());
|
||||
|
||||
ServerEntity savedEntity = serverService.updateServer(existingEntity);
|
||||
return convertToResponse(savedEntity);
|
||||
} else {
|
||||
throw new RuntimeException("Server not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByUid(String uid) {
|
||||
serverService.deleteServer(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(ServerRequest request) {
|
||||
deleteByUid(request.getUid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerResponse convertToResponse(ServerEntity entity) {
|
||||
ServerResponse response = modelMapper.map(entity, ServerResponse.class);
|
||||
|
||||
// Set display names
|
||||
if (entity.getType() != null) {
|
||||
try {
|
||||
ServerTypeEnum typeEnum = ServerTypeEnum.valueOf(entity.getType());
|
||||
response.setServerTypeDisplay(typeEnum.getChineseName());
|
||||
} catch (IllegalArgumentException e) {
|
||||
response.setServerTypeDisplay(entity.getType());
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.getStatus() != null) {
|
||||
try {
|
||||
ServerStatusEnum statusEnum = ServerStatusEnum.valueOf(entity.getStatus());
|
||||
response.setServerStatusDisplay(statusEnum.getChineseName());
|
||||
response.setIsHealthy(statusEnum.isHealthy());
|
||||
response.setIsOperational(statusEnum.isOperational());
|
||||
} catch (IllegalArgumentException e) {
|
||||
response.setServerStatusDisplay(entity.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
// Set health indicators
|
||||
response.setHasHighCpuUsage(entity.getCpuUsage() != null && entity.getCpuUsage() > 80);
|
||||
response.setHasHighMemoryUsage(entity.getMemoryUsage() != null && entity.getMemoryUsage() > 80);
|
||||
response.setHasHighDiskUsage(entity.getDiskUsage() != null && entity.getDiskUsage() > 85);
|
||||
response.setHasRecentHeartbeat(entity.getLastHeartbeat() != null &&
|
||||
entity.getLastHeartbeat().isAfter(java.time.LocalDateTime.now().minusMinutes(5)));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getUidFromRequest(ServerRequest request) {
|
||||
return request.getUid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerEntity doSave(ServerEntity entity) {
|
||||
return serverRepository.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerEntity handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, ServerEntity entity) {
|
||||
log.warn("Optimistic locking failure for server: {}", entity.getUid());
|
||||
return entity;
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private ServerEntity convertToEntity(ServerRequest request) {
|
||||
ServerEntity entity = new ServerEntity();
|
||||
entity.setServerName(request.getServerName());
|
||||
entity.setServerIp(request.getServerIp());
|
||||
entity.setType(request.getServerType());
|
||||
entity.setStatus(request.getServerStatus());
|
||||
entity.setDescription(request.getDescription());
|
||||
entity.setCpuUsage(request.getCpuUsage());
|
||||
entity.setMemoryUsage(request.getMemoryUsage());
|
||||
entity.setTotalMemoryMb(request.getTotalMemoryMb());
|
||||
entity.setUsedMemoryMb(request.getUsedMemoryMb());
|
||||
entity.setDiskUsage(request.getDiskUsage());
|
||||
entity.setTotalDiskGb(request.getTotalDiskGb());
|
||||
entity.setUsedDiskGb(request.getUsedDiskGb());
|
||||
entity.setUptimeSeconds(request.getUptimeSeconds());
|
||||
entity.setStartTime(request.getStartTime());
|
||||
entity.setLastHeartbeat(request.getLastHeartbeat());
|
||||
entity.setServerPort(request.getServerPort());
|
||||
entity.setOsInfo(request.getOsInfo());
|
||||
entity.setJavaVersion(request.getJavaVersion());
|
||||
entity.setAppVersion(request.getAppVersion());
|
||||
entity.setEnvironment(request.getEnvironment());
|
||||
entity.setLocation(request.getLocation());
|
||||
entity.setMonitoringEnabled(request.getMonitoringEnabled());
|
||||
entity.setCpuAlertThreshold(request.getCpuAlertThreshold());
|
||||
entity.setMemoryAlertThreshold(request.getMemoryAlertThreshold());
|
||||
entity.setDiskAlertThreshold(request.getDiskAlertThreshold());
|
||||
entity.setOrgUid(request.getOrgUid());
|
||||
entity.setDeleted(false);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void updateEntityFromRequest(ServerEntity entity, ServerRequest request) {
|
||||
if (request.getServerName() != null) {
|
||||
entity.setServerName(request.getServerName());
|
||||
}
|
||||
if (request.getServerType() != null) {
|
||||
entity.setType(request.getServerType());
|
||||
}
|
||||
if (request.getServerStatus() != null) {
|
||||
entity.setStatus(request.getServerStatus());
|
||||
}
|
||||
if (request.getDescription() != null) {
|
||||
entity.setDescription(request.getDescription());
|
||||
}
|
||||
if (request.getCpuUsage() != null) {
|
||||
entity.setCpuUsage(request.getCpuUsage());
|
||||
}
|
||||
if (request.getMemoryUsage() != null) {
|
||||
entity.setMemoryUsage(request.getMemoryUsage());
|
||||
}
|
||||
if (request.getDiskUsage() != null) {
|
||||
entity.setDiskUsage(request.getDiskUsage());
|
||||
}
|
||||
if (request.getEnvironment() != null) {
|
||||
entity.setEnvironment(request.getEnvironment());
|
||||
}
|
||||
if (request.getLocation() != null) {
|
||||
entity.setLocation(request.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 19:56: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.core.server;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Service for server monitoring and management
|
||||
* Provides business logic for server monitoring operations
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class ServerService {
|
||||
|
||||
private final ServerRepository serverRepository;
|
||||
|
||||
/**
|
||||
* Create a new server record
|
||||
* @param serverEntity server entity to create
|
||||
* @return created server entity
|
||||
*/
|
||||
@Transactional
|
||||
public ServerEntity createServer(ServerEntity serverEntity) {
|
||||
log.info("Creating server: {}", serverEntity.getServerName());
|
||||
return serverRepository.save(serverEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update server information
|
||||
* @param serverEntity server entity to update
|
||||
* @return updated server entity
|
||||
*/
|
||||
@Transactional
|
||||
public ServerEntity updateServer(ServerEntity serverEntity) {
|
||||
log.info("Updating server: {}", serverEntity.getServerName());
|
||||
return serverRepository.save(serverEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find server by UID
|
||||
* @param uid server UID
|
||||
* @return Optional<ServerEntity>
|
||||
*/
|
||||
public Optional<ServerEntity> findByUid(String uid) {
|
||||
return serverRepository.findByUid(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all servers for an organization
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
public List<ServerEntity> findByOrgUid(String orgUid) {
|
||||
return serverRepository.findByOrgUidAndDeletedFalseOrderByCreatedAtDesc(orgUid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find servers by type
|
||||
* @param type server type
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
public List<ServerEntity> findByType(String type, String orgUid) {
|
||||
return serverRepository.findByTypeAndOrgUidAndDeletedFalse(type, orgUid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find servers by status
|
||||
* @param status server status
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
public List<ServerEntity> findByStatus(String status, String orgUid) {
|
||||
return serverRepository.findByStatusAndOrgUidAndDeletedFalse(status, orgUid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find servers with high resource usage
|
||||
* @param orgUid organization UID
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
public List<ServerEntity> findServersWithHighUsage(String orgUid) {
|
||||
return serverRepository.findServersWithHighUsage(orgUid, 80.0, 80.0, 85.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find servers without recent heartbeat
|
||||
* @param orgUid organization UID
|
||||
* @param minutesThreshold minutes threshold for heartbeat
|
||||
* @return List<ServerEntity>
|
||||
*/
|
||||
public List<ServerEntity> findServersWithoutRecentHeartbeat(String orgUid, int minutesThreshold) {
|
||||
LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(minutesThreshold);
|
||||
return serverRepository.findServersWithoutRecentHeartbeat(orgUid, cutoffTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update server heartbeat
|
||||
* @param uid server UID
|
||||
* @return updated server entity
|
||||
*/
|
||||
@Transactional
|
||||
public Optional<ServerEntity> updateHeartbeat(String uid) {
|
||||
Optional<ServerEntity> optional = serverRepository.findByUid(uid);
|
||||
if (optional.isPresent()) {
|
||||
ServerEntity server = optional.get();
|
||||
server.setLastHeartbeat(LocalDateTime.now());
|
||||
return Optional.of(serverRepository.save(server));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update server resource usage
|
||||
* @param uid server UID
|
||||
* @param cpuUsage CPU usage percenservere
|
||||
* @param memoryUsage memory usage percenservere
|
||||
* @param diskUsage disk usage percenservere
|
||||
* @return updated server entity
|
||||
*/
|
||||
@Transactional
|
||||
public Optional<ServerEntity> updateResourceUsage(String uid, Double cpuUsage, Double memoryUsage, Double diskUsage) {
|
||||
Optional<ServerEntity> optional = serverRepository.findByUid(uid);
|
||||
if (optional.isPresent()) {
|
||||
ServerEntity server = optional.get();
|
||||
server.setCpuUsage(cpuUsage);
|
||||
server.setMemoryUsage(memoryUsage);
|
||||
server.setDiskUsage(diskUsage);
|
||||
server.setLastHeartbeat(LocalDateTime.now());
|
||||
|
||||
// Update status based on resource usage
|
||||
if (cpuUsage > 90 || memoryUsage > 90 || diskUsage > 95) {
|
||||
server.setStatus(ServerStatusEnum.OVERLOADED.name());
|
||||
} else if (cpuUsage > 80 || memoryUsage > 80 || diskUsage > 85) {
|
||||
server.setStatus(ServerStatusEnum.WARNING.name());
|
||||
} else {
|
||||
server.setStatus(ServerStatusEnum.ONLINE.name());
|
||||
}
|
||||
|
||||
return Optional.of(serverRepository.save(server));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current server metrics (for self-monitoring)
|
||||
* @return ServerEntity with current metrics
|
||||
*/
|
||||
public ServerEntity getCurrentServerMetrics() {
|
||||
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
|
||||
|
||||
// Calculate memory usage
|
||||
long totalMemory = memoryBean.getHeapMemoryUsage().getMax();
|
||||
long usedMemory = memoryBean.getHeapMemoryUsage().getUsed();
|
||||
double memoryUsagePercent = (double) usedMemory / totalMemory * 100;
|
||||
|
||||
// Get CPU usage (approximate)
|
||||
double cpuUsage = osBean.getSystemLoadAverage() * 100;
|
||||
if (cpuUsage > 100) cpuUsage = 100;
|
||||
|
||||
// Create server entity with current metrics
|
||||
return ServerEntity.builder()
|
||||
.serverName(System.getProperty("os.name") + " - " + System.getProperty("user.name"))
|
||||
.serverIp("127.0.0.1")
|
||||
.type(ServerTypeEnum.APPLICATION.name())
|
||||
.status(ServerStatusEnum.ONLINE.name())
|
||||
.cpuUsage(cpuUsage)
|
||||
.memoryUsage(memoryUsagePercent)
|
||||
.totalMemoryMb(totalMemory / (1024 * 1024))
|
||||
.usedMemoryMb(usedMemory / (1024 * 1024))
|
||||
.uptimeSeconds(ManagementFactory.getRuntimeMXBean().getUptime() / 1000)
|
||||
.startTime(LocalDateTime.now().minusSeconds(ManagementFactory.getRuntimeMXBean().getUptime() / 1000))
|
||||
.lastHeartbeat(LocalDateTime.now())
|
||||
.osInfo(System.getProperty("os.name") + " " + System.getProperty("os.version"))
|
||||
.javaVersion(System.getProperty("java.version"))
|
||||
.environment("DEV")
|
||||
.monitoringEnabled(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete server (soft delete)
|
||||
* @param uid server UID
|
||||
*/
|
||||
@Transactional
|
||||
public void deleteServer(String uid) {
|
||||
Optional<ServerEntity> optional = serverRepository.findByUid(uid);
|
||||
if (optional.isPresent()) {
|
||||
ServerEntity server = optional.get();
|
||||
server.setDeleted(true);
|
||||
serverRepository.save(server);
|
||||
log.info("Deleted server: {}", server.getServerName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server statistics for an organization
|
||||
* @param orgUid organization UID
|
||||
* @return ServerStatistics object
|
||||
*/
|
||||
public ServerStatistics getServerStatistics(String orgUid) {
|
||||
List<ServerEntity> servers = findByOrgUid(orgUid);
|
||||
|
||||
long totalServers = servers.size();
|
||||
long onlineServers = servers.stream()
|
||||
.filter(s -> ServerStatusEnum.ONLINE.name().equals(s.getStatus()))
|
||||
.count();
|
||||
long offlineServers = servers.stream()
|
||||
.filter(s -> ServerStatusEnum.OFFLINE.name().equals(s.getStatus()))
|
||||
.count();
|
||||
long warningServers = servers.stream()
|
||||
.filter(s -> ServerStatusEnum.WARNING.name().equals(s.getStatus()))
|
||||
.count();
|
||||
long overloadedServers = servers.stream()
|
||||
.filter(s -> ServerStatusEnum.OVERLOADED.name().equals(s.getStatus()))
|
||||
.count();
|
||||
|
||||
return ServerStatistics.builder()
|
||||
.totalServers(totalServers)
|
||||
.onlineServers(onlineServers)
|
||||
.offlineServers(offlineServers)
|
||||
.warningServers(warningServers)
|
||||
.overloadedServers(overloadedServers)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Server statistics data class
|
||||
*/
|
||||
public static class ServerStatistics {
|
||||
private long totalServers;
|
||||
private long onlineServers;
|
||||
private long offlineServers;
|
||||
private long warningServers;
|
||||
private long overloadedServers;
|
||||
|
||||
// Getters and setters
|
||||
public long getTotalServers() { return totalServers; }
|
||||
public void setTotalServers(long totalServers) { this.totalServers = totalServers; }
|
||||
|
||||
public long getOnlineServers() { return onlineServers; }
|
||||
public void setOnlineServers(long onlineServers) { this.onlineServers = onlineServers; }
|
||||
|
||||
public long getOfflineServers() { return offlineServers; }
|
||||
public void setOfflineServers(long offlineServers) { this.offlineServers = offlineServers; }
|
||||
|
||||
public long getWarningServers() { return warningServers; }
|
||||
public void setWarningServers(long warningServers) { this.warningServers = warningServers; }
|
||||
|
||||
public long getOverloadedServers() { return overloadedServers; }
|
||||
public void setOverloadedServers(long overloadedServers) { this.overloadedServers = overloadedServers; }
|
||||
|
||||
// Builder pattern
|
||||
public static ServerStatisticsBuilder builder() {
|
||||
return new ServerStatisticsBuilder();
|
||||
}
|
||||
|
||||
public static class ServerStatisticsBuilder {
|
||||
private ServerStatistics statistics = new ServerStatistics();
|
||||
|
||||
public ServerStatisticsBuilder totalServers(long totalServers) {
|
||||
statistics.totalServers = totalServers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerStatisticsBuilder onlineServers(long onlineServers) {
|
||||
statistics.onlineServers = onlineServers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerStatisticsBuilder offlineServers(long offlineServers) {
|
||||
statistics.offlineServers = offlineServers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerStatisticsBuilder warningServers(long warningServers) {
|
||||
statistics.warningServers = warningServers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerStatisticsBuilder overloadedServers(long overloadedServers) {
|
||||
statistics.overloadedServers = overloadedServers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerStatistics build() {
|
||||
return statistics;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-07-09 22:19:21
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-22 17:14:52
|
||||
* @LastEditTime: 2025-07-24 20:39:01
|
||||
* @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.
|
||||
@@ -11,13 +11,12 @@
|
||||
* 联系:270580156@qq.com
|
||||
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host;
|
||||
package com.bytedesk.core.server;
|
||||
|
||||
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;
|
||||
|
||||
@@ -25,30 +24,14 @@ import jakarta.persistence.criteria.Predicate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class HostSpecification extends BaseSpecification {
|
||||
public class ServerSpecification extends BaseSpecification {
|
||||
|
||||
public static Specification<HostEntity> search(HostRequest request) {
|
||||
public static Specification<ServerEntity> search(ServerRequest request) {
|
||||
log.info("request: {} orgUid: {} pageNumber: {} pageSize: {}",
|
||||
request, request.getOrgUid(), request.getPageNumber(), request.getPageSize());
|
||||
return (root, query, criteriaBuilder) -> {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
|
||||
// name
|
||||
if (StringUtils.hasText(request.getName())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("name"), "%" + request.getName() + "%"));
|
||||
}
|
||||
// description
|
||||
if (StringUtils.hasText(request.getDescription())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("description"), "%" + request.getDescription() + "%"));
|
||||
}
|
||||
// type
|
||||
if (StringUtils.hasText(request.getType())) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("type"), request.getType()));
|
||||
}
|
||||
//
|
||||
if (StringUtils.hasText(request.getUserUid())) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("userUid"), request.getUserUid()));
|
||||
}
|
||||
//
|
||||
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 19:56: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.core.server;
|
||||
|
||||
/**
|
||||
* Server status enumeration
|
||||
* Defines different statuses of servers
|
||||
*/
|
||||
public enum ServerStatusEnum {
|
||||
ONLINE, // 在线运行
|
||||
OFFLINE, // 离线
|
||||
MAINTENANCE, // 维护中
|
||||
STARTING, // 启动中
|
||||
STOPPING, // 停止中
|
||||
RESTARTING, // 重启中
|
||||
ERROR, // 错误状态
|
||||
WARNING, // 警告状态
|
||||
DEGRADED, // 降级运行
|
||||
OVERLOADED, // 过载
|
||||
UNKNOWN; // 未知状态
|
||||
|
||||
/**
|
||||
* Get Chinese name for the server status
|
||||
* @return Chinese name
|
||||
*/
|
||||
public String getChineseName() {
|
||||
switch (this) {
|
||||
case ONLINE:
|
||||
return "在线运行";
|
||||
case OFFLINE:
|
||||
return "离线";
|
||||
case MAINTENANCE:
|
||||
return "维护中";
|
||||
case STARTING:
|
||||
return "启动中";
|
||||
case STOPPING:
|
||||
return "停止中";
|
||||
case RESTARTING:
|
||||
return "重启中";
|
||||
case ERROR:
|
||||
return "错误状态";
|
||||
case WARNING:
|
||||
return "警告状态";
|
||||
case DEGRADED:
|
||||
return "降级运行";
|
||||
case OVERLOADED:
|
||||
return "过载";
|
||||
case UNKNOWN:
|
||||
return "未知状态";
|
||||
default:
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if server is healthy (online and not in error/warning states)
|
||||
* @return true if healthy
|
||||
*/
|
||||
public boolean isHealthy() {
|
||||
return this == ONLINE || this == DEGRADED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if server is operational (can serve requests)
|
||||
* @return true if operational
|
||||
*/
|
||||
public boolean isOperational() {
|
||||
return this == ONLINE || this == DEGRADED || this == OVERLOADED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from string value to enum
|
||||
* @param value string value
|
||||
* @return ServerStatusEnum
|
||||
*/
|
||||
public static ServerStatusEnum fromValue(String value) {
|
||||
for (ServerStatusEnum status : ServerStatusEnum.values()) {
|
||||
if (status.name().equalsIgnoreCase(value)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No ServerStatusEnum constant with value: " + value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* @Author: jackning 270580156@qq.com
|
||||
* @Date: 2024-05-11 18:14:28
|
||||
* @LastEditors: jackning 270580156@qq.com
|
||||
* @LastEditTime: 2025-07-24 19:56: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.core.server;
|
||||
|
||||
/**
|
||||
* Server type enumeration
|
||||
* Defines different types of servers in the system
|
||||
*/
|
||||
public enum ServerTypeEnum {
|
||||
APPLICATION, // 应用服务器
|
||||
DATABASE, // 数据库服务器
|
||||
CACHE, // 缓存服务器
|
||||
LOAD_BALANCER, // 负载均衡器
|
||||
WEB_SERVER, // Web服务器
|
||||
FILE_SERVER, // 文件服务器
|
||||
MAIL_SERVER, // 邮件服务器
|
||||
DNS_SERVER, // DNS服务器
|
||||
PROXY_SERVER, // 代理服务器
|
||||
MONITORING, // 监控服务器
|
||||
BACKUP, // 备份服务器
|
||||
GATEWAY, // 网关服务器
|
||||
API_SERVER, // API服务器
|
||||
MESSAGE_QUEUE, // 消息队列服务器
|
||||
SEARCH_ENGINE, // 搜索引擎服务器
|
||||
CDN, // CDN服务器
|
||||
OTHER; // 其他类型
|
||||
|
||||
/**
|
||||
* Get Chinese name for the server type
|
||||
* @return Chinese name
|
||||
*/
|
||||
public String getChineseName() {
|
||||
switch (this) {
|
||||
case APPLICATION:
|
||||
return "应用服务器";
|
||||
case DATABASE:
|
||||
return "数据库服务器";
|
||||
case CACHE:
|
||||
return "缓存服务器";
|
||||
case LOAD_BALANCER:
|
||||
return "负载均衡器";
|
||||
case WEB_SERVER:
|
||||
return "Web服务器";
|
||||
case FILE_SERVER:
|
||||
return "文件服务器";
|
||||
case MAIL_SERVER:
|
||||
return "邮件服务器";
|
||||
case DNS_SERVER:
|
||||
return "DNS服务器";
|
||||
case PROXY_SERVER:
|
||||
return "代理服务器";
|
||||
case MONITORING:
|
||||
return "监控服务器";
|
||||
case BACKUP:
|
||||
return "备份服务器";
|
||||
case GATEWAY:
|
||||
return "网关服务器";
|
||||
case API_SERVER:
|
||||
return "API服务器";
|
||||
case MESSAGE_QUEUE:
|
||||
return "消息队列服务器";
|
||||
case SEARCH_ENGINE:
|
||||
return "搜索引擎服务器";
|
||||
case CDN:
|
||||
return "CDN服务器";
|
||||
case OTHER:
|
||||
return "其他类型";
|
||||
default:
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from string value to enum
|
||||
* @param value string value
|
||||
* @return ServerTypeEnum
|
||||
*/
|
||||
public static ServerTypeEnum fromValue(String value) {
|
||||
for (ServerTypeEnum type : ServerTypeEnum.values()) {
|
||||
if (type.name().equalsIgnoreCase(value)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No ServerTypeEnum constant with value: " + value);
|
||||
}
|
||||
}
|
||||
@@ -11,26 +11,26 @@
|
||||
*
|
||||
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host.event;
|
||||
package com.bytedesk.core.server.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import com.bytedesk.core.host.HostEntity;
|
||||
import com.bytedesk.core.server.ServerEntity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class HostCreateEvent extends ApplicationEvent {
|
||||
public class ServerCreateEvent extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private HostEntity host;
|
||||
private ServerEntity server;
|
||||
|
||||
public HostCreateEvent(HostEntity host) {
|
||||
super(host);
|
||||
this.host = host;
|
||||
public ServerCreateEvent(ServerEntity server) {
|
||||
super(server);
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,25 +11,25 @@
|
||||
*
|
||||
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host.event;
|
||||
package com.bytedesk.core.server.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import com.bytedesk.core.host.HostEntity;
|
||||
import com.bytedesk.core.server.ServerEntity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class HostDeleteEvent extends ApplicationEvent {
|
||||
public class ServerDeleteEvent extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private HostEntity host;
|
||||
private ServerEntity server;
|
||||
|
||||
public HostDeleteEvent(HostEntity host) {
|
||||
super(host);
|
||||
this.host = host;
|
||||
public ServerDeleteEvent(ServerEntity server) {
|
||||
super(server);
|
||||
this.server = server;
|
||||
}
|
||||
}
|
||||
@@ -11,26 +11,26 @@
|
||||
*
|
||||
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
|
||||
*/
|
||||
package com.bytedesk.core.host.event;
|
||||
package com.bytedesk.core.server.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import com.bytedesk.core.host.HostEntity;
|
||||
import com.bytedesk.core.server.ServerEntity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class HostUpdateEvent extends ApplicationEvent {
|
||||
public class ServerUpdateEvent extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private HostEntity host;
|
||||
private ServerEntity server;
|
||||
|
||||
public HostUpdateEvent(HostEntity host) {
|
||||
super(host);
|
||||
this.host = host;
|
||||
public ServerUpdateEvent(ServerEntity server) {
|
||||
super(server);
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
@NonNullApi
|
||||
package com.bytedesk.core.host;
|
||||
package com.bytedesk.core.server;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
Reference in New Issue
Block a user