blob: 49dbd21dbd8f98961784d4d2a82cb3bed38e9728 [file] [log] [blame]
xiukira687b9cb2025-05-29 15:15:02 +08001package com.g9.g9backend.controller;
2
xiukirad0a7a082025-06-05 16:28:08 +08003import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
xiukira07ea6ee2025-06-06 19:28:24 +08005import com.baomidou.mybatisplus.core.metadata.IPage;
6import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
xiukirad0a7a082025-06-05 16:28:08 +08007import com.g9.g9backend.pojo.*;
8import com.g9.g9backend.pojo.DTO.*;
xiukiraac78f3d2025-06-08 23:38:10 +08009import com.g9.g9backend.pojo.Thread;
xiukirad0a7a082025-06-05 16:28:08 +080010import com.g9.g9backend.service.*;
xiukira687b9cb2025-05-29 15:15:02 +080011import org.slf4j.Logger;
12import org.slf4j.LoggerFactory;
xiukira29f8d372025-06-06 18:07:13 +080013import org.springframework.http.HttpStatus;
xiukirad0a7a082025-06-05 16:28:08 +080014import org.springframework.http.ResponseEntity;
15import org.springframework.web.bind.annotation.*;
xiukira687b9cb2025-05-29 15:15:02 +080016
xiukira07ea6ee2025-06-06 19:28:24 +080017import java.util.ArrayList;
18import java.util.List;
19
xiukira687b9cb2025-05-29 15:15:02 +080020/**
21 * UserController 用户控制器类,处理与用户相关的请求
22 *
23 * @author hcy
24 */
25@RestController
26@RequestMapping("/user")
27public class UserController {
28
xiukirad0a7a082025-06-05 16:28:08 +080029 private final UserService userService;
30
31 private final InvitationService invitationService;
32
33 private final SubscriptionService subscriptionService;
34
xiukira29f8d372025-06-06 18:07:13 +080035 private final SearchHistoryService searchHistoryService;
36
xiukira07ea6ee2025-06-06 19:28:24 +080037 private final RewardService rewardService;
38
39 private final UserCollectionService userCollectionService;
40
41 private final UserUploadService userUploadService;
42
43 private final UserPurchaseService userPurchaseService;
44
45 private final ResourceService resourceService;
46
xiukiraac78f3d2025-06-08 23:38:10 +080047 private final ThreadService threadService;
48
49 public UserController(UserService userService, InvitationService invitationService, SubscriptionService subscriptionService, SearchHistoryService searchHistoryService, RewardService rewardService, UserCollectionService userCollectionService, UserUploadService userUploadService, UserPurchaseService userPurchaseService, ResourceService resourceService, ThreadService threadService) {
xiukirad0a7a082025-06-05 16:28:08 +080050 this.userService = userService;
51 this.invitationService = invitationService;
52 this.subscriptionService = subscriptionService;
xiukira29f8d372025-06-06 18:07:13 +080053 this.searchHistoryService = searchHistoryService;
xiukira07ea6ee2025-06-06 19:28:24 +080054 this.rewardService = rewardService;
55 this.userCollectionService = userCollectionService;
56 this.userUploadService = userUploadService;
57 this.userPurchaseService = userPurchaseService;
58 this.resourceService = resourceService;
xiukiraac78f3d2025-06-08 23:38:10 +080059 this.threadService = threadService;
xiukirad0a7a082025-06-05 16:28:08 +080060 }
61
xiukira07ea6ee2025-06-06 19:28:24 +080062
xiukira687b9cb2025-05-29 15:15:02 +080063 private final Logger logger = LoggerFactory.getLogger(UserController.class);
xiukira687b9cb2025-05-29 15:15:02 +080064
xiukirad0a7a082025-06-05 16:28:08 +080065 /**
66 * 用户注册
67 *
68 * @param registerDTO 用户注册
69 * @return 注册结果
70 */
71 @PostMapping("/register")
72 public ResponseEntity<String> register(@RequestBody RegisterDTO registerDTO) {
73 String username = registerDTO.getUsername();
74 String password = registerDTO.getPassword();
75 String invitationCode = registerDTO.getInvitationCode();
76 logger.info("Register request received for account: {}", username);
xiukira687b9cb2025-05-29 15:15:02 +080077
xiukirad0a7a082025-06-05 16:28:08 +080078 // 根据用户名查询该用户名是否已存在
79 QueryWrapper<User> userQuery = new QueryWrapper<>();
80 userQuery.eq("username", username);
81 User userCheck = userService.getOne(userQuery);
82
83 if (userCheck != null) {
84 // 用户名重复
85 logger.warn("Registration attempt failed. Account already exists: {}", username);
xiukirab8bd04e2025-06-09 17:31:16 +080086 return ResponseEntity.status(412).body("");
xiukirad0a7a082025-06-05 16:28:08 +080087 }
88
89 // 查询邀请码是否存在
90 QueryWrapper<Invitation> invitationQuery = new QueryWrapper<>();
91 invitationQuery.eq("invitation_code", invitationCode);
92 Invitation invitation = invitationService.getOne(invitationQuery);
93
94 if (invitation == null) {
95 // 邀请码不存在
96 logger.info("The invitation code does not exist: {}", invitationCode);
97 return ResponseEntity.status(409).body("");
98 } else if (invitation.getInviteeId() != 0) {
99 // 邀请码已被使用
100 logger.info("The invitation code has been used: {}", invitationCode);
101 return ResponseEntity.status(410).body("");
102 }
103 // 注册
104 // 添加新用户
105 User user = new User();
106 user.setUsername(username);
107 user.setPassword(password);
108 userService.save(user);
109
110 // 设置该邀请码已被使用
111 User userGetId = userService.getOne(userQuery);
112 int newUserId = userGetId.getUserId();
113
xiukira29f8d372025-06-06 18:07:13 +0800114 UpdateWrapper<Invitation> invitationUpdate = new UpdateWrapper<>();
115 invitationUpdate.eq("invitation_code", invitationCode).set("invitee_id", newUserId);
116 invitationService.update(invitationUpdate);
xiukirad0a7a082025-06-05 16:28:08 +0800117
118 // 生成五个邀请码并分配给新用户
119 String[] invitationCodes = invitationService.generateInvitationCode();
120
121 for (String code : invitationCodes) {
122 Invitation newInvitation = new Invitation();
123 newInvitation.setInvitationCode(code);
124 newInvitation.setUserId(newUserId);
125 invitationService.save(newInvitation);
126 }
127
128 logger.info("User registered successfully: {}", username);
129 return ResponseEntity.ok("");
130 }
131
132 /**
133 * 用户登录
134 *
135 * @param user 登录信息
136 * @return 登录结果
137 */
138 @PostMapping("/login")
139 public ResponseEntity<String> login(@RequestBody User user) {
140 String username = user.getUsername();
141 String password = user.getPassword();
142 logger.info("Login attempt for account: {}", username);
143
144 // 根据用户名查询该用户名是否已存在
145 QueryWrapper<User> userQuery = new QueryWrapper<>();
146 userQuery.eq("username", username);
147 User userCheck = userService.getOne(userQuery);
148
149 if (userCheck == null) {
150 // 用户名不存在
151 logger.warn("Login failed. User not found: {}", username);
152 return ResponseEntity.status(406).body("");
153 } else {
154 if (userCheck.getPassword().equals(password)) {
155 return ResponseEntity.ok("");
156 } else {
157 // 密码错误
158 logger.warn("Login failed. Incorrect password for account: {}", username);
159 return ResponseEntity.status(408).body("");
160 }
161 }
162 }
163
164 /**
165 * 关注
166 *
167 * @param subscription 关注信息
168 * @return 关注结果
169 */
170 @PostMapping("/subscription")
171 public ResponseEntity<String> subscription(@RequestBody Subscription subscription) {
172 subscriptionService.save(subscription);
173 return ResponseEntity.ok("");
174 }
xiukira29f8d372025-06-06 18:07:13 +0800175
176 /**
177 * 注销账户
178 *
179 * @param userId 用户id
180 * @param password 密码
181 * @return 注销结果
182 */
183 @DeleteMapping
184 @ResponseStatus(HttpStatus.NO_CONTENT)
185 public ResponseEntity<String> userDelete(@RequestParam int userId, @RequestParam String password) {
186 logger.warn("Delete user with id: {}", userId);
187 // 根据用户id查询该用户
188 QueryWrapper<User> userQuery = new QueryWrapper<>();
189 userQuery.eq("user_id", userId);
190 User userCheck = userService.getOne(userQuery);
191
192 if (userCheck.getPassword().equals(password)) {
193 // 注销账户(自动清除与该用户相关的记录,注意会回收分配给该用户的邀请码)
194 userService.remove(userQuery);
195
196 return ResponseEntity.noContent().build();
197 } else {
198 logger.warn("Delete failed. Incorrect password for account: {}", password);
199 return ResponseEntity.status(408).body("");
200 }
201 }
202
203 /**
204 * 删除用户搜索历史
205 *
206 * @param searchHistoryId 搜索历史id
207 * @return 删除用户搜索历史结果
208 */
209 @DeleteMapping("/search")
210 @ResponseStatus(HttpStatus.NO_CONTENT)
211 public ResponseEntity<String> searchDelete(@RequestParam int searchHistoryId) {
212 searchHistoryService.removeById(searchHistoryId);
213 return ResponseEntity.noContent().build();
214 }
215
216 /**
217 * 取消关注
218 *
219 * @param userId 被关注者id
220 * @param followerId 关注被人者id
221 * @return 取消关注结果
222 */
223 @DeleteMapping("/subscription")
224 @ResponseStatus(HttpStatus.NO_CONTENT)
225 public ResponseEntity<String> subscriptionDelete(@RequestParam int userId, @RequestParam int followerId) {
226 QueryWrapper<Subscription> subscriptionQuery = new QueryWrapper<>();
227 subscriptionQuery.eq("user_id", userId).eq("follower_id", followerId);
228 subscriptionService.remove(subscriptionQuery);
229 return ResponseEntity.noContent().build();
230 }
xiukira07ea6ee2025-06-06 19:28:24 +0800231
232
233 /**
234 * 获取用户ID
235 *
236 * @param username 用户名
237 * @param password 密码
238 * @return 获取邀请码结果
239 */
240 @GetMapping("/getId")
241 public ResponseEntity<Integer> getUserId(@RequestParam String username, @RequestParam String password) {
242 QueryWrapper<User> userQuery = new QueryWrapper<>();
243 userQuery.eq("username", username).eq("password", password);
244 User user = userService.getOne(userQuery);
245 return ResponseEntity.ok(user.getUserId());
246 }
247
248 /**
249 * 获取邀请码
250 *
251 * @param userId 用户id
252 * @return 获取邀请码结果
253 */
254 @GetMapping("/invitation-code")
255 public ResponseEntity<GetInvitationCodeDTO> getInvitationCode(@RequestParam int userId) {
256 QueryWrapper<Invitation> invitationQuery = new QueryWrapper<>();
257 invitationQuery.eq("user_id", userId).eq("invitee_id", 0); // 获取未被使用过的分配给该用户的邀请码
258 invitationQuery.select("invitation_code");
259 List<Invitation> invitationList = invitationService.list(invitationQuery);
260 GetInvitationCodeDTO getInvitationCodeDTO = new GetInvitationCodeDTO(invitationList);
261 return ResponseEntity.ok(getInvitationCodeDTO);
262 }
263
264 /**
265 * 获取用户信息
266 *
267 * @param userId 用户id
268 * @return 获取用户信息结果
269 */
270 @GetMapping("/info")
271 public ResponseEntity<User> getUserInfo(@RequestParam int userId) {
272 User user = userService.getById(userId);
273 return ResponseEntity.ok(user);
274 }
275
276 /**
277 * 获取用户悬赏
278 *
279 * @param userId 用户id
280 * @param pageNumber 页数
281 * @param rows 行数
282 * @return 获取用户悬赏结果
283 */
284 @GetMapping("/reward")
285 public ResponseEntity<GetUserRewardDTO> getUserReward(@RequestParam int userId, @RequestParam int pageNumber, @RequestParam int rows) {
286 IPage<Reward> page = new Page<>(pageNumber, rows);
287 QueryWrapper<Reward> rewardQuery = new QueryWrapper<>();
288 rewardQuery.eq("user_id", userId);
289 IPage<Reward> rewardPage = rewardService.page(page, rewardQuery);
290 List<Reward> rewardList = rewardPage.getRecords();
291 long total = rewardPage.getTotal();
292 long pages = rewardPage.getPages();
293 long current = rewardPage.getCurrent();
294 long size = rewardPage.getSize();
295
296 GetUserRewardDTO getUserRewardDTO = new GetUserRewardDTO(rewardList, total, pages, current, size);
297 return ResponseEntity.ok(getUserRewardDTO);
298 }
299
300 /**
301 * 获取用户收藏资源
302 *
303 * @param userId 用户id
304 * @param pageNumber 页数
305 * @param rows 行数
306 * @return 获取用户收藏结果
307 */
308 @GetMapping("/collection")
309 public ResponseEntity<GetUserResourceListDTO> getUserCollection(@RequestParam int userId, @RequestParam int pageNumber, @RequestParam int rows) {
310 IPage<UserCollection> page = new Page<>(pageNumber, rows);
311 QueryWrapper<UserCollection> userCollectionQuery = new QueryWrapper<>();
312 userCollectionQuery.eq("user_id", userId);
313 IPage<UserCollection> userCollectionPage = userCollectionService.page(page, userCollectionQuery);
314 List<UserCollection> resourceList = userCollectionPage.getRecords();
315 List<Resource> collectionList = new ArrayList<>();
316 for (UserCollection userCollection : resourceList) {
317 Resource resource = resourceService.getById(userCollection.getResourceId());
318 collectionList.add(resource);
319 }
320 long total = userCollectionPage.getTotal();
321 long pages = userCollectionPage.getPages();
322 long current = userCollectionPage.getCurrent();
323 long size = userCollectionPage.getSize();
324
325 GetUserResourceListDTO getUserResourceListDTO = new GetUserResourceListDTO(collectionList, total, pages, current, size);
326 return ResponseEntity.ok(getUserResourceListDTO);
327 }
328
329 /**
330 * 获取用户上传资源
331 *
332 * @param userId 用户id
333 * @param pageNumber 页数
334 * @param rows 行数
335 * @return 获取用户上传资源结果
336 */
337 @GetMapping("/upload")
338 public ResponseEntity<GetUserResourceListDTO> getUserUpload(@RequestParam int userId, @RequestParam int pageNumber, @RequestParam int rows) {
339 IPage<UserUpload> page = new Page<>(pageNumber, rows);
340 QueryWrapper<UserUpload> userUploadQuery = new QueryWrapper<>();
341 userUploadQuery.eq("user_id", userId);
342 IPage<UserUpload> userUploadPage = userUploadService.page(page, userUploadQuery);
343 List<UserUpload> resourceList = userUploadPage.getRecords();
344 List<Resource> uploadList = new ArrayList<>();
345 for (UserUpload userUpload : resourceList) {
346 Resource resource = resourceService.getById(userUpload.getResourceId());
347 uploadList.add(resource);
348 }
349 long total = userUploadPage.getTotal();
350 long pages = userUploadPage.getPages();
351 long current = userUploadPage.getCurrent();
352 long size = userUploadPage.getSize();
353
354 GetUserResourceListDTO getUserResourceListDTO = new GetUserResourceListDTO(uploadList, total, pages, current, size);
355 return ResponseEntity.ok(getUserResourceListDTO);
356 }
357
358 /**
359 * 获取用户购买资源
360 *
361 * @param userId 用户id
362 * @param pageNumber 页数
363 * @param rows 行数
364 * @return 获取用户购买资源结果
365 */
366 @GetMapping("/purchase")
367 public ResponseEntity<GetUserResourceListDTO> getUserPurchase(@RequestParam int userId, @RequestParam int pageNumber, @RequestParam int rows) {
368 IPage<UserPurchase> page = new Page<>(pageNumber, rows);
369 QueryWrapper<UserPurchase> userPurchaseQuery = new QueryWrapper<>();
370 userPurchaseQuery.eq("user_id", userId);
371 IPage<UserPurchase> userPurchasePage = userPurchaseService.page(page, userPurchaseQuery);
372 List<UserPurchase> resourceList = userPurchasePage.getRecords();
373 List<Resource> purchaseList = new ArrayList<>();
374 for (UserPurchase userPurchase : resourceList) {
375 Resource resource = resourceService.getById(userPurchase.getResourceId());
376 purchaseList.add(resource);
377 }
378 long total = userPurchasePage.getTotal();
379 long pages = userPurchasePage.getPages();
380 long current = userPurchasePage.getCurrent();
381 long size = userPurchasePage.getSize();
382
383 GetUserResourceListDTO getUserResourceListDTO = new GetUserResourceListDTO(purchaseList, total, pages, current, size);
384 return ResponseEntity.ok(getUserResourceListDTO);
385 }
386
387 /**
388 * 获取用户搜索历史
389 *
390 * @param userId 用户id
391 * @return 获取用户搜索历史结果
392 */
393 @GetMapping("/search")
394 public ResponseEntity<GetUserSearchHistoryDTO> getUserSearchHistory(@RequestParam int userId) {
395 QueryWrapper<SearchHistory> SearchHistoryQuery = new QueryWrapper<>();
396 SearchHistoryQuery.eq("user_id", userId).orderByDesc("search_history_id").last("LIMIT 10");
397 List<SearchHistory> searchHistoryList = searchHistoryService.list(SearchHistoryQuery);
398
399 GetUserSearchHistoryDTO getUserSearchHistoryDTO = new GetUserSearchHistoryDTO(searchHistoryList);
400 return ResponseEntity.ok(getUserSearchHistoryDTO);
401 }
402
403 /**
xiukiraac78f3d2025-06-08 23:38:10 +0800404 * 获取用户发布贴子
405 *
406 * @param userId 用户id
407 * @param pageNumber 页数
408 * @param rows 行数
409 * @return 获取用户发布贴子结果
410 */
411 @GetMapping("/thread")
412 public ResponseEntity<GetUserThreadListDTO> getUserThread(@RequestParam int userId, @RequestParam int pageNumber, @RequestParam int rows) {
413 IPage<Thread> page = new Page<>(pageNumber, rows);
414 QueryWrapper<Thread> threadQuery = new QueryWrapper<>();
415 threadQuery.eq("user_id", userId);
416 IPage<Thread> threadPage = threadService.page(page, threadQuery);
417 List<Thread> threadList = threadPage.getRecords();
418 long total = threadPage.getTotal();
419 long pages = threadPage.getPages();
420 long current = threadPage.getCurrent();
421 long size = threadPage.getSize();
422
423 GetUserThreadListDTO getUserThreadListDTO = new GetUserThreadListDTO(threadList, total, pages, current, size);
424 return ResponseEntity.ok(getUserThreadListDTO);
425 }
426
427 /**
xiukira07ea6ee2025-06-06 19:28:24 +0800428 * 获取用户数据
429 *
430 * @param userId 用户id
431 * @return 获取用户数据结果
432 */
433 @GetMapping("/data")
434 public ResponseEntity<GetUserDataDTO> getUserData(@RequestParam int userId) {
435 User user = userService.getById(userId);
436 int subscriberCount = user.getSubscriberCount();
437 int uploadAmount = user.getUploadAmount();
438
439 QueryWrapper<UserUpload> UserUploadQuery = new QueryWrapper<>();
440 UserUploadQuery.eq("user_id", userId);
441 List<UserUpload> UserUpload = userUploadService.list(UserUploadQuery);
442 int beDownloadedAmount = 0; // 上传资源被下载量
443 float[] seedPercentageList = new float[4]; // 上传资源类型百分比,0-1区间的小数
444 int resourcePackAmount = 0;
445 int modAmount = 0;
446 int modPackAmount = 0;
447 int mapAmount = 0;
448 for (UserUpload userUpload : UserUpload) {
449 Resource resource = resourceService.getById(userUpload.getResourceId());
450 beDownloadedAmount += resource.getDownloads();
451 switch (resource.getClassify()) {
452 case "resourcePack":
453 resourcePackAmount++;
454 break;
455 case "mod":
456 modAmount++;
457 break;
458 case "modPack":
459 modPackAmount++;
460 break;
461 case "map":
462 mapAmount++;
463 break;
464 }
465 }
466 int totalAmount = resourcePackAmount + modAmount + modPackAmount + mapAmount;
467 seedPercentageList[0] = (float) resourcePackAmount / totalAmount;
468 seedPercentageList[1] = (float) modAmount / totalAmount;
469 seedPercentageList[2] = (float) modPackAmount / totalAmount;
470 seedPercentageList[3] = (float) mapAmount / totalAmount;
471
472 GetUserDataDTO getUserDataDTO = new GetUserDataDTO(subscriberCount, uploadAmount, beDownloadedAmount, seedPercentageList);
473 return ResponseEntity.ok(getUserDataDTO);
474 }
475
476 /**
477 * 获取关注列表
478 *
479 * @param userId 用户id
480 * @return 获取关注列表结果
481 */
482 @GetMapping("/subscriber")
483 public ResponseEntity<GetUserDTO> getUserSubscriber(@RequestParam int userId) {
484 QueryWrapper<Subscription> subscriptionQuery = new QueryWrapper<>();
485 subscriptionQuery.eq("follower_id", userId);
486 List<Subscription> subscriptionList = subscriptionService.list(subscriptionQuery);
487
488 List<User> subscriberList = new ArrayList<>();
489 for (Subscription subscription : subscriptionList) {
490 User user = userService.getById(subscription.getUserId());
491 subscriberList.add(user);
492 }
493
494 GetUserDTO getUserDTO = new GetUserDTO(subscriberList);
495 return ResponseEntity.ok(getUserDTO);
496 }
497
498 /**
499 * 获取粉丝列表
500 *
501 * @param userId 用户id
502 * @return 获取粉丝列表结果
503 */
504 @GetMapping("/follower")
505 public ResponseEntity<GetUserDTO> getUserFollower(@RequestParam int userId) {
506 QueryWrapper<Subscription> subscriptionQuery = new QueryWrapper<>();
507 subscriptionQuery.eq("user_id", userId);
508 List<Subscription> subscriptionList = subscriptionService.list(subscriptionQuery);
509
510 List<User> subscriberList = new ArrayList<>();
511 for (Subscription subscription : subscriptionList) {
512 User user = userService.getById(subscription.getUserId());
513 subscriberList.add(user);
514 }
515
516 GetUserDTO getUserDTO = new GetUserDTO(subscriberList);
517 return ResponseEntity.ok(getUserDTO);
518 }
xiukiraa3c84182025-06-06 20:54:38 +0800519
520 /**
521 * 修改用户签名
522 *
523 * @param user 用户信息
524 * @return 用户签名修改结果
525 */
526 @PutMapping("/signature")
527 public ResponseEntity<String> modifySignature(@RequestBody User user) {
528 UpdateWrapper<User> userUpdate = new UpdateWrapper<>();
529 userUpdate.eq("user_id", user.getUserId()).set("signature", user.getSignature());
530 userService.update(userUpdate);
531
532 return ResponseEntity.ok("");
533 }
534
535 /**
536 * 修改用户密码
537 *
538 * @param modifyPasswordDTO 用户信息
539 * @return 用户密码修改结果
540 */
541 @PutMapping("/password")
542 public ResponseEntity<String> modifyPassword(@RequestBody ModifyPasswordDTO modifyPasswordDTO) {
543 // 检查密码是否正确
544 QueryWrapper<User> userQuery = new QueryWrapper<>();
545 userQuery.eq("user_id", modifyPasswordDTO.getUserId());
546 User user = userService.getOne(userQuery);
547 if (user.getPassword().equals(modifyPasswordDTO.getPassword())) {
548 UpdateWrapper<User> userUpdate = new UpdateWrapper<>();
549 userUpdate.eq("user_id", modifyPasswordDTO.getUserId()).set("password", modifyPasswordDTO.getNewPassword());
550 userService.update(userUpdate);
551 return ResponseEntity.ok("");
552 } else {
553 // 密码错误
554 logger.warn("Modify failed. Incorrect password for userID: {}", modifyPasswordDTO.getUserId());
555 return ResponseEntity.status(408).body("");
556 }
557 }
558
559 /**
560 * 修改用户头像
561 *
562 * @param user 用户信息
563 * @return 用户头像修改结果
564 */
565 @PutMapping("/avatar")
566 public ResponseEntity<String> modifyAvatar(@RequestBody User user) {
567 UpdateWrapper<User> userUpdate = new UpdateWrapper<>();
568 userUpdate.eq("user_id", user.getUserId()).set("avatar", user.getAvatar());
569 userService.update(userUpdate);
570
571 return ResponseEntity.ok("");
572 }
xiukirad0a7a082025-06-05 16:28:08 +0800573}