lrj
2 天以前 9f8395fab13ca4b230a0f7d62636e209745c91d4
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
package com.rongyichuang.player.service;
 
import com.rongyichuang.player.dto.ActivityRegistrationInput;
import com.rongyichuang.player.dto.ActivityRegistrationResponse;
import com.rongyichuang.player.dto.MediaFileInput;
import com.rongyichuang.player.dto.response.PlayerRegistrationResponse;
import com.rongyichuang.player.entity.ActivityPlayer;
import com.rongyichuang.player.entity.Player;
import com.rongyichuang.player.repository.ActivityPlayerRepository;
import com.rongyichuang.player.repository.PlayerRepository;
import com.rongyichuang.common.entity.Media;
import com.rongyichuang.common.repository.MediaRepository;
import com.rongyichuang.common.enums.MediaTargetType;
import com.rongyichuang.common.util.UserContextUtil;
import com.rongyichuang.user.entity.User;
import com.rongyichuang.user.service.UserService;
import com.rongyichuang.media.service.MediaV2Service;
import com.rongyichuang.media.dto.MediaSaveInput;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
 
/**
 * 活动选手服务类
 */
@Service
@Transactional
public class ActivityPlayerService {
 
    private static final Logger log = LoggerFactory.getLogger(ActivityPlayerService.class);
 
    @Autowired
    private ActivityPlayerRepository activityPlayerRepository;
 
    @Autowired
    private PlayerRepository playerRepository;
 
    @Autowired
    private MediaRepository mediaRepository;
 
    @Autowired
    private UserContextUtil userContextUtil;
 
    @Autowired
    private UserService userService;
 
    @Autowired
    private MediaV2Service mediaV2Service;
 
 
 
    /**
     * 提交活动报名
     * @param input 报名输入信息
     * @return 报名结果
     */
    public ActivityRegistrationResponse submitActivityRegistration(ActivityRegistrationInput input) {
        try {
            log.info("开始处理活动报名,活动ID: {}, 选手姓名: {}", input.getActivityId(), input.getPlayerInfo().getName());
 
            // 1. 验证输入参数
            if (input.getActivityId() == null) {
                log.warn("活动ID为空");
                return ActivityRegistrationResponse.error("活动ID不能为空");
            }
            if (input.getPlayerInfo() == null || input.getPlayerInfo().getName() == null || input.getPlayerInfo().getName().trim().isEmpty()) {
                log.warn("选手姓名为空");
                return ActivityRegistrationResponse.error("选手姓名不能为空");
            }
            if (input.getPlayerInfo().getPhone() == null || input.getPlayerInfo().getPhone().trim().isEmpty()) {
                log.warn("联系电话为空");
                return ActivityRegistrationResponse.error("联系电话不能为空");
            }
 
            log.info("输入参数验证通过");
 
            // 2. 查找或创建选手记录
            log.info("开始查找或创建选手记录,手机号: {}", input.getPlayerInfo().getPhone());
            Player player = findOrCreatePlayer(input);
            if (player == null) {
                log.error("创建选手记录失败");
                return ActivityRegistrationResponse.error("创建选手记录失败");
            }
            log.info("选手记录处理成功,选手ID: {}", player.getId());
 
            // 3. 检查是否已经报名
            log.info("检查是否已经报名,活动ID: {}, 选手ID: {}", input.getActivityId(), player.getId());
            Optional<ActivityPlayer> existingRegistration = activityPlayerRepository
                    .findByActivityIdAndPlayerId(input.getActivityId(), player.getId());
            if (existingRegistration.isPresent()) {
                log.warn("选手已经报名过此活动");
                return ActivityRegistrationResponse.error("您已经报名过此活动");
            }
            log.info("未发现重复报名");
 
            // 4. 创建报名记录
            log.info("开始创建报名记录");
            ActivityPlayer activityPlayer = new ActivityPlayer();
            activityPlayer.setActivityId(input.getActivityId());
            activityPlayer.setStageId(input.getActivityId()); // 根据文档:如果比赛未定义阶段,stage_id设为activity_id
            activityPlayer.setPlayerId(player.getId());
            activityPlayer.setRegionId(input.getRegionId());
            activityPlayer.setProjectName(input.getProjectName()); // 设置项目名称
            activityPlayer.setDescription(input.getDescription());
            // BaseEntity会自动设置createTime和updateTime
            log.info("ActivityPlayer对象创建完成,准备保存到数据库");
 
            ActivityPlayer savedActivityPlayer = activityPlayerRepository.save(activityPlayer);
            log.info("报名记录创建成功,ID: {}", savedActivityPlayer.getId());
 
            // 5. 保存其他媒体文件(兼容旧版本)
            if (input.getMediaFiles() != null && !input.getMediaFiles().isEmpty()) {
                saveMediaFiles(savedActivityPlayer.getId(), input.getMediaFiles());
            }
 
            // 6. 保存头像媒体记录
            if (input.getPlayerInfo().getAvatarMediaId() != null && !input.getPlayerInfo().getAvatarMediaId().trim().isEmpty()) {
                savePlayerAvatarMedia(player.getId(), input.getPlayerInfo().getAvatarMediaId());
            }
 
            // 7. 保存附件媒体记录
            if (input.getAttachmentMediaIds() != null && !input.getAttachmentMediaIds().isEmpty()) {
                saveAttachmentMediaRecords(savedActivityPlayer.getId(), input.getAttachmentMediaIds());
            }
 
            return ActivityRegistrationResponse.success("报名成功", savedActivityPlayer.getId(), player.getId(), player.getUserId());
 
        } catch (Exception e) {
            log.error("处理活动报名时发生错误", e);
            return ActivityRegistrationResponse.error("报名失败:" + e.getMessage());
        }
    }
 
