diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java index 38719605..8052c39f 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java @@ -61,13 +61,15 @@ public class HomePageController { /** * 获取设备使用数据 * - * @param deviceId 设备ID + * @param deviceTypeId 设备ID (可选) * @param range 时间范围 1:半年 2:一年 * @return 每月使用数据列表 */ - @GetMapping("/getEquipmentUsageData/{deviceId}/{range}") - public R>> getEquipmentUsageData(@PathVariable Long deviceId, @PathVariable Integer range) { - return R.ok(deviceService.getEquipmentUsageData(deviceId, range)); + @GetMapping("/getEquipmentUsageData/{range}") + public R>> getEquipmentUsageData(@PathVariable Integer range, + @RequestParam(required = false) Long deviceTypeId) { + return R.ok(deviceService.getEquipmentUsageData(deviceTypeId, range)); } + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/fence/DeviceFenceAccessRecordController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/fence/DeviceFenceAccessRecordController.java new file mode 100644 index 00000000..97e7aa97 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/fence/DeviceFenceAccessRecordController.java @@ -0,0 +1,108 @@ +package com.fuyuanshen.web.controller.device.fence; + +import java.util.List; + +import com.fuyuanshen.equipment.domain.bo.DeviceFenceAccessRecordBo; +import com.fuyuanshen.equipment.domain.vo.DeviceFenceAccessRecordVo; +import com.fuyuanshen.equipment.service.IDeviceFenceAccessRecordService; +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit; +import com.fuyuanshen.common.log.annotation.Log; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.core.validate.EditGroup; +import com.fuyuanshen.common.log.enums.BusinessType; +import com.fuyuanshen.common.excel.utils.ExcelUtil; + +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; + +/** + * 围栏进出记录 + * + * @author Lion Li + * @date 2025-09-11 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/fys-equipment/fenceAccessRecord") +public class DeviceFenceAccessRecordController extends BaseController { + + private final IDeviceFenceAccessRecordService deviceFenceAccessRecordService; + + /** + * 查询围栏进出记录列表 + */ + @SaCheckPermission("fys-equipment:fenceAccessRecord:list") + @GetMapping("/list") + public TableDataInfo list(DeviceFenceAccessRecordBo bo, PageQuery pageQuery) { + return deviceFenceAccessRecordService.queryPageList(bo, pageQuery); + } + + /** + * 围栏进出记录列表 + */ + @SaCheckPermission("fys-equipment:fenceAccessRecord:export") + @Log(title = "围栏进出记录", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(DeviceFenceAccessRecordBo bo, HttpServletResponse response) { + List list = deviceFenceAccessRecordService.queryList(bo); + ExcelUtil.exportExcel(list, "围栏进出记录", DeviceFenceAccessRecordVo.class, response); + } + + /** + * 获取围栏进出记录详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("fys-equipment:fenceAccessRecord:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(deviceFenceAccessRecordService.queryById(id)); + } + + /** + * 新增围栏进出记录 + */ + @SaCheckPermission("fys-equipment:fenceAccessRecord:add") + @Log(title = "围栏进出记录", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody DeviceFenceAccessRecordBo bo) { + return toAjax(deviceFenceAccessRecordService.insertByBo(bo)); + } + + /** + * 修改围栏进出记录 + */ + @SaCheckPermission("fys-equipment:fenceAccessRecord:edit") + @Log(title = "围栏进出记录", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody DeviceFenceAccessRecordBo bo) { + return toAjax(deviceFenceAccessRecordService.updateByBo(bo)); + } + + /** + * 删除围栏进出记录 + * + * @param ids 主键串 + */ + @SaCheckPermission("fys-equipment:fenceAccessRecord:remove") + @Log(title = "围栏进出记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(deviceFenceAccessRecordService.deleteWithValidByIds(List.of(ids), true)); + } + + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/fence/DeviceGeoFenceController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/fence/DeviceGeoFenceController.java new file mode 100644 index 00000000..cae25e3f --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/fence/DeviceGeoFenceController.java @@ -0,0 +1,124 @@ +package com.fuyuanshen.web.controller.device.fence; + +import java.util.List; + +import com.fuyuanshen.equipment.domain.bo.DeviceGeoFenceBo; +import com.fuyuanshen.equipment.domain.dto.FenceCheckResponse; +import com.fuyuanshen.equipment.domain.query.FenceCheckRequest; +import com.fuyuanshen.equipment.domain.vo.DeviceGeoFenceVo; +import com.fuyuanshen.equipment.service.IDeviceGeoFenceService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit; +import com.fuyuanshen.common.log.annotation.Log; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.core.validate.EditGroup; +import com.fuyuanshen.common.log.enums.BusinessType; +import com.fuyuanshen.common.excel.utils.ExcelUtil; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; + +/** + * 电子围栏 + * + * @author Lion Li + * @date 2025-09-11 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/fys-equipment/geoFence") +public class DeviceGeoFenceController extends BaseController { + + private final IDeviceGeoFenceService deviceGeoFenceService; + + /** + * 查询电子围栏列表 + */ + @SaCheckPermission("fys-equipment:geoFence:list") + @GetMapping("/list") + public TableDataInfo list(DeviceGeoFenceBo bo, PageQuery pageQuery) { + return deviceGeoFenceService.queryPageList(bo, pageQuery); + } + + /** + * 电子围栏列表 + */ + @SaCheckPermission("fys-equipment:geoFence:export") + @Log(title = "电子围栏", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(DeviceGeoFenceBo bo, HttpServletResponse response) { + List list = deviceGeoFenceService.queryList(bo); + ExcelUtil.exportExcel(list, "电子围栏", DeviceGeoFenceVo.class, response); + } + + /** + * 获取电子围栏详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("fys-equipment:geoFence:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(deviceGeoFenceService.queryById(id)); + } + + /** + * 新增电子围栏 + */ + @SaCheckPermission("fys-equipment:geoFence:add") + @Log(title = "电子围栏", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody DeviceGeoFenceBo bo) { + return toAjax(deviceGeoFenceService.insertByBo(bo)); + } + + /** + * 修改电子围栏 + */ + @SaCheckPermission("fys-equipment:geoFence:edit") + @Log(title = "电子围栏", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody DeviceGeoFenceBo bo) { + return toAjax(deviceGeoFenceService.updateByBo(bo)); + } + + /** + * 删除电子围栏 + * + * @param ids 主键串 + */ + @SaCheckPermission("fys-equipment:geoFence:remove") + @Log(title = "电子围栏", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(deviceGeoFenceService.deleteWithValidByIds(List.of(ids), true)); + } + + + /** + * 位置检查 + * + * @param request + * @return + */ + @PostMapping("/check") + public ResponseEntity checkPosition( + @Valid @RequestBody FenceCheckRequest request) { + FenceCheckResponse response = deviceGeoFenceService.checkPosition(request); + return ResponseEntity.ok(response); + } + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceFenceAccessRecord.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceFenceAccessRecord.java new file mode 100644 index 00000000..8b50674c --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceFenceAccessRecord.java @@ -0,0 +1,78 @@ +package com.fuyuanshen.equipment.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.io.Serial; + +/** + * 围栏进出记录对象 device_fence_access_record + * + * @author Lion Li + * @date 2025-09-11 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("device_fence_access_record") +public class DeviceFenceAccessRecord extends BaseEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 记录ID + */ + @TableId(value = "id") + private Long id; + + /** + * 围栏ID + */ + private Long fenceId; + + /** + * 设备标识 + */ + private String deviceId; + + /** + * 用户ID + */ + private Long userId; + + /** + * 事件类型 + */ + private Long eventType; + + /** + * 纬度 + */ + private Long latitude; + + /** + * 经度 + */ + private Long longitude; + + /** + * 定位精度 + */ + private Long accuracy; + + /** + * 事件时间 + */ + private Date eventTime; + + /** + * 记录创建时间 + */ + private Date createdTime; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceGeoFence.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceGeoFence.java new file mode 100644 index 00000000..37285038 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceGeoFence.java @@ -0,0 +1,78 @@ +package com.fuyuanshen.equipment.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.io.Serial; + +/** + * 电子围栏对象 device_geo_fence + * + * @author Lion Li + * @date 2025-09-11 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("device_geo_fence") +public class DeviceGeoFence extends BaseEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 围栏唯一标识 + */ + @TableId(value = "id") + private Long id; + + /** + * 围栏名称 + */ + private String name; + + /** + * 围栏描述 + */ + private String description; + + /** + * 围栏区域类型, 0 POLYGON, 1 CIRCLE + */ + private Long areaType; + + /** + * 围栏坐标数据 + */ + private String coordinates; + + /** + * 圆形围栏半径(米) + */ + private Long radius; + + /** + * 是否激活 + */ + private Long isActive; + + /** + * 创建人 + */ + private Long createdBy; + + /** + * 创建时间 + */ + private Date createdTime; + + /** + * 更新时间 + */ + private Date updatedTime; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceChargeDischargeBo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceChargeDischargeBo.java index e953b0e8..cda7d679 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceChargeDischargeBo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceChargeDischargeBo.java @@ -6,6 +6,7 @@ import com.fuyuanshen.equipment.domain.DeviceChargeDischarge; import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; +import cn.hutool.core.date.DateUtil; import lombok.EqualsAndHashCode; import jakarta.validation.constraints.*; import java.util.Date; @@ -44,13 +45,25 @@ public class DeviceChargeDischargeBo extends BaseEntity { * 开始时间 */ @NotNull(message = "开始时间不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonFormat(pattern = "yyyy-MM-dd") private Date startTime; + // 添加字符串类型的setter方法来处理前端传递的字符串日期 + public void setStartTime(String startTime) { + this.startTime = DateUtil.parseDate(startTime); + } + /** * 结束时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") private Date endTime; + // 添加字符串类型的setter方法来处理前端传递的字符串日期 + public void setEndTime(String endTime) { + this.endTime = DateUtil.parseDate(endTime); + } + /** * 起始电量百分比(0-100) */ diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceFenceAccessRecordBo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceFenceAccessRecordBo.java new file mode 100644 index 00000000..60d00f4e --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceFenceAccessRecordBo.java @@ -0,0 +1,83 @@ +package com.fuyuanshen.equipment.domain.bo; + +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.core.validate.EditGroup; +import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; +import com.fuyuanshen.equipment.domain.DeviceFenceAccessRecord; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 围栏进出记录业务对象 device_fence_access_record + * + * @author Lion Li + * @date 2025-09-11 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = DeviceFenceAccessRecord.class, reverseConvertGenerate = false) +public class DeviceFenceAccessRecordBo extends BaseEntity { + + /** + * 记录ID + */ + @NotNull(message = "记录ID不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 围栏ID + */ + @NotNull(message = "围栏ID不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long fenceId; + + /** + * 设备标识 + */ + @NotBlank(message = "设备标识不能为空", groups = { AddGroup.class, EditGroup.class }) + private String deviceId; + + /** + * 用户ID + */ + private Long userId; + + /** + * 事件类型 + */ + @NotNull(message = "事件类型不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long eventType; + + /** + * 纬度 + */ + @NotNull(message = "纬度不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long latitude; + + /** + * 经度 + */ + @NotNull(message = "经度不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long longitude; + + /** + * 定位精度 + */ + private Long accuracy; + + /** + * 事件时间 + */ + @NotNull(message = "事件时间不能为空", groups = { AddGroup.class, EditGroup.class }) + private Date eventTime; + + /** + * 记录创建时间 + */ + private Date createdTime; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceGeoFenceBo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceGeoFenceBo.java new file mode 100644 index 00000000..d13217d9 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceGeoFenceBo.java @@ -0,0 +1,80 @@ +package com.fuyuanshen.equipment.domain.bo; + +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.core.validate.EditGroup; +import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; +import com.fuyuanshen.equipment.domain.DeviceGeoFence; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 电子围栏业务对象 device_geo_fence + * + * @author Lion Li + * @date 2025-09-11 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = DeviceGeoFence.class, reverseConvertGenerate = false) +public class DeviceGeoFenceBo extends BaseEntity { + + /** + * 围栏唯一标识 + */ + @NotNull(message = "围栏唯一标识不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 围栏名称 + */ + @NotBlank(message = "围栏名称不能为空", groups = { AddGroup.class, EditGroup.class }) + private String name; + + /** + * 围栏描述 + */ + private String description; + + /** + * 围栏区域类型, 0 POLYGON, 1 CIRCLE + */ + @NotNull(message = "围栏区域类型, 0 POLYGON, 1 CIRCLE不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long areaType; + + /** + * 围栏坐标数据 + */ + @NotBlank(message = "围栏坐标数据不能为空", groups = { AddGroup.class, EditGroup.class }) + private String coordinates; + + /** + * 圆形围栏半径(米) + */ + private Long radius; + + /** + * 是否激活 + */ + private Long isActive; + + /** + * 创建人 + */ + private Long createdBy; + + /** + * 创建时间 + */ + private Date createdTime; + + /** + * 更新时间 + */ + private Date updatedTime; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/dto/FenceCheckResponse.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/dto/FenceCheckResponse.java new file mode 100644 index 00000000..5d47f15d --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/dto/FenceCheckResponse.java @@ -0,0 +1,63 @@ +package com.fuyuanshen.equipment.domain.dto; + +import lombok.Data; + +import java.util.List; + + +/** + * 围栏位置检查响应结果 + * + * @author: 默苍璃 + * @date: 2025-09-1110:11 + */ + +@Data +public class FenceCheckResponse { + + /** + * 设备ID + */ + private String deviceId; + + /** + * 检查时间 + */ + private Long checkTime; + + /** + * 进入围栏列表 + */ + private List enteredFences; + + /** + * 离开围栏列表 + */ + private List exitedFences; + + /** + * 当前所在围栏列表 + */ + private List currentFences; + + /** + * 围栏信息 + */ + @Data + public static class FenceInfo { + /** + * 围栏ID + */ + private Long fenceId; + + /** + * 围栏名称 + */ + private String fenceName; + + /** + * 围栏类型 + */ + private Integer fenceType; + } +} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/query/FenceCheckRequest.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/query/FenceCheckRequest.java new file mode 100644 index 00000000..de556516 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/query/FenceCheckRequest.java @@ -0,0 +1,39 @@ +package com.fuyuanshen.equipment.domain.query; + +/** + * @author: 默苍璃 + * @date: 2025-09-1110:10 + */ + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 围栏位置检查请求参数 + */ +@Data +public class FenceCheckRequest { + + /** + * 设备ID + */ + @NotNull(message = "设备ID不能为空") + private String deviceId; + + /** + * 纬度 + */ + @NotNull(message = "纬度不能为空") + private Double latitude; + + /** + * 经度 + */ + @NotNull(message = "经度不能为空") + private Double longitude; + + /** + * 定位精度(米) + */ + private Double accuracy; +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java index 09e73b6d..1d2e2484 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java @@ -21,6 +21,18 @@ public class AlarmInformationVo { */ private Integer processingAlarm = 0; + + /** + * 今日报警总数 + */ + private Integer alarmsTotalToday = 0; + + /** + * 今日总处理报警 + */ + private Integer processingAlarmToday = 0; + + /** * 强制报警 */ @@ -37,7 +49,7 @@ public class AlarmInformationVo { private Integer alarmManual = 0; /** - * 电子围栏 + * */ private Integer fenceElectronic = 0; diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DataOverviewVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DataOverviewVo.java index c8c016d7..c4b6d39e 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DataOverviewVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DataOverviewVo.java @@ -26,6 +26,11 @@ public class DataOverviewVo { */ private Integer bindingNew = 0; + /** + * 已绑定设备 + */ + private Integer binding = 0; + /** * 异常设备 */ diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceFenceAccessRecordVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceFenceAccessRecordVo.java new file mode 100644 index 00000000..a91b3950 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceFenceAccessRecordVo.java @@ -0,0 +1,94 @@ +package com.fuyuanshen.equipment.domain.vo; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import com.fuyuanshen.common.excel.annotation.ExcelDictFormat; +import com.fuyuanshen.common.excel.convert.ExcelDictConvert; +import com.fuyuanshen.equipment.domain.DeviceFenceAccessRecord; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 围栏进出记录视图对象 device_fence_access_record + * + * @author Lion Li + * @date 2025-09-11 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = DeviceFenceAccessRecord.class) +public class DeviceFenceAccessRecordVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 记录ID + */ + @ExcelProperty(value = "记录ID") + private Long id; + + /** + * 围栏ID + */ + @ExcelProperty(value = "围栏ID") + private Long fenceId; + + /** + * 设备标识 + */ + @ExcelProperty(value = "设备标识") + private String deviceId; + + /** + * 用户ID + */ + @ExcelProperty(value = "用户ID") + private Long userId; + + /** + * 事件类型 + */ + @ExcelProperty(value = "事件类型") + private Long eventType; + + /** + * 纬度 + */ + @ExcelProperty(value = "纬度") + private Long latitude; + + /** + * 经度 + */ + @ExcelProperty(value = "经度") + private Long longitude; + + /** + * 定位精度 + */ + @ExcelProperty(value = "定位精度") + private Long accuracy; + + /** + * 事件时间 + */ + @ExcelProperty(value = "事件时间") + private Date eventTime; + + /** + * 记录创建时间 + */ + @ExcelProperty(value = "记录创建时间") + private Date createdTime; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceGeoFenceVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceGeoFenceVo.java new file mode 100644 index 00000000..50fbc372 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceGeoFenceVo.java @@ -0,0 +1,94 @@ +package com.fuyuanshen.equipment.domain.vo; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import com.fuyuanshen.common.excel.annotation.ExcelDictFormat; +import com.fuyuanshen.common.excel.convert.ExcelDictConvert; +import com.fuyuanshen.equipment.domain.DeviceGeoFence; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 电子围栏视图对象 device_geo_fence + * + * @author Lion Li + * @date 2025-09-11 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = DeviceGeoFence.class) +public class DeviceGeoFenceVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 围栏唯一标识 + */ + @ExcelProperty(value = "围栏唯一标识") + private Long id; + + /** + * 围栏名称 + */ + @ExcelProperty(value = "围栏名称") + private String name; + + /** + * 围栏描述 + */ + @ExcelProperty(value = "围栏描述") + private String description; + + /** + * 围栏区域类型, 0 POLYGON, 1 CIRCLE + */ + @ExcelProperty(value = "围栏区域类型, 0 POLYGON, 1 CIRCLE") + private Integer areaType; + + /** + * 围栏坐标数据 + */ + @ExcelProperty(value = "围栏坐标数据") + private String coordinates; + + /** + * 圆形围栏半径(米) + */ + @ExcelProperty(value = "圆形围栏半径(米)") + private Long radius; + + /** + * 是否激活 + */ + @ExcelProperty(value = "是否激活") + private Long isActive; + + /** + * 创建人 + */ + @ExcelProperty(value = "创建人") + private Long createdBy; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createdTime; + + /** + * 更新时间 + */ + @ExcelProperty(value = "更新时间") + private Date updatedTime; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java index d84f59ad..2ebecdc1 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java @@ -26,4 +26,24 @@ public class EquipmentClassificationVo { */ private Integer devices4GAndBluetooth = 0; + /** + * 设备总数 + */ + private Integer total; + + + /** + * 计算设备总数 + * + * @return 设备总数 + */ + public Integer getTotal() { + if (total == null) { + total = (equipment4G == null ? 0 : equipment4G) + + (deviceBluetooth == null ? 0 : deviceBluetooth) + + (devices4GAndBluetooth == null ? 0 : devices4GAndBluetooth); + } + return total; + } + } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceFenceAccessRecordMapper.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceFenceAccessRecordMapper.java new file mode 100644 index 00000000..f6f03f6d --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceFenceAccessRecordMapper.java @@ -0,0 +1,15 @@ +package com.fuyuanshen.equipment.mapper; + +import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus; +import com.fuyuanshen.equipment.domain.DeviceFenceAccessRecord; +import com.fuyuanshen.equipment.domain.vo.DeviceFenceAccessRecordVo; + +/** + * 围栏进出记录Mapper接口 + * + * @author Lion Li + * @date 2025-09-11 + */ +public interface DeviceFenceAccessRecordMapper extends BaseMapperPlus { + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceGeoFenceMapper.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceGeoFenceMapper.java new file mode 100644 index 00000000..f6352b93 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceGeoFenceMapper.java @@ -0,0 +1,15 @@ +package com.fuyuanshen.equipment.mapper; + +import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus; +import com.fuyuanshen.equipment.domain.DeviceGeoFence; +import com.fuyuanshen.equipment.domain.vo.DeviceGeoFenceVo; + +/** + * 电子围栏Mapper接口 + * + * @author Lion Li + * @date 2025-09-11 + */ +public interface DeviceGeoFenceMapper extends BaseMapperPlus { + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java index bd1f4e43..5d772caa 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java @@ -99,11 +99,11 @@ public interface DeviceMapper extends BaseMapper { /** * 获取设备使用数据 * - * @param deviceId 设备ID + * @param deviceTypeId 设备ID * @param range 时间范围 1:半年 2:一年 * @return 每月使用数据列表 */ - List> getEquipmentUsageData(Long deviceId, Integer range); + List> getEquipmentUsageData(@Param("deviceTypeId") Long deviceTypeId, @Param("range") Integer range); // 在DeviceMapper.java中添加方法 int getUsageDataForMonth(@Param("deviceId") Long deviceId, diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java index 777f62bf..bae56010 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java @@ -139,9 +139,9 @@ public interface DeviceService extends IService { /** * 获取设备使用数据 * - * @param deviceId + * @param deviceTypeId * @param range * @return */ - List> getEquipmentUsageData(Long deviceId, Integer range); + List> getEquipmentUsageData(Long deviceTypeId, Integer range); } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceFenceAccessRecordService.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceFenceAccessRecordService.java new file mode 100644 index 00000000..0d596719 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceFenceAccessRecordService.java @@ -0,0 +1,68 @@ +package com.fuyuanshen.equipment.service; + +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.equipment.domain.bo.DeviceFenceAccessRecordBo; +import com.fuyuanshen.equipment.domain.vo.DeviceFenceAccessRecordVo; + +import java.util.Collection; +import java.util.List; + +/** + * 围栏进出记录Service接口 + * + * @author Lion Li + * @date 2025-09-11 + */ +public interface IDeviceFenceAccessRecordService { + + /** + * 查询围栏进出记录 + * + * @param id 主键 + * @return 围栏进出记录 + */ + DeviceFenceAccessRecordVo queryById(Long id); + + /** + * 分页查询围栏进出记录列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 围栏进出记录分页列表 + */ + TableDataInfo queryPageList(DeviceFenceAccessRecordBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的围栏进出记录列表 + * + * @param bo 查询条件 + * @return 围栏进出记录列表 + */ + List queryList(DeviceFenceAccessRecordBo bo); + + /** + * 新增围栏进出记录 + * + * @param bo 围栏进出记录 + * @return 是否新增成功 + */ + Boolean insertByBo(DeviceFenceAccessRecordBo bo); + + /** + * 修改围栏进出记录 + * + * @param bo 围栏进出记录 + * @return 是否修改成功 + */ + Boolean updateByBo(DeviceFenceAccessRecordBo bo); + + /** + * 校验并批量删除围栏进出记录信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceGeoFenceService.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceGeoFenceService.java new file mode 100644 index 00000000..69a7d8f3 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceGeoFenceService.java @@ -0,0 +1,78 @@ +package com.fuyuanshen.equipment.service; + +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.equipment.domain.bo.DeviceGeoFenceBo; +import com.fuyuanshen.equipment.domain.dto.FenceCheckResponse; +import com.fuyuanshen.equipment.domain.query.FenceCheckRequest; +import com.fuyuanshen.equipment.domain.vo.DeviceGeoFenceVo; + +import java.util.Collection; +import java.util.List; + +/** + * 电子围栏Service接口 + * + * @author Lion Li + * @date 2025-09-11 + */ +public interface IDeviceGeoFenceService { + + /** + * 查询电子围栏 + * + * @param id 主键 + * @return 电子围栏 + */ + DeviceGeoFenceVo queryById(Long id); + + /** + * 分页查询电子围栏列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 电子围栏分页列表 + */ + TableDataInfo queryPageList(DeviceGeoFenceBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的电子围栏列表 + * + * @param bo 查询条件 + * @return 电子围栏列表 + */ + List queryList(DeviceGeoFenceBo bo); + + /** + * 新增电子围栏 + * + * @param bo 电子围栏 + * @return 是否新增成功 + */ + Boolean insertByBo(DeviceGeoFenceBo bo); + + /** + * 修改电子围栏 + * + * @param bo 电子围栏 + * @return 是否修改成功 + */ + Boolean updateByBo(DeviceGeoFenceBo bo); + + /** + * 校验并批量删除电子围栏信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 检查设备位置与围栏的关系 + * + * @param request 位置检查请求 + * @return 位置检查结果 + */ + FenceCheckResponse checkPosition(FenceCheckRequest request); +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceFenceAccessRecordServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceFenceAccessRecordServiceImpl.java new file mode 100644 index 00000000..a09f8386 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceFenceAccessRecordServiceImpl.java @@ -0,0 +1,140 @@ +package com.fuyuanshen.equipment.service.impl; + +import com.fuyuanshen.common.core.utils.MapstructUtils; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.fuyuanshen.equipment.domain.DeviceFenceAccessRecord; +import com.fuyuanshen.equipment.domain.bo.DeviceFenceAccessRecordBo; +import com.fuyuanshen.equipment.domain.vo.DeviceFenceAccessRecordVo; +import com.fuyuanshen.equipment.mapper.DeviceFenceAccessRecordMapper; +import com.fuyuanshen.equipment.service.IDeviceFenceAccessRecordService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 围栏进出记录Service业务层处理 + * + * @author Lion Li + * @date 2025-09-11 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class DeviceFenceAccessRecordServiceImpl implements IDeviceFenceAccessRecordService { + + private final DeviceFenceAccessRecordMapper baseMapper; + + /** + * 查询围栏进出记录 + * + * @param id 主键 + * @return 围栏进出记录 + */ + @Override + public DeviceFenceAccessRecordVo queryById(Long id){ + return baseMapper.selectVoById(id); + } + + /** + * 分页查询围栏进出记录列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 围栏进出记录分页列表 + */ + @Override + public TableDataInfo queryPageList(DeviceFenceAccessRecordBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的围栏进出记录列表 + * + * @param bo 查询条件 + * @return 围栏进出记录列表 + */ + @Override + public List queryList(DeviceFenceAccessRecordBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(DeviceFenceAccessRecordBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByAsc(DeviceFenceAccessRecord::getId); + lqw.eq(bo.getFenceId() != null, DeviceFenceAccessRecord::getFenceId, bo.getFenceId()); + lqw.eq(StringUtils.isNotBlank(bo.getDeviceId()), DeviceFenceAccessRecord::getDeviceId, bo.getDeviceId()); + lqw.eq(bo.getUserId() != null, DeviceFenceAccessRecord::getUserId, bo.getUserId()); + lqw.eq(bo.getEventType() != null, DeviceFenceAccessRecord::getEventType, bo.getEventType()); + lqw.eq(bo.getLatitude() != null, DeviceFenceAccessRecord::getLatitude, bo.getLatitude()); + lqw.eq(bo.getLongitude() != null, DeviceFenceAccessRecord::getLongitude, bo.getLongitude()); + lqw.eq(bo.getAccuracy() != null, DeviceFenceAccessRecord::getAccuracy, bo.getAccuracy()); + lqw.eq(bo.getEventTime() != null, DeviceFenceAccessRecord::getEventTime, bo.getEventTime()); + lqw.eq(bo.getCreatedTime() != null, DeviceFenceAccessRecord::getCreatedTime, bo.getCreatedTime()); + return lqw; + } + + /** + * 新增围栏进出记录 + * + * @param bo 围栏进出记录 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(DeviceFenceAccessRecordBo bo) { + DeviceFenceAccessRecord add = MapstructUtils.convert(bo, DeviceFenceAccessRecord.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改围栏进出记录 + * + * @param bo 围栏进出记录 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(DeviceFenceAccessRecordBo bo) { + DeviceFenceAccessRecord update = MapstructUtils.convert(bo, DeviceFenceAccessRecord.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(DeviceFenceAccessRecord entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除围栏进出记录信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceGeoFenceServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceGeoFenceServiceImpl.java new file mode 100644 index 00000000..c5fbb2df --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceGeoFenceServiceImpl.java @@ -0,0 +1,199 @@ +package com.fuyuanshen.equipment.service.impl; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fuyuanshen.common.core.utils.MapstructUtils; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.fuyuanshen.equipment.domain.DeviceGeoFence; +import com.fuyuanshen.equipment.domain.bo.DeviceGeoFenceBo; +import com.fuyuanshen.equipment.domain.dto.FenceCheckResponse; +import com.fuyuanshen.equipment.domain.query.FenceCheckRequest; +import com.fuyuanshen.equipment.domain.vo.DeviceGeoFenceVo; +import com.fuyuanshen.equipment.mapper.DeviceGeoFenceMapper; +import com.fuyuanshen.equipment.service.IDeviceGeoFenceService; +import com.fuyuanshen.equipment.utils.map.GeoFenceChecker; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 电子围栏Service业务层处理 + * + * @author Lion Li + * @date 2025-09-11 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class DeviceGeoFenceServiceImpl implements IDeviceGeoFenceService { + + private final DeviceGeoFenceMapper baseMapper; + + /** + * 查询电子围栏 + * + * @param id 主键 + * @return 电子围栏 + */ + @Override + public DeviceGeoFenceVo queryById(Long id) { + return baseMapper.selectVoById(id); + } + + /** + * 分页查询电子围栏列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 电子围栏分页列表 + */ + @Override + public TableDataInfo queryPageList(DeviceGeoFenceBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的电子围栏列表 + * + * @param bo 查询条件 + * @return 电子围栏列表 + */ + @Override + public List queryList(DeviceGeoFenceBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(DeviceGeoFenceBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByAsc(DeviceGeoFence::getId); + lqw.like(StringUtils.isNotBlank(bo.getName()), DeviceGeoFence::getName, bo.getName()); + lqw.eq(StringUtils.isNotBlank(bo.getDescription()), DeviceGeoFence::getDescription, bo.getDescription()); + lqw.eq(bo.getAreaType() != null, DeviceGeoFence::getAreaType, bo.getAreaType()); + lqw.eq(StringUtils.isNotBlank(bo.getCoordinates()), DeviceGeoFence::getCoordinates, bo.getCoordinates()); + lqw.eq(bo.getRadius() != null, DeviceGeoFence::getRadius, bo.getRadius()); + lqw.eq(bo.getIsActive() != null, DeviceGeoFence::getIsActive, bo.getIsActive()); + lqw.eq(bo.getCreatedBy() != null, DeviceGeoFence::getCreatedBy, bo.getCreatedBy()); + lqw.eq(bo.getCreatedTime() != null, DeviceGeoFence::getCreatedTime, bo.getCreatedTime()); + lqw.eq(bo.getUpdatedTime() != null, DeviceGeoFence::getUpdatedTime, bo.getUpdatedTime()); + return lqw; + } + + /** + * 新增电子围栏 + * + * @param bo 电子围栏 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(DeviceGeoFenceBo bo) { + DeviceGeoFence add = MapstructUtils.convert(bo, DeviceGeoFence.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改电子围栏 + * + * @param bo 电子围栏 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(DeviceGeoFenceBo bo) { + DeviceGeoFence update = MapstructUtils.convert(bo, DeviceGeoFence.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(DeviceGeoFence entity) { + // TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除电子围栏信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + // TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } + + + /** + * 检查设备位置与围栏的关系 + * + * @param request 位置检查请求 + * @return 位置检查结果 + */ + @Override + public FenceCheckResponse checkPosition(FenceCheckRequest request) { + // 1. 获取所有激活的围栏 + DeviceGeoFenceBo bo = new DeviceGeoFenceBo(); + bo.setIsActive(1L); // 假设1表示激活状态 + List activeFences = queryList(bo); + + // 2. 判断设备位置与各围栏的关系 + FenceCheckResponse response = new FenceCheckResponse(); + response.setDeviceId(request.getDeviceId()); + response.setCheckTime(System.currentTimeMillis()); + + // 这里需要实现具体的围栏判断逻辑 + // 根据您之前提供的算法实现点在围栏内的判断 + + for (DeviceGeoFenceVo fence : activeFences) { + String coordinates = fence.getCoordinates(); + + // 在需要转换的地方 + ObjectMapper objectMapper = new ObjectMapper(); + List coordinateList = List.of(); + try { + coordinateList = objectMapper.readValue(coordinates, + new TypeReference>() { + }); + } catch (Exception e) { + // 处理解析异常 + log.error("坐标数据解析失败: {}", e.getMessage()); + } + + FenceCheckResponse.FenceInfo fenceInfo = new FenceCheckResponse.FenceInfo(); + boolean pointInFence = GeoFenceChecker.isPointInFence(request.getLatitude(), request.getLongitude(), fence.getAreaType(), coordinateList, fence.getRadius()); + if (pointInFence) { + fenceInfo.setFenceId(fence.getId()); + fenceInfo.setFenceName(fence.getName()); + fenceInfo.setFenceType(fence.getAreaType()); + response.getEnteredFences().add(fenceInfo); + } else { + response.getExitedFences().add(fenceInfo); + } + } + + return response; + } + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java index 967bc391..5646e991 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java @@ -630,6 +630,7 @@ public class DeviceServiceImpl extends ServiceImpl impleme @Override public EquipmentClassificationVo getEquipmentClassification() { EquipmentClassificationVo equipmentClassification = deviceMapper.getEquipmentClassification(); + equipmentClassification.getTotal(); return equipmentClassification; } @@ -648,13 +649,13 @@ public class DeviceServiceImpl extends ServiceImpl impleme /** * 获取设备使用数据 * - * @param deviceId 设备ID + * @param deviceTypeId 设备ID * @param range 时间范围 1:半年 2:一年 * @return 每月使用数据列表 */ @Override - public List> getEquipmentUsageData(Long deviceId, Integer range) { - List> equipmentUsageData = deviceMapper.getEquipmentUsageData(deviceId, range); + public List> getEquipmentUsageData(Long deviceTypeId, Integer range) { + List> equipmentUsageData = deviceMapper.getEquipmentUsageData(deviceTypeId, range); return equipmentUsageData; } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/Coordinate.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/Coordinate.java new file mode 100644 index 00000000..781c9a23 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/Coordinate.java @@ -0,0 +1,24 @@ +package com.fuyuanshen.equipment.utils.map; + +/** + * @author: 默苍璃 + * @date: 2025-09-1110:27 + */ +public class Coordinate { + private double lat; + private double lng; + + // 构造函数 + public Coordinate() {} + + public Coordinate(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + + // getter和setter方法 + public double getLat() { return lat; } + public void setLat(double lat) { this.lat = lat; } + public double getLng() { return lng; } + public void setLng(double lng) { this.lng = lng; } +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/GeoFenceChecker.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/GeoFenceChecker.java new file mode 100644 index 00000000..5f38139c --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/GeoFenceChecker.java @@ -0,0 +1,135 @@ +package com.fuyuanshen.equipment.utils.map; + +import java.util.List; + +/** + * @author: 默苍璃 + * @date: 2025-09-1110:13 + */ +public class GeoFenceChecker { + + /** + * 点是否在围栏内 + * + * @param pointLat 点的纬度 + * @param pointLng 点的经度 + * @param fenceType 围栏类型:0 POLYGON 或 1 CIRCLE + * @param coordinates 围栏坐标点列表 + * @param radius 圆形围栏半径(米),仅对CIRCLE类型有效 + * @return true表示在围栏内,false表示在围栏外 + */ + public static boolean isPointInFence(double pointLat, double pointLng, + Integer fenceType, + List coordinates, + Long radius) { + if (fenceType == 0) { + return isPointInPolygon(pointLat, pointLng, coordinates); + } else if (fenceType == 1) { + if (coordinates == null || coordinates.isEmpty() || radius == null) { + return false; + } + // 圆形围栏只有一个坐标点(圆心) + Coordinate center = coordinates.get(0); + return isPointInCircle(pointLat, pointLng, center.lat, center.lng, radius); + } + return false; + } + + /** + * 使用射线投射算法判断点是否在多边形内 + * + * @param pointLat 点的纬度 + * @param pointLng 点的经度 + * @param polygon 多边形顶点坐标列表 + * @return true表示在多边形内,false表示在多边形外 + */ + public static boolean isPointInPolygon(double pointLat, double pointLng, + List polygon) { + if (polygon == null || polygon.size() < 3) { + return false; + } + + int intersectCount = 0; + int vertexCount = polygon.size(); + + // 遍历多边形的每条边 + for (int i = 0; i < vertexCount; i++) { + Coordinate p1 = polygon.get(i); + Coordinate p2 = polygon.get((i + 1) % vertexCount); + + // 检查点是否在边的y范围内 + if (p1.lat != p2.lat && + (pointLat >= Math.min(p1.lat, p2.lat)) && + (pointLat < Math.max(p1.lat, p2.lat))) { + + // 计算边与从点发出的水平射线的交点经度 + double intersectLng = (pointLat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) + p1.lng; + + // 如果交点在点的右侧,则计数加1 + if (pointLng < intersectLng) { + intersectCount++; + } + } + } + + // 奇数个交点表示点在多边形内 + return intersectCount % 2 == 1; + } + + /** + * 判断点是否在圆形内 + * + * @param pointLat 点的纬度 + * @param pointLng 点的经度 + * @param centerLat 圆心纬度 + * @param centerLng 圆心经度 + * @param radius 半径(米) + * @return true表示在圆内,false表示在圆外 + */ + public static boolean isPointInCircle(double pointLat, double pointLng, + double centerLat, double centerLng, + Long radius) { + double distance = calculateDistance(pointLat, pointLng, centerLat, centerLng); + return distance <= radius; + } + + /** + * 计算两点间距离(使用Haversine公式) + * + * @param lat1 点1纬度 + * @param lng1 点1经度 + * @param lat2 点2纬度 + * @param lng2 点2经度 + * @return 距离(米) + */ + public static double calculateDistance(double lat1, double lng1, double lat2, double lng2) { + final double EARTH_RADIUS = 6371000; // 地球半径(米) + + double dLat = Math.toRadians(lat2 - lat1); + double dLng = Math.toRadians(lng2 - lng1); + + double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * + Math.sin(dLng / 2) * Math.sin(dLng / 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + return EARTH_RADIUS * c; + } + + /** + * 坐标点类 + */ + public static class Coordinate { + public double lat; + public double lng; + + public Coordinate() { + } + + public Coordinate(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + } +} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceFenceAccessRecordMapper.xml b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceFenceAccessRecordMapper.xml new file mode 100644 index 00000000..2667e1b3 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceFenceAccessRecordMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceGeoFenceMapper.xml b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceGeoFenceMapper.xml new file mode 100644 index 00000000..1590ebe0 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceGeoFenceMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml index 81c66744..4d1a80fd 100644 --- a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml +++ b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml @@ -321,11 +321,14 @@ @@ -347,55 +350,67 @@