1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
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.core.conditions.update.LambdaUpdateWrapper;
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.ArrayList;
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 updateDirectoryVisible(String id, Boolean isTrue) {
        // 1. 参数校验
        if (id == null || id.isEmpty() || isTrue == null) {
            log.error("修改目录显示状态失败:参数非法,id={}, isTrue={}", id, isTrue);
            return false;
        }
        // 2. 修改目录自身的可见状态
        AnnotationDirectoryEntity directoryEntity = new AnnotationDirectoryEntity();
        directoryEntity.setId(id);
        directoryEntity.setIsTrue(isTrue);
        boolean dirUpdateResult = updateById(directoryEntity);
        if (!dirUpdateResult) {
            log.error("修改目录{}显示状态失败", id);
            return false;
        }
        // 3. 批量修改该目录下所有标注的可见状态(核心新增逻辑)
        LambdaUpdateWrapper<AnnotationEntity> annotationUpdateWrapper = new LambdaUpdateWrapper<>();
        annotationUpdateWrapper.eq(AnnotationEntity::getDirectoryId, id) // 匹配目录ID
                .set(AnnotationEntity::getIsTrue, isTrue); // 同步设置相同的可见状态
        boolean annotationUpdateResult = annotationService.update(annotationUpdateWrapper);
        // 简化日志:只记录操作结果
        log.info("目录{}显示状态修改成功(状态:{}),下属标注状态同步修改结果:{}",
                id, isTrue, annotationUpdateResult);
 
        // 4. 返回最终结果(目录修改成功且标注修改成功,或标注无数据时返回目录修改结果)
        return dirUpdateResult;
    }
 
    @Override
    @Transactional(rollbackFor = Exception.class) // 事务保证级联删除
    public boolean deleteDirectory(String id) {
        if (id == null || id.isEmpty()) {
            log.error("删除目录失败:ID为空");
            return false;
        }
        // ====================== 关键:不允许删除默认文件夹 ======================
        if ("default_directory_00000001".equals(id)) {
            log.error("删除目录失败:默认文件夹不允许删除");
            throw new RuntimeException("默认文件夹不允许删除");
        }
        // 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 = lambdaQuery()
//                .orderByDesc(AnnotationDirectoryEntity::getCreateTime) // 核心:目录按创建时间降序
//                .list();
//        if (directoryEntities.isEmpty()) {
//            return List.of();
//        }
//
//        // 2. 批量查询所有标注,按目录ID分组(减少数据库查询次数)
//        List<AnnotationEntity> allAnnotations = annotationService.list();
//        Map<String, 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. 获取当前目录下的标注,并按createTime降序排序
//            List<AnnotationEntity> annotationEntities = annotationMap.getOrDefault(directoryEntity.getId(), List.of())
//                    .stream()
//                    .sorted((a1, a2) -> a2.getCreateTime().compareTo(a1.getCreateTime())) // 标注按创建时间降序
//                    .collect(Collectors.toList());
//
//            // 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());
//    }
 
    /**
     * 查询全部目录(含下属标注数据)
     * 优化点:
     * 1. 默认文件夹固定置顶,其余目录按createTime降序排序
     * 2. 目录下的标注按createTime降序排序
     */
    @Override
    public List<AnnotationDirectoryDTO> listAllDirectoryWithAnnotations() {
        // 1. 查询所有目录(未排序)
        List<AnnotationDirectoryEntity> allDirectoryEntities = list();
        if (allDirectoryEntities.isEmpty()) {
            return List.of();
        }
 
        // 2. 拆分默认目录和普通目录
        String defaultDirId = "default_directory_00000001"; // 默认文件夹固定ID
        AnnotationDirectoryEntity defaultDirectory = null;
        List<AnnotationDirectoryEntity> normalDirectories = new ArrayList<>();
 
        for (AnnotationDirectoryEntity dir : allDirectoryEntities) {
            if (defaultDirId.equals(dir.getId())) {
                defaultDirectory = dir; // 筛选出默认目录
            } else {
                normalDirectories.add(dir); // 其余为普通目录
            }
        }
 
        // 3. 普通目录按createTime降序排序
        List<AnnotationDirectoryEntity> sortedNormalDirectories = normalDirectories.stream()
                .sorted((d1, d2) -> d2.getCreateTime().compareTo(d1.getCreateTime()))
                .collect(Collectors.toList());
 
        // 4. 组装最终的目录列表:默认目录(如果存在) + 排序后的普通目录
        List<AnnotationDirectoryEntity> finalDirectoryEntities = new ArrayList<>();
        if (defaultDirectory != null) {
            finalDirectoryEntities.add(defaultDirectory); // 默认目录置顶
        }
        finalDirectoryEntities.addAll(sortedNormalDirectories);
 
        // 5. 批量查询所有标注,按目录ID分组(减少数据库查询次数)
        List<AnnotationEntity> allAnnotations = annotationService.list();
        Map<String, List<AnnotationEntity>> annotationMap = allAnnotations.stream()
                .collect(Collectors.groupingBy(AnnotationEntity::getDirectoryId));
 
        // 6. 遍历组装DTO(逻辑不变,仅使用最终排序后的目录列表)
        return finalDirectoryEntities.stream().map(directoryEntity -> {
            AnnotationDirectoryDTO directoryDTO = AnnotationDirectoryDTO.builder().build();
            BeanUtils.copyProperties(directoryEntity, directoryDTO);
 
            // 7. 目录下的标注按createTime降序排序
            List<AnnotationEntity> annotationEntities = annotationMap.getOrDefault(directoryEntity.getId(), List.of())
                    .stream()
                    .sorted((a1, a2) -> a2.getCreateTime().compareTo(a1.getCreateTime()))
                    .collect(Collectors.toList());
 
            // 8. 标注实体转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());
 
            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());
//    }
}