    /**
     * 查找或创建选手记录
     */
    private Player findOrCreatePlayer(ActivityRegistrationInput input) {
        try {
            // 先根据手机号查找现有选手
            String phone = input.getPlayerInfo().getPhone();
            Optional<Player> existingPlayerOpt = playerRepository.findByPhone(phone);
            
            if (existingPlayerOpt.isPresent()) {
                Player existingPlayer = existingPlayerOpt.get();
                // 更新选手信息
                existingPlayer.setName(input.getPlayerInfo().getName());
                if (input.getPlayerInfo().getGender() != null) {
                    existingPlayer.setGender(input.getPlayerInfo().getGender());
                }
                if (input.getPlayerInfo().getEducation() != null) {
                    existingPlayer.setEducation(input.getPlayerInfo().getEducation());
                }
                if (input.getPlayerInfo().getIntroduction() != null) {
                    existingPlayer.setIntroduction(input.getPlayerInfo().getIntroduction());
                }
                if (input.getPlayerInfo().getDescription() != null) {
                    existingPlayer.setDescription(input.getPlayerInfo().getDescription());
                }
                
                // 更新关联的用户信息(如果存在)
                updateUserInfo(existingPlayer, input);
                
                // BaseEntity会自动设置updateTime
                return playerRepository.save(existingPlayer);
            }
 
            // 创建新选手
            Player newPlayer = new Player();
            newPlayer.setName(input.getPlayerInfo().getName());
            newPlayer.setPhone(input.getPlayerInfo().getPhone());
            newPlayer.setGender(input.getPlayerInfo().getGender());
            newPlayer.setEducation(input.getPlayerInfo().getEducation());
            newPlayer.setIntroduction(input.getPlayerInfo().getIntroduction());
            newPlayer.setDescription(input.getPlayerInfo().getDescription());
            newPlayer.setRoleId(1L); // 默认角色ID为1(学员角色)
            newPlayer.setState(1); // 1表示有效状态
            
            // 创建或关联用户记录
            User user = createOrUpdateUser(input);
            newPlayer.setUserId(user.getId());
            
            // BaseEntity会自动设置createTime和updateTime
            Player savedPlayer = playerRepository.save(newPlayer);
            log.info("新选手创建成功,ID: {}, 姓名: {}", savedPlayer.getId(), savedPlayer.getName());
            return savedPlayer;
 
        } catch (Exception e) {
            log.error("查找或创建选手记录时发生错误", e);
            return null;
        }
    }
 
    /**
     * 创建或更新用户记录
     */
    private User createOrUpdateUser(ActivityRegistrationInput input) {
        try {
            // 使用UserService的findOrCreateUserByPhone方法
            User user = userService.findOrCreateUserByPhone(
                input.getPlayerInfo().getPhone(),
                input.getPlayerInfo().getName(),
                null // 不设置密码,使用默认密码
            );
            
            // 更新用户的生日信息
            if (input.getPlayerInfo().getBirthDate() != null) {
                user.setBirthday(input.getPlayerInfo().getBirthDate());
                user = userService.save(user);
                log.info("更新用户生日信息成功,用户ID: {}", user.getId());
            }
            
            return user;
        } catch (Exception e) {
            log.error("创建或更新用户记录时发生错误", e);
            throw new RuntimeException("创建或更新用户记录失败", e);
        }
    }
 
