feat: add M7 DeviceService and DTOs

This commit is contained in:
2026-05-25 00:59:12 +08:00
parent 58b947a366
commit f94f2b91e8
5 changed files with 525 additions and 0 deletions
@@ -0,0 +1,231 @@
package cn.craftlabs.platform.api.service;
import cn.craftlabs.platform.api.persistence.customer.PlatformCustomer;
import cn.craftlabs.platform.api.persistence.customer.PlatformCustomerMapper;
import cn.craftlabs.platform.api.persistence.device.PlatformDevice;
import cn.craftlabs.platform.api.persistence.device.PlatformDeviceMapper;
import cn.craftlabs.platform.api.persistence.device.PlatformDeviceSnBinding;
import cn.craftlabs.platform.api.persistence.device.PlatformDeviceSnBindingMapper;
import cn.craftlabs.platform.api.persistence.device.PlatformDeviceSwapRequest;
import cn.craftlabs.platform.api.persistence.device.PlatformDeviceSwapRequestMapper;
import cn.craftlabs.platform.api.persistence.license.PlatformLicenseSn;
import cn.craftlabs.platform.api.persistence.license.PlatformLicenseSnMapper;
import cn.craftlabs.platform.api.persistence.project.PlatformProject;
import cn.craftlabs.platform.api.persistence.project.PlatformProjectMapper;
import cn.craftlabs.platform.api.web.dto.DeviceBindingResponse;
import cn.craftlabs.platform.api.web.dto.DeviceCreateRequest;
import cn.craftlabs.platform.api.web.dto.DeviceResponse;
import cn.craftlabs.platform.api.web.dto.DeviceSwapRequestDto;
import cn.craftlabs.platform.api.web.dto.PageResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class DeviceService {
private final PlatformDeviceMapper deviceMapper;
private final PlatformDeviceSnBindingMapper bindingMapper;
private final PlatformDeviceSwapRequestMapper swapRequestMapper;
private final PlatformCustomerMapper customerMapper;
private final PlatformProjectMapper projectMapper;
private final PlatformLicenseSnMapper licenseSnMapper;
public DeviceService(
PlatformDeviceMapper deviceMapper,
PlatformDeviceSnBindingMapper bindingMapper,
PlatformDeviceSwapRequestMapper swapRequestMapper,
PlatformCustomerMapper customerMapper,
PlatformProjectMapper projectMapper,
PlatformLicenseSnMapper licenseSnMapper) {
this.deviceMapper = deviceMapper;
this.bindingMapper = bindingMapper;
this.swapRequestMapper = swapRequestMapper;
this.customerMapper = customerMapper;
this.projectMapper = projectMapper;
this.licenseSnMapper = licenseSnMapper;
}
@Transactional(readOnly = true)
public PageResponse<DeviceResponse> listDevices(int page, int size, Long customerId, String site, String snCode) {
LambdaQueryWrapper<PlatformDevice> q =
Wrappers.lambdaQuery(PlatformDevice.class)
.eq(customerId != null, PlatformDevice::getCustomerId, customerId)
.eq(site != null && !site.isEmpty(), PlatformDevice::getSite, site)
.orderByDesc(PlatformDevice::getId);
Page<PlatformDevice> mpPage = new Page<>(page + 1L, size);
deviceMapper.selectPage(mpPage, q);
List<DeviceResponse> content =
mpPage.getRecords().stream().map(this::toDeviceResponse).collect(Collectors.toList());
return new PageResponse<>(content, mpPage.getTotal(), page, size);
}
@Transactional(readOnly = true)
public DeviceResponse getDevice(Long id) {
PlatformDevice d = deviceMapper.selectById(id);
return d != null ? toDeviceResponse(d) : null;
}
@Transactional
public DeviceResponse createDevice(DeviceCreateRequest request) {
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
PlatformDevice d = new PlatformDevice();
d.setMid(request.getMid());
d.setAlias(request.getAlias());
d.setSite(request.getSite());
d.setCustomerId(request.getCustomerId());
d.setProjectId(request.getProjectId());
d.setStatus("ONLINE");
d.setFirstSeenAt(now);
d.setCreatedAt(now);
d.setUpdatedAt(now);
deviceMapper.insert(d);
return toDeviceResponse(d);
}
@Transactional
public DeviceResponse updateDevice(Long id, DeviceCreateRequest request) {
PlatformDevice d = deviceMapper.selectById(id);
if (d == null) {
return null;
}
d.setMid(request.getMid());
d.setAlias(request.getAlias());
d.setSite(request.getSite());
d.setCustomerId(request.getCustomerId());
d.setProjectId(request.getProjectId());
d.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
deviceMapper.updateById(d);
return toDeviceResponse(d);
}
@Transactional(readOnly = true)
public List<DeviceBindingResponse> getBindings(Long deviceId) {
LambdaQueryWrapper<PlatformDeviceSnBinding> q =
Wrappers.lambdaQuery(PlatformDeviceSnBinding.class)
.eq(PlatformDeviceSnBinding::getDeviceId, deviceId)
.orderByDesc(PlatformDeviceSnBinding::getBindAt);
return bindingMapper.selectList(q).stream()
.map(this::toBindingResponse)
.collect(Collectors.toList());
}
@Transactional
public void createSwapRequest(DeviceSwapRequestDto request) {
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
PlatformDeviceSwapRequest sr = new PlatformDeviceSwapRequest();
sr.setOldDeviceId(request.getOldDeviceId());
sr.setNewMid(request.getNewMid());
sr.setSnId(request.getSnId());
sr.setReason(request.getReason());
sr.setStatus("PENDING");
sr.setRemark(request.getRemark());
sr.setCreatedAt(now);
swapRequestMapper.insert(sr);
}
@Transactional
public void handleDeviceEvent(String mid, Long snId) {
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
LambdaQueryWrapper<PlatformDevice> q =
Wrappers.lambdaQuery(PlatformDevice.class)
.eq(PlatformDevice::getMid, mid);
PlatformDevice device = deviceMapper.selectOne(q);
if (device == null) {
device = new PlatformDevice();
device.setMid(mid);
device.setStatus("ONLINE");
device.setFirstSeenAt(now);
device.setCreatedAt(now);
device.setUpdatedAt(now);
deviceMapper.insert(device);
} else {
device.setLastHeartbeatAt(now);
device.setUpdatedAt(now);
deviceMapper.updateById(device);
}
PlatformDeviceSnBinding binding = new PlatformDeviceSnBinding();
binding.setDeviceId(device.getId());
binding.setLicenseSnId(snId);
binding.setBindType("ACTIVATE");
binding.setBindAt(now);
binding.setCreatedAt(now);
bindingMapper.insert(binding);
}
private DeviceResponse toDeviceResponse(PlatformDevice d) {
DeviceResponse r = new DeviceResponse();
r.setId(d.getId());
r.setMid(d.getMid());
r.setAlias(d.getAlias());
r.setSite(d.getSite());
r.setCustomerId(d.getCustomerId());
r.setProjectId(d.getProjectId());
r.setStatus(d.getStatus());
r.setStatusLabel(statusLabel(d.getStatus()));
r.setFirstSeenAt(d.getFirstSeenAt());
r.setLastHeartbeatAt(d.getLastHeartbeatAt());
r.setCreatedAt(d.getCreatedAt());
if (d.getCustomerId() != null) {
PlatformCustomer c = customerMapper.selectById(d.getCustomerId());
if (c != null) {
r.setCustomerName(c.getName());
}
}
if (d.getProjectId() != null) {
PlatformProject p = projectMapper.selectById(d.getProjectId());
if (p != null) {
r.setProjectName(p.getName());
}
}
return r;
}
private DeviceBindingResponse toBindingResponse(PlatformDeviceSnBinding b) {
DeviceBindingResponse r = new DeviceBindingResponse();
r.setId(b.getId());
r.setLicenseSnId(b.getLicenseSnId());
r.setBindType(b.getBindType());
r.setBindTypeLabel(bindTypeLabel(b.getBindType()));
r.setBindAt(b.getBindAt());
r.setRemark(b.getRemark());
if (b.getLicenseSnId() != null) {
PlatformLicenseSn sn = licenseSnMapper.selectById(b.getLicenseSnId());
if (sn != null) {
r.setSnCode(sn.getSnCode());
}
}
return r;
}
private static String statusLabel(String status) {
if (status == null) {
return "离线";
}
switch (status) {
case "ONLINE": return "在线";
case "OFFLINE": return "离线";
case "RETIRED": return "已退役";
default: return "离线";
}
}
private static String bindTypeLabel(String bindType) {
if (bindType == null) {
return "";
}
switch (bindType) {
case "ACTIVATE": return "激活绑定";
case "SWAP": return "换机";
case "UNBIND": return "解绑";
default: return "";
}
}
}
@@ -0,0 +1,70 @@
package cn.craftlabs.platform.api.web.dto;
import java.time.OffsetDateTime;
public class DeviceBindingResponse {
private Long id;
private Long licenseSnId;
private String snCode;
private String bindType;
private String bindTypeLabel;
private OffsetDateTime bindAt;
private String remark;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getLicenseSnId() {
return licenseSnId;
}
public void setLicenseSnId(Long licenseSnId) {
this.licenseSnId = licenseSnId;
}
public String getSnCode() {
return snCode;
}
public void setSnCode(String snCode) {
this.snCode = snCode;
}
public String getBindType() {
return bindType;
}
public void setBindType(String bindType) {
this.bindType = bindType;
}
public String getBindTypeLabel() {
return bindTypeLabel;
}
public void setBindTypeLabel(String bindTypeLabel) {
this.bindTypeLabel = bindTypeLabel;
}
public OffsetDateTime getBindAt() {
return bindAt;
}
public void setBindAt(OffsetDateTime bindAt) {
this.bindAt = bindAt;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
@@ -0,0 +1,50 @@
package cn.craftlabs.platform.api.web.dto;
public class DeviceCreateRequest {
private String mid;
private String alias;
private String site;
private Long customerId;
private Long projectId;
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getSite() {
return site;
}
public void setSite(String site) {
this.site = site;
}
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
public Long getProjectId() {
return projectId;
}
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
}
@@ -0,0 +1,124 @@
package cn.craftlabs.platform.api.web.dto;
import java.time.OffsetDateTime;
public class DeviceResponse {
private Long id;
private String mid;
private String alias;
private String site;
private Long customerId;
private String customerName;
private Long projectId;
private String projectName;
private String status;
private String statusLabel;
private OffsetDateTime firstSeenAt;
private OffsetDateTime lastHeartbeatAt;
private OffsetDateTime createdAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getSite() {
return site;
}
public void setSite(String site) {
this.site = site;
}
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public Long getProjectId() {
return projectId;
}
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getStatusLabel() {
return statusLabel;
}
public void setStatusLabel(String statusLabel) {
this.statusLabel = statusLabel;
}
public OffsetDateTime getFirstSeenAt() {
return firstSeenAt;
}
public void setFirstSeenAt(OffsetDateTime firstSeenAt) {
this.firstSeenAt = firstSeenAt;
}
public OffsetDateTime getLastHeartbeatAt() {
return lastHeartbeatAt;
}
public void setLastHeartbeatAt(OffsetDateTime lastHeartbeatAt) {
this.lastHeartbeatAt = lastHeartbeatAt;
}
public OffsetDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(OffsetDateTime createdAt) {
this.createdAt = createdAt;
}
}
@@ -0,0 +1,50 @@
package cn.craftlabs.platform.api.web.dto;
public class DeviceSwapRequestDto {
private Long oldDeviceId;
private String newMid;
private Long snId;
private String reason;
private String remark;
public Long getOldDeviceId() {
return oldDeviceId;
}
public void setOldDeviceId(Long oldDeviceId) {
this.oldDeviceId = oldDeviceId;
}
public String getNewMid() {
return newMid;
}
public void setNewMid(String newMid) {
this.newMid = newMid;
}
public Long getSnId() {
return snId;
}
public void setSnId(Long snId) {
this.snId = snId;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}