From bc8f980e912825eaaadaf9fdd2367f443a56de02 Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Sat, 07 Mar 2026 10:17:19 +0800
Subject: [PATCH] 2026-03-07 标记功能接口,支持点、线、面、圆标记存储
---
ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationDirectoryMapper.java | 9
ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationServiceImpl.java | 64 ++++
ard-sample/src/main/java/com/ard/sample/annotation/util/JsonSerializeUtil.java | 32 ++
ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationDirectoryService.java | 19 +
ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationService.java | 18 +
ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationMapper.java | 14 +
ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDTO.java | 37 ++
ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDirectoryDTO.java | 31 ++
ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationEntity.java | 50 +++
ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationPointsDTO.java | 26 ++
ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationDirectoryEntity.java | 33 ++
ard-sample/src/main/java/com/ard/sample/annotation/util/ConvertUtil.java | 57 ++++
ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationDirectoryServiceImpl.java | 147 +++++++++++
ard-admin/src/main/java/com/ard/web/controller/sample/AnnotationController.java | 197 +++++++++++++++
14 files changed, 734 insertions(+), 0 deletions(-)
diff --git a/ard-admin/src/main/java/com/ard/web/controller/sample/AnnotationController.java b/ard-admin/src/main/java/com/ard/web/controller/sample/AnnotationController.java
new file mode 100644
index 0000000..a6c0f77
--- /dev/null
+++ b/ard-admin/src/main/java/com/ard/web/controller/sample/AnnotationController.java
@@ -0,0 +1,197 @@
+package com.ard.web.controller.sample;
+
+import com.ard.sample.annotation.model.dto.AnnotationDTO;
+import com.ard.sample.annotation.model.dto.AnnotationDirectoryDTO;
+import com.ard.sample.annotation.model.entity.AnnotationDirectoryEntity;
+import com.ard.sample.annotation.model.entity.AnnotationEntity;
+import com.ard.sample.annotation.service.IAnnotationDirectoryService;
+import com.ard.sample.annotation.service.IAnnotationService;
+import com.ard.sample.annotation.util.ConvertUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Api(tags = "标注管理")
+@Slf4j
+@RestController
+@RequestMapping("/annotation")
+@RequiredArgsConstructor
+public class AnnotationController {
+
+ private final IAnnotationDirectoryService directoryService;
+ private final IAnnotationService annotationService;
+
+ // ====================== 目录接口 ======================
+ @ApiOperation("新增目录")
+ @PostMapping("/directory")
+ public ResponseEntity<Map<String, Object>> addDirectory(@RequestBody AnnotationDirectoryEntity entity) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+ //AnnotationDirectoryEntity entity = ConvertUtil.directoryDtoToEntity(dto);
+ boolean success = directoryService.addDirectory(entity);
+ result.put("success", success);
+ result.put("msg", success ? "目录新增成功" : "目录新增失败");
+ result.put("data", entity.getId()); // 返回新增ID
+ } catch (Exception e) {
+ log.error("新增目录异常", e);
+ result.put("success", false);
+ result.put("msg", "新增目录失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ @ApiOperation("修改目录")
+ @PutMapping("/directory")
+ public ResponseEntity<Map<String, Object>> editDirectory(@RequestBody AnnotationDirectoryEntity entity) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+// AnnotationDirectoryEntity entity = ConvertUtil.directoryDtoToEntity(dto);
+ boolean success = directoryService.editDirectory(entity);
+ result.put("success", success);
+ result.put("msg", success ? "目录修改成功" : "目录修改失败");
+ } catch (Exception e) {
+ log.error("修改目录异常", e);
+ result.put("success", false);
+ result.put("msg", "修改目录失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ @ApiOperation("删除目录及子项")
+ @DeleteMapping("/directory/{id}")
+ public ResponseEntity<Map<String, Object>> deleteDirectory(@PathVariable Integer id) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+ boolean success = directoryService.deleteDirectory(id);
+ result.put("success", success);
+ result.put("msg", success ? "目录删除成功" : "目录删除失败");
+ } catch (Exception e) {
+ log.error("删除目录异常", e);
+ result.put("success", false);
+ result.put("msg", "删除目录失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+
+ // ====================== 标记接口 ======================
+ @ApiOperation("新增标记")
+ @PostMapping
+ public ResponseEntity<Map<String, Object>> addAnnotation(@RequestBody AnnotationDTO dto) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+ AnnotationEntity entity = ConvertUtil.annotationDtoToEntity(dto);
+ boolean success = annotationService.addAnnotation(entity);
+ result.put("success", success);
+ result.put("msg", success ? "标记新增成功" : "标记新增失败");
+ result.put("data", entity.getId());
+ } catch (Exception e) {
+ log.error("新增标记异常", e);
+ result.put("success", false);
+ result.put("msg", "新增标记失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ @ApiOperation("修改标记")
+ @PutMapping
+ public ResponseEntity<Map<String, Object>> editAnnotation(@RequestBody AnnotationDTO dto) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+ AnnotationEntity entity = ConvertUtil.annotationDtoToEntity(dto);
+ boolean success = annotationService.editAnnotation(entity);
+ result.put("success", success);
+ result.put("msg", success ? "标记修改成功" : "标记修改失败");
+ } catch (Exception e) {
+ log.error("修改标记异常", e);
+ result.put("success", false);
+ result.put("msg", "修改标记失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ @ApiOperation("删除标记")
+ @DeleteMapping("/{id}")
+ public ResponseEntity<Map<String, Object>> deleteAnnotation(@PathVariable Integer id) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+ boolean success = annotationService.deleteAnnotation(id);
+ result.put("success", success);
+ result.put("msg", success ? "标记删除成功" : "标记删除失败");
+ } catch (Exception e) {
+ log.error("删除标记异常", e);
+ result.put("success", false);
+ result.put("msg", "删除标记失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ @ApiOperation("批量删除标记")
+ @DeleteMapping("/batch")
+ public ResponseEntity<Map<String, Object>> batchDeleteAnnotation(@RequestBody List<Integer> ids) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+ boolean success = annotationService.batchDeleteAnnotation(ids);
+ result.put("success", success);
+ result.put("msg", success ? "标记批量删除成功" : "标记批量删除失败");
+ } catch (Exception e) {
+ log.error("批量删除标记异常", e);
+ result.put("success", false);
+ result.put("msg", "批量删除标记失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ // 层级查询:目录→标记→坐标
+ @ApiOperation("按目标id获取所有目录及子标记信息")
+ @GetMapping("/directory/{directoryId}")
+ public ResponseEntity<Map<String, Object>> getDirectoryWithAnnotations(@PathVariable Integer directoryId) {
+ Map<String, Object> result = new HashMap<>();
+ try {
+ // 1. 查询目录
+ AnnotationDirectoryEntity dirEntity = directoryService.getById(directoryId);
+ if (dirEntity == null) {
+ result.put("success", false);
+ result.put("msg", "目录不存在");
+ return ResponseEntity.ok(result);
+ }
+ AnnotationDirectoryDTO dirDto = ConvertUtil.directoryEntityToDto(dirEntity);
+
+ // 2. 查询目录下标记
+ List<AnnotationEntity> annoEntities = annotationService.listByDirectoryId(directoryId);
+ List<AnnotationDTO> annoDtos = ConvertUtil.annotationEntityListToDtoList(annoEntities);
+ dirDto.setAnnotations(annoDtos);
+
+ result.put("success", true);
+ result.put("data", dirDto);
+ } catch (Exception e) {
+ log.error("查询目录及标记异常", e);
+ result.put("success", false);
+ result.put("msg", "查询失败:" + e.getMessage());
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ /**
+ * 新增:获取全部目录及下属标注数据
+ */
+ @ApiOperation("获取全部目录及下属标注数据")
+ @GetMapping("/directory/all")
+ public ResponseEntity<Map<String, Object>> listAllDirectoryWithAnnotations() {
+ List<AnnotationDirectoryDTO> directoryList = directoryService.listAllDirectoryWithAnnotations();
+
+ Map<String, Object> result = new HashMap<>();
+ result.put("success", true);
+ result.put("msg", "查询全部目录及标注成功");
+ result.put("data", directoryList);
+
+ return ResponseEntity.ok(result);
+ }
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationDirectoryMapper.java b/ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationDirectoryMapper.java
new file mode 100644
index 0000000..b14dfcb
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationDirectoryMapper.java
@@ -0,0 +1,9 @@
+package com.ard.sample.annotation.mapper;
+
+import com.ard.sample.annotation.model.entity.AnnotationDirectoryEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AnnotationDirectoryMapper extends BaseMapper<AnnotationDirectoryEntity> {
+}
\ No newline at end of file
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationMapper.java b/ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationMapper.java
new file mode 100644
index 0000000..192ad4a
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/mapper/AnnotationMapper.java
@@ -0,0 +1,14 @@
+package com.ard.sample.annotation.mapper;
+
+import com.ard.sample.annotation.model.entity.AnnotationEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface AnnotationMapper extends BaseMapper<AnnotationEntity> {
+ // 按目录ID查询标记列表
+ List<AnnotationEntity> selectByDirectoryId(@Param("directoryId") Integer directoryId);
+}
\ No newline at end of file
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDTO.java b/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDTO.java
new file mode 100644
index 0000000..66ea70c
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDTO.java
@@ -0,0 +1,37 @@
+package com.ard.sample.annotation.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class AnnotationDTO {
+
+ private Integer id;
+
+ private Integer directoryId;
+
+ private String name;
+
+ private String color;
+
+ private String annotationType;
+
+ private List<AnnotationPointsDTO> coordinateInfo;
+
+ private String imageUrl;
+
+ private String drawer;
+
+ private String description;
+
+ private Long createTime;
+
+ private Long updateTime;
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDirectoryDTO.java b/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDirectoryDTO.java
new file mode 100644
index 0000000..01afa6b
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationDirectoryDTO.java
@@ -0,0 +1,31 @@
+package com.ard.sample.annotation.model.dto;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 标注目录的DTO类
+ * */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class AnnotationDirectoryDTO {
+ private Integer id;
+
+ private String directoryName;
+
+ private List<AnnotationDTO> annotations; // 层级返回用
+
+ private String directoryRemark;
+
+ private Long createTime;
+
+ private Long updateTime;
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationPointsDTO.java b/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationPointsDTO.java
new file mode 100644
index 0000000..eab831b
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/model/dto/AnnotationPointsDTO.java
@@ -0,0 +1,26 @@
+package com.ard.sample.annotation.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 点、线、面、圆标注的DTO类
+ * */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AnnotationPointsDTO {
+
+ private Double longitude;
+
+ private Double latitude;
+
+ private Double height;
+
+ private Double radius;
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationDirectoryEntity.java b/ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationDirectoryEntity.java
new file mode 100644
index 0000000..50dd1c5
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationDirectoryEntity.java
@@ -0,0 +1,33 @@
+package com.ard.sample.annotation.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "annotation_directory")
+public class AnnotationDirectoryEntity implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @TableField(value = "directory_name")
+ private String directoryName;
+
+ @TableField(value = "directory_remark")
+ private String directoryRemark;
+
+ @TableField(value = "create_time", fill = FieldFill.INSERT)
+ private Long createTime;
+
+ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+ private Long updateTime;
+
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationEntity.java b/ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationEntity.java
new file mode 100644
index 0000000..3752036
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/model/entity/AnnotationEntity.java
@@ -0,0 +1,50 @@
+package com.ard.sample.annotation.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "annotation")
+public class AnnotationEntity implements Serializable {
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @TableField(value = "directory_id")
+ private Integer directoryId;
+
+ @TableField(value = "name")
+ private String name;
+
+ @TableField(value = "color")
+ private String color;
+
+ @TableField(value = "annotation_type")
+ private String annotationType;
+
+ @TableField(value = "coordinate_info")
+ private byte[] coordinateInfo;
+
+ @TableField(value = "image_url")
+ private String imageUrl;
+
+ @TableField(value = "drawer")
+ private String drawer;
+
+ @TableField(value = "description")
+ private String description;
+
+ @TableField(value = "create_time", fill = FieldFill.INSERT)
+ private Long createTime;
+
+ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+ private Long updateTime;
+
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationDirectoryService.java b/ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationDirectoryService.java
new file mode 100644
index 0000000..d302d19
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationDirectoryService.java
@@ -0,0 +1,19 @@
+package com.ard.sample.annotation.service;
+
+import com.ard.sample.annotation.model.dto.AnnotationDirectoryDTO;
+import com.ard.sample.annotation.model.entity.AnnotationDirectoryEntity;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+public interface IAnnotationDirectoryService extends IService<AnnotationDirectoryEntity> {
+ // 新增目录
+ boolean addDirectory(AnnotationDirectoryEntity entity);
+ // 修改目录
+ boolean editDirectory(AnnotationDirectoryEntity entity);
+ // 删除目录(级联删除标记)
+ boolean deleteDirectory(Integer id);
+
+ // 新增:查询全部目录(含下属标注数据)
+ List<AnnotationDirectoryDTO> listAllDirectoryWithAnnotations();
+}
\ No newline at end of file
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationService.java b/ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationService.java
new file mode 100644
index 0000000..da2707f
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/service/IAnnotationService.java
@@ -0,0 +1,18 @@
+package com.ard.sample.annotation.service;
+
+import com.ard.sample.annotation.model.entity.AnnotationEntity;
+import com.baomidou.mybatisplus.extension.service.IService;
+import java.util.List;
+
+public interface IAnnotationService extends IService<AnnotationEntity> {
+ // 新增标记
+ boolean addAnnotation(AnnotationEntity entity);
+ // 修改标记
+ boolean editAnnotation(AnnotationEntity entity);
+ // 删除标记
+ boolean deleteAnnotation(Integer id);
+ // 批量删除标记
+ boolean batchDeleteAnnotation(List<Integer> ids);
+ // 按目录ID查询标记
+ List<AnnotationEntity> listByDirectoryId(Integer directoryId);
+}
\ No newline at end of file
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationDirectoryServiceImpl.java b/ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationDirectoryServiceImpl.java
new file mode 100644
index 0000000..6ba5f04
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationDirectoryServiceImpl.java
@@ -0,0 +1,147 @@
+package com.ard.sample.annotation.service.impl;
+
+import com.ard.common.utils.bean.BeanUtils;
+import com.ard.sample.annotation.mapper.AnnotationMapper;
+import com.ard.sample.annotation.model.dto.AnnotationDTO;
+import com.ard.sample.annotation.model.dto.AnnotationDirectoryDTO;
+import com.ard.sample.annotation.model.entity.AnnotationDirectoryEntity;
+import com.ard.sample.annotation.model.entity.AnnotationEntity;
+import com.ard.sample.annotation.service.IAnnotationDirectoryService;
+import com.ard.sample.annotation.service.IAnnotationService;
+import com.ard.sample.annotation.util.JsonSerializeUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ard.sample.annotation.mapper.AnnotationDirectoryMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class AnnotationDirectoryServiceImpl extends ServiceImpl<AnnotationDirectoryMapper, AnnotationDirectoryEntity>
+ implements IAnnotationDirectoryService {
+
+ // 注入已实现的AnnotationService(而非直接用Mapper),复用其查询逻辑
+ private final IAnnotationService annotationService;
+
+ private final AnnotationMapper annotationMapper;
+
+ @Override
+ public boolean addDirectory(AnnotationDirectoryEntity entity) {
+ return save(entity);
+ }
+
+ @Override
+ public boolean editDirectory(AnnotationDirectoryEntity entity) {
+ if (entity.getId() == null) {
+ log.error("修改目录失败:ID为空");
+ return false;
+ }
+ return updateById(entity);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class) // 事务保证级联删除
+ public boolean deleteDirectory(Integer id) {
+ if (id == null) {
+ log.error("删除目录失败:ID为空");
+ return false;
+ }
+ // 1. 删除目录下所有标记
+ annotationMapper.deleteByMap(Map.of("directory_id", id));
+ // 2. 删除目录
+ boolean result = removeById(id);
+ log.info("删除目录{},结果:{}", id, result);
+ return result;
+ }
+
+ /**
+ * 查询全部目录(含下属标注数据)
+ * 修复点:替换自定义Mapper方法为MyBatis-Plus通用查询,避免SQL映射缺失问题
+ */
+ @Override
+ public List<AnnotationDirectoryDTO> listAllDirectoryWithAnnotations() {
+ // 1. 查询所有目录
+ List<AnnotationDirectoryEntity> directoryEntities = list();
+ if (directoryEntities.isEmpty()) {
+ return List.of();
+ }
+
+ // 2. 批量查询所有标注,按目录ID分组(减少数据库查询次数)
+ List<AnnotationEntity> allAnnotations = annotationService.list();
+ Map<Integer, List<AnnotationEntity>> annotationMap = allAnnotations.stream()
+ .collect(Collectors.groupingBy(AnnotationEntity::getDirectoryId));
+
+ // 3. 遍历目录,组装DTO(关联下属标注)
+ return directoryEntities.stream().map(directoryEntity -> {
+ AnnotationDirectoryDTO directoryDTO = AnnotationDirectoryDTO.builder().build();
+ BeanUtils.copyProperties(directoryEntity, directoryDTO);
+
+ // 4. 获取当前目录下的标注(从分组Map中获取,避免循环查库)
+ List<AnnotationEntity> annotationEntities = annotationMap.getOrDefault(directoryEntity.getId(), List.of());
+
+ // 5. 标注实体转DTO(反序列化坐标数据)
+ List<AnnotationDTO> annotationDTOList = annotationEntities.stream().map(annotationEntity -> {
+ AnnotationDTO annotationDTO = AnnotationDTO.builder().build();
+ BeanUtils.copyProperties(annotationEntity, annotationDTO);
+ try {
+ // 反序列化坐标数据
+ annotationDTO.setCoordinateInfo(
+ JsonSerializeUtil.deserialize(annotationEntity.getCoordinateInfo())
+ );
+ } catch (Exception e) {
+ log.error("反序列化标注坐标失败,标注ID:{}", annotationEntity.getId(), e);
+ annotationDTO.setCoordinateInfo(null);
+ }
+ return annotationDTO;
+ }).collect(Collectors.toList());
+
+ // 6. 设置目录下的标注列表
+ directoryDTO.setAnnotations(annotationDTOList);
+ return directoryDTO;
+ }).collect(Collectors.toList());
+ }
+
+// /**
+// * 查询全部目录(含下属标注数据)
+// */
+// @Override
+// public List<AnnotationDirectoryDTO> listAllDirectoryWithAnnotations() {
+// // 1. 查询所有目录
+// List<AnnotationDirectoryEntity> directoryEntities = list();
+//
+// // 2. 遍历目录,关联查询标注数据并组装DTO
+// return directoryEntities.stream().map(directoryEntity -> {
+// AnnotationDirectoryDTO directoryDTO = AnnotationDirectoryDTO.builder().build();
+// BeanUtils.copyProperties(directoryEntity, directoryDTO);
+//
+// // 3. 查询当前目录下的所有标注
+// List<AnnotationEntity> annotationEntities = annotationMapper.selectByDirectoryId(directoryEntity.getId());
+//
+// // 4. 标注实体转DTO(反序列化坐标数据)
+// List<AnnotationDTO> annotationDTOList = annotationEntities.stream().map(annotationEntity -> {
+// AnnotationDTO annotationDTO = AnnotationDTO.builder().build();
+// BeanUtils.copyProperties(annotationEntity, annotationDTO);
+// try {
+// // 反序列化坐标数据
+// annotationDTO.setCoordinateInfo(
+// JsonSerializeUtil.deserialize(annotationEntity.getCoordinateInfo())
+// );
+// } catch (Exception e) {
+// log.error("反序列化标注坐标失败,标注ID:{}", annotationEntity.getId(), e);
+// annotationDTO.setCoordinateInfo(null);
+// }
+// return annotationDTO;
+// }).collect(Collectors.toList());
+//
+// // 5. 给目录DTO设置下属标注列表(需先给AnnotationDirectoryDTO新增annotations字段)
+// directoryDTO.setAnnotations(annotationDTOList);
+// return directoryDTO;
+// }).collect(Collectors.toList());
+// }
+}
\ No newline at end of file
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationServiceImpl.java b/ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationServiceImpl.java
new file mode 100644
index 0000000..bf09f45
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/service/impl/AnnotationServiceImpl.java
@@ -0,0 +1,64 @@
+package com.ard.sample.annotation.service.impl;
+
+import com.ard.sample.annotation.mapper.AnnotationMapper;
+import com.ard.sample.annotation.model.entity.AnnotationEntity;
+import com.ard.sample.annotation.service.IAnnotationService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class AnnotationServiceImpl extends ServiceImpl<AnnotationMapper, AnnotationEntity>
+ implements IAnnotationService {
+
+ @Override
+ public boolean addAnnotation(AnnotationEntity entity) {
+ return save(entity);
+ }
+
+ @Override
+ public boolean editAnnotation(AnnotationEntity entity) {
+ if (entity.getId() == null) {
+ log.error("修改标记失败:ID为空");
+ return false;
+ }
+ return updateById(entity);
+ }
+
+ @Override
+ public boolean deleteAnnotation(Integer id) {
+ if (id == null) {
+ log.error("删除标记失败:ID为空");
+ return false;
+ }
+ boolean result = removeById(id);
+ log.info("删除标记{},结果:{}", id, result);
+ return result;
+ }
+
+ @Override
+ public boolean batchDeleteAnnotation(List<Integer> ids) {
+ if (CollectionUtils.isEmpty(ids)) {
+ log.error("批量删除标记失败:ID列表为空");
+ return false;
+ }
+ boolean result = removeByIds(ids);
+ log.info("批量删除标记{},结果:{}", ids, result);
+ return result;
+ }
+
+ @Override
+ public List<AnnotationEntity> listByDirectoryId(Integer directoryId) {
+ if (directoryId == null) {
+ log.error("按目录查询标记失败:目录ID为空");
+ return List.of();
+ }
+ return lambdaQuery().eq(AnnotationEntity::getDirectoryId, directoryId).list();
+ }
+}
\ No newline at end of file
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/util/ConvertUtil.java b/ard-sample/src/main/java/com/ard/sample/annotation/util/ConvertUtil.java
new file mode 100644
index 0000000..e39e7bb
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/util/ConvertUtil.java
@@ -0,0 +1,57 @@
+package com.ard.sample.annotation.util;
+
+import com.ard.sample.annotation.model.dto.AnnotationDTO;
+import com.ard.sample.annotation.model.dto.AnnotationDirectoryDTO;
+import com.ard.sample.annotation.model.dto.AnnotationPointsDTO;
+import com.ard.sample.annotation.model.entity.AnnotationDirectoryEntity;
+import com.ard.sample.annotation.model.entity.AnnotationEntity;
+import org.springframework.beans.BeanUtils;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ConvertUtil {
+ // 目录DTO → 目录Entity
+ public static AnnotationDirectoryEntity directoryDtoToEntity(AnnotationDirectoryDTO dto) {
+ AnnotationDirectoryEntity entity = new AnnotationDirectoryEntity();
+ BeanUtils.copyProperties(dto, entity);
+ return entity;
+ }
+
+ // 目录Entity → 目录DTO
+ public static AnnotationDirectoryDTO directoryEntityToDto(AnnotationDirectoryEntity entity) {
+ AnnotationDirectoryDTO dto = new AnnotationDirectoryDTO();
+ BeanUtils.copyProperties(entity, dto);
+ return dto;
+ }
+
+ // 标记DTO → 标记Entity(含坐标序列化)
+ public static AnnotationEntity annotationDtoToEntity(AnnotationDTO dto) throws Exception {
+ AnnotationEntity entity = new AnnotationEntity();
+ BeanUtils.copyProperties(dto, entity);
+ // 序列化坐标数据
+ entity.setCoordinateInfo(JsonSerializeUtil.serialize(dto.getCoordinateInfo()));
+ return entity;
+ }
+
+ // 标记Entity → 标记DTO(含坐标反序列化)
+ public static AnnotationDTO annotationEntityToDto(AnnotationEntity entity) throws Exception {
+ AnnotationDTO dto = new AnnotationDTO();
+ BeanUtils.copyProperties(entity, dto);
+ // 反序列化坐标数据
+ List<AnnotationPointsDTO> points = JsonSerializeUtil.deserialize(entity.getCoordinateInfo());
+ dto.setCoordinateInfo(points);
+ return dto;
+ }
+
+ // 标记Entity列表 → 标记DTO列表
+ public static List<AnnotationDTO> annotationEntityListToDtoList(List<AnnotationEntity> entityList) {
+ return entityList.stream().map(entity -> {
+ try {
+ return annotationEntityToDto(entity);
+ } catch (Exception e) {
+ throw new RuntimeException("标记Entity转DTO失败", e);
+ }
+ }).collect(Collectors.toList());
+ }
+}
\ No newline at end of file
diff --git a/ard-sample/src/main/java/com/ard/sample/annotation/util/JsonSerializeUtil.java b/ard-sample/src/main/java/com/ard/sample/annotation/util/JsonSerializeUtil.java
new file mode 100644
index 0000000..4f6c3bd
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/annotation/util/JsonSerializeUtil.java
@@ -0,0 +1,32 @@
+package com.ard.sample.annotation.util;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ard.sample.annotation.model.dto.AnnotationPointsDTO;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class JsonSerializeUtil {
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+
+ // 序列化:List<AnnotationPointsDTO> → byte[]
+ public static byte[] serialize(List<AnnotationPointsDTO> points) throws JsonProcessingException {
+ if (points == null) {
+ return null;
+ }
+ String json = objectMapper.writeValueAsString(points);
+ return json.getBytes();
+ }
+
+ // 反序列化:byte[] → List<AnnotationPointsDTO>
+ public static List<AnnotationPointsDTO> deserialize(byte[] bytes) throws JsonProcessingException {
+ if (bytes == null || bytes.length == 0) {
+ return null;
+ }
+ String json = new String(bytes);
+ return objectMapper.readValue(json,
+ objectMapper.getTypeFactory().constructCollectionType(List.class, AnnotationPointsDTO.class));
+ }
+}
\ No newline at end of file
--
Gitblit v1.9.3