    /**
     * 更新现有选手关联的用户信息
     */
    private void updateUserInfo(Player existingPlayer, ActivityRegistrationInput input) {
        try {
            if (existingPlayer.getUserId() != null && existingPlayer.getUserId() > 0) {
                Optional<User> userOpt = userService.findById(existingPlayer.getUserId());
                if (userOpt.isPresent()) {
                    User user = userOpt.get();
                    // 更新用户姓名
                    user.setName(input.getPlayerInfo().getName());
                    // 更新生日信息
                    if (input.getPlayerInfo().getBirthDate() != null) {
                        user.setBirthday(input.getPlayerInfo().getBirthDate());
                    }
                    userService.save(user);
                    log.info("更新现有用户信息成功,用户ID: {}", user.getId());
                } else {
                    log.warn("未找到选手关联的用户记录,选手ID: {}, 用户ID: {}", existingPlayer.getId(), existingPlayer.getUserId());
                }
            } else {
                log.info("选手未关联用户记录,选手ID: {}", existingPlayer.getId());
            }
        } catch (Exception e) {
            log.error("更新用户信息时发生错误", e);
            // 不抛出异常,避免影响选手信息的更新
        }
    }
 
    /**
     * 保存媒体文件
     */
    private void saveMediaFiles(Long activityPlayerId, List<MediaFileInput> mediaFiles) {
        try {
            for (MediaFileInput mediaFile : mediaFiles) {
                Media media = new Media();
                media.setName(mediaFile.getName());
                media.setPath(mediaFile.getPath());
                media.setFileExt(mediaFile.getFileExt());
                media.setFileSize(mediaFile.getFileSize());
                media.setMediaType(mediaFile.getMediaType());
                media.setTargetType(MediaTargetType.ACTIVITY_PLAYER_SUBMISSION.getValue()); // 活动选手媒体文件
                media.setTargetId(activityPlayerId);
                media.setState(1); // 1表示有效状态
                // BaseEntity会自动设置createTime和updateTime
 
                mediaRepository.save(media);
                log.info("媒体文件保存成功,文件名: {}", mediaFile.getName());
            }
        } catch (Exception e) {
            log.error("保存媒体文件时发生错误", e);
        }
    }
 
    /**
     * 获取玩家在指定活动中的报名状态
     * @param activityId 活动ID
     * @return 报名状态信息
     */
    public PlayerRegistrationResponse getPlayerRegistration(Long activityId) {
        try {
            // 获取当前用户ID
            Long currentUserId = userContextUtil.getCurrentUserId();
            if (currentUserId == null) {
                log.warn("未找到当前用户信息");
                return null;
            }
 
            // 查找当前用户对应的Player记录
            Optional<Player> playerOpt = playerRepository.findByUserId(currentUserId);
            if (!playerOpt.isPresent()) {
                log.info("用户 {} 尚未创建Player记录", currentUserId);
                return null;
            }
 
            Player player = playerOpt.get();
            
            // 查找该玩家在指定活动中的报名记录
            Optional<ActivityPlayer> activityPlayerOpt = activityPlayerRepository
                    .findByActivityIdAndPlayerId(activityId, player.getId());
            
            if (!activityPlayerOpt.isPresent()) {
                log.info("玩家 {} 未在活动 {} 中报名", player.getId(), activityId);
                return null;
            }
 
            ActivityPlayer activityPlayer = activityPlayerOpt.get();
            
            // 构建响应对象
            PlayerRegistrationResponse response = new PlayerRegistrationResponse();
            response.setId(activityPlayer.getId());
            response.setStatus(activityPlayer.getState());
            response.setRegistrationTime(activityPlayer.getCreateTime() != null ? 
                    activityPlayer.getCreateTime().toString() : null);
            response.setReviewStatus(activityPlayer.getState()); // 使用state作为审核状态
            response.setReviewComment(activityPlayer.getDescription()); // 使用description作为审核备注
 
            log.info("成功获取玩家 {} 在活动 {} 中的报名状态", player.getId(), activityId);
            return response;
 
        } catch (Exception e) {
            log.error("获取玩家报名状态时发生错误,活动ID: {}", activityId, e);
            throw new RuntimeException("获取报名状态失败", e);
        }
    }
 
