diff --git a/pom.xml b/pom.xml
index aa1e152..fca73a7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,6 +59,21 @@
validation-api
2.0.1.Final
+
+ org.hibernate
+ hibernate-spatial
+ 5.4.32.Final
+
+
+ org.hibernate.validator
+ hibernate-validator
+ 6.2.0.Final
+
+
+ org.locationtech.jts
+ jts-core
+ 1.18.0
+
diff --git a/src/main/java/com/waterquality/projectmanagement/controller/FacilityController.java b/src/main/java/com/waterquality/projectmanagement/controller/FacilityController.java
new file mode 100644
index 0000000..89fa4db
--- /dev/null
+++ b/src/main/java/com/waterquality/projectmanagement/controller/FacilityController.java
@@ -0,0 +1,58 @@
+package com.waterquality.projectmanagement.controller;
+
+import com.waterquality.projectmanagement.Response;
+import com.waterquality.projectmanagement.dto.facility.FacilityCreateDTO;
+import com.waterquality.projectmanagement.dto.facility.FacilityVO;
+import com.waterquality.projectmanagement.entity.facility.FacilityStatus;
+import com.waterquality.projectmanagement.entity.facility.FacilityType;
+import com.waterquality.projectmanagement.service.FacilityService;
+import jakarta.validation.constraints.NotNull;
+import lombok.*;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+// FacilityController.java
+@RestController
+@RequestMapping("/api/facilities")
+@RequiredArgsConstructor
+public class FacilityController {
+
+ private final FacilityService facilityService;
+
+ @PostMapping
+ public ResponseEntity> create(
+ @Valid @RequestBody FacilityCreateDTO dto) {
+ return ResponseEntity.ok(Response.newSuccess(facilityService.createFacility(dto)));
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity> getById(@PathVariable Integer id) {
+ return ResponseEntity.ok(Response.newSuccess(
+ facilityService.convertToVO(facilityService.getFacilityById(id))));
+ }
+
+ @GetMapping("/search")
+ public ResponseEntity>> search(
+ @RequestParam(required = false) FacilityType type,
+ @RequestParam(required = false) FacilityStatus status,
+ @RequestParam(required = false) String area,
+ @PageableDefault Pageable pageable) {
+ return ResponseEntity.ok(Response.newSuccess(
+ facilityService.searchFacilities(type, status, area, pageable)));
+ }
+
+
+ @PatchMapping("/{id}/status")
+ public ResponseEntity> updateStatus(
+ @PathVariable Integer id,
+ @RequestParam @NotNull FacilityStatus status) {
+ facilityService.updateStatus(id, status);
+ return ResponseEntity.ok(Response.newSuccess(null));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/waterquality/projectmanagement/dto/facility/FacilityCreateDTO.java b/src/main/java/com/waterquality/projectmanagement/dto/facility/FacilityCreateDTO.java
new file mode 100644
index 0000000..73179cf
--- /dev/null
+++ b/src/main/java/com/waterquality/projectmanagement/dto/facility/FacilityCreateDTO.java
@@ -0,0 +1,37 @@
+package com.waterquality.projectmanagement.dto.facility;
+
+import com.waterquality.projectmanagement.entity.facility.FacilityType;
+import lombok.*;
+import org.hibernate.validator.constraints.Range;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.*;
+import java.time.LocalDate;
+
+@Data
+public class FacilityCreateDTO {
+ @NotBlank(message = "设施编码不能为空")
+ @Size(max = 30, message = "编码长度不能超过30字符")
+ private String code;
+
+ @NotNull(message = "设施类型不能为空")
+ private FacilityType type;
+
+ @NotNull(message = "经度不能为空")
+ @Range(min = -180, max = 180, message = "经度范围错误")
+ private Double longitude;
+
+ @NotNull(message = "纬度不能为空")
+ @Range(min = -90, max = 90, message = "纬度范围错误")
+ private Double latitude;
+
+ @NotBlank(message = "所属区域不能为空")
+ private String area;
+
+ @NotNull(message = "管理部门不能为空")
+ private Integer deptId;
+
+ @FutureOrPresent(message = "安装日期不能早于当前日期")
+ private LocalDate installDate;
+}
+
diff --git a/src/main/java/com/waterquality/projectmanagement/dto/facility/FacilityVO.java b/src/main/java/com/waterquality/projectmanagement/dto/facility/FacilityVO.java
new file mode 100644
index 0000000..614c3ef
--- /dev/null
+++ b/src/main/java/com/waterquality/projectmanagement/dto/facility/FacilityVO.java
@@ -0,0 +1,22 @@
+package com.waterquality.projectmanagement.dto.facility;
+
+import com.waterquality.projectmanagement.entity.facility.FacilityStatus;
+import com.waterquality.projectmanagement.entity.facility.FacilityType;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+// FacilityVO.java
+@Data
+public class FacilityVO {
+ private Integer id;
+ private String code;
+ private FacilityType type;
+ private String location;
+ private String area;
+ private FacilityStatus status;
+ private String deptName;
+ private LocalDate installDate;
+ private LocalDate lastMaintainDate;
+
+}
diff --git a/src/main/java/com/waterquality/projectmanagement/entity/facility/Facility.java b/src/main/java/com/waterquality/projectmanagement/entity/facility/Facility.java
index 9fdb850..249c1db 100644
--- a/src/main/java/com/waterquality/projectmanagement/entity/facility/Facility.java
+++ b/src/main/java/com/waterquality/projectmanagement/entity/facility/Facility.java
@@ -1,7 +1,11 @@
package com.waterquality.projectmanagement.entity.facility;
+import com.waterquality.projectmanagement.entity.department.Department;
import jakarta.persistence.*;
import lombok.*;
+import org.locationtech.jts.geom.Coordinate;
+
+import java.time.LocalDate;
@Entity
@Table(name = "facilities")
@@ -22,8 +26,7 @@ public class Facility {
@Column(name = "facility_type", nullable = false)
private FacilityType type;
- @Column(columnDefinition = "POINT SRID 4326 NOT NULL")
- private Point location;
+ private String location;
@Column(nullable = false, length = 100)
private String area;
@@ -33,7 +36,7 @@ public class Facility {
private FacilityStatus status = FacilityStatus.NORMAL;
@ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "responsible_dept", nullable = false)
+ @JoinColumn(name = "responsible_dept", nullable = true)
private Department responsibleDept;
@Column(name = "install_date")
@@ -43,20 +46,6 @@ public class Facility {
private LocalDate lastMaintainDate;
// 空间坐标转换方法
- public void setCoordinates(Double lng, Double lat) {
- this.location = GeometryUtils.createPoint(lng, lat);
- }
- public Coordinate getCoordinate() {
- return this.location.getCoordinate();
- }
}
-// 空间工具类
-public class GeometryUtils {
- private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
-
- public static Point createPoint(Double lng, Double lat) {
- return GEOMETRY_FACTORY.createPoint(new Coordinate(lng, lat));
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/waterquality/projectmanagement/repository/FacilityRepository.java b/src/main/java/com/waterquality/projectmanagement/repository/FacilityRepository.java
new file mode 100644
index 0000000..84b62d5
--- /dev/null
+++ b/src/main/java/com/waterquality/projectmanagement/repository/FacilityRepository.java
@@ -0,0 +1,49 @@
+package com.waterquality.projectmanagement.repository;
+
+import com.waterquality.projectmanagement.entity.department.Department;
+import com.waterquality.projectmanagement.entity.facility.Facility;
+import com.waterquality.projectmanagement.entity.facility.FacilityStatus;
+import com.waterquality.projectmanagement.entity.facility.FacilityType;
+import org.locationtech.jts.geom.Polygon;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+// FacilityRepository.java
+public interface FacilityRepository extends JpaRepository {
+
+ // 根据编码查询
+ Optional findByCode(String code);
+
+ // 空间范围查询(使用HQL)
+ // @Query("SELECT f FROM Facility f WHERE within(f.location, :polygon) = true")
+ // List findWithinArea(@Param("polygon") Polygon polygon);
+
+ // 状态统计(使用原生SQL)
+ @Query(value = "SELECT status, COUNT(*) as count FROM facilities GROUP BY status",
+ nativeQuery = true)
+ List