    /**
     * 保存学员头像
     * 参考judge模块的实现,将已上传的头像媒体文件关联到学员
     */
    private void savePlayerAvatar(Long playerId, Long avatarMediaId) {
        try {
            // 查找现有的头像记录并删除(确保一个学员只有一个头像)
            mediaRepository.deleteByTargetTypeAndTargetId(MediaTargetType.STUDENT_AVATAR.getValue(), playerId);
            
            // 更新媒体文件的target信息
            Media avatarMedia = mediaRepository.findById(avatarMediaId).orElse(null);
            if (avatarMedia != null) {
                avatarMedia.setTargetType(MediaTargetType.STUDENT_AVATAR.getValue());
                avatarMedia.setTargetId(playerId);
                mediaRepository.save(avatarMedia);
                log.info("学员头像保存成功,学员ID: {}, 媒体ID: {}", playerId, avatarMediaId);
            } else {
                log.warn("未找到头像媒体文件,媒体ID: {}", avatarMediaId);
            }
        } catch (Exception e) {
            log.error("保存学员头像时发生错误,学员ID: {}, 媒体ID: {}", playerId, avatarMediaId, e);
        }
    }
 
    /**
     * 保存附件媒体文件
     * 将已上传的附件媒体文件关联到活动报名记录
     */
    private void saveAttachmentMediaFiles(Long activityPlayerId, List<Long> attachmentMediaIds) {
        try {
            for (Long mediaId : attachmentMediaIds) {
                Media attachmentMedia = mediaRepository.findById(mediaId).orElse(null);
                if (attachmentMedia != null) {
                    attachmentMedia.setTargetType(MediaTargetType.ACTIVITY_PLAYER_SUBMISSION.getValue());
                    attachmentMedia.setTargetId(activityPlayerId);
                    mediaRepository.save(attachmentMedia);
                    log.info("附件媒体文件保存成功,报名ID: {}, 媒体ID: {}", activityPlayerId, mediaId);
                } else {
                    log.warn("未找到附件媒体文件,媒体ID: {}", mediaId);
                }
            }
        } catch (Exception e) {
            log.error("保存附件媒体文件时发生错误,报名ID: {}", activityPlayerId, e);
        }
    }
 
    /**
     * 保存选手头像媒体记录
     * 使用新的媒体API保存头像媒体记录
     */
    private void savePlayerAvatarMedia(Long playerId, String avatarMediaId) {
        try {
            log.info("开始保存选手头像媒体记录,选手ID: {}, 媒体ID: {}", playerId, avatarMediaId);
            
            MediaSaveInput input = new MediaSaveInput();
            input.setTargetType("player");
            input.setTargetId(playerId);
            input.setUrl(avatarMediaId); // COS路径
            input.setFileName("avatar.jpg"); // 默认头像文件名
            input.setFileExt("jpg"); // 文件扩展名
            input.setFileSize(0L); // 文件大小暂时设为0
            input.setMediaType(1); // 头像类型
            
            mediaV2Service.saveMedia(input);
            log.info("选手头像媒体记录保存成功,选手ID: {}", playerId);
            
        } catch (Exception e) {
            log.error("保存选手头像媒体记录时发生错误,选手ID: {}, 媒体ID: {}", playerId, avatarMediaId, e);
        }
    }
 
    /**
     * 保存附件媒体记录
     * 使用新的媒体API保存附件媒体记录
     */
    private void saveAttachmentMediaRecords(Long activityPlayerId, List<String> attachmentMediaIds) {
        try {
            log.info("开始保存附件媒体记录,报名ID: {}, 附件数量: {}", activityPlayerId, attachmentMediaIds.size());
            
            for (String mediaId : attachmentMediaIds) {
                MediaSaveInput input = new MediaSaveInput();
                input.setTargetType("activity_player");
                input.setTargetId(activityPlayerId);
                input.setUrl(mediaId); // COS路径
                input.setFileName("attachment"); // 默认附件文件名
                input.setFileExt("jpg"); // 文件扩展名
                input.setFileSize(0L); // 文件大小暂时设为0
                input.setMediaType(2); // 附件类型
                
                mediaV2Service.saveMedia(input);
                log.info("附件媒体记录保存成功,报名ID: {}, 媒体ID: {}", activityPlayerId, mediaId);
            }
            
        } catch (Exception e) {
            log.error("保存附件媒体记录时发生错误,报名ID: {}", activityPlayerId, e);
        }
    }
}