blob: 61f56fe8085f2998ddbf358a2c1177485335d941 [file] [log] [blame]
package com.g9.g9backend.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.g9.g9backend.pojo.*;
import com.g9.g9backend.pojo.DTO.*;
import com.g9.g9backend.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
/**
* ResourceController 资源控制器类,处理与资源相关的请求
*
* @author hcy
*/
@RestController
@RequestMapping("/resource")
public class ResourceController {
private final ResourceService resourceService;
private final GameplayService gameplayService;
private final RewardService rewardService;
private final UserUploadService userUploadService;
private final CommunityService communityService;
private final UserService userService;
private final UserPurchaseService userPurchaseService;
private final UserLikeService userLikeService;
private final UserCollectionService userCollectionService;
private final NotificationService notificationService;
private final ResourceVersionService resourceVersionService;
private final SearchHistoryService searchHistoryService;
private final GameVersionService gameVersionService;
private final TorrentRecordService torrentRecordService;
private final HotTrendService hotTrendService;
static Map<String, String> GAME_CLASSIFY = new HashMap() {{
put("模组", "mod");
put("地图", "map");
put("整合包", "modPack");
put("材质包", "resourcePack");
}};
public ResourceController(ResourceService resourceService, GameplayService gameplayService, RewardService rewardService, UserUploadService userUploadService, CommunityService communityService, UserService userService, UserPurchaseService userPurchaseService, UserLikeService userLikeService, UserCollectionService userCollectionService, NotificationService notificationService, ResourceVersionService resourceVersionService, SearchHistoryService searchHistoryService, GameVersionService gameVersionService, TorrentRecordService torrentRecordService, HotTrendService hotTrendService) {
this.resourceService = resourceService;
this.gameplayService = gameplayService;
this.rewardService = rewardService;
this.userUploadService = userUploadService;
this.communityService = communityService;
this.userService = userService;
this.userPurchaseService = userPurchaseService;
this.userLikeService = userLikeService;
this.userCollectionService = userCollectionService;
this.notificationService = notificationService;
this.resourceVersionService = resourceVersionService;
this.searchHistoryService = searchHistoryService;
this.gameVersionService = gameVersionService;
this.torrentRecordService = torrentRecordService;
this.hotTrendService = hotTrendService;
}
private final Logger logger = LoggerFactory.getLogger(ResourceController.class);
/**
* 上传资源
*
* @param postResourceDTO 上传资源信息
* @return 上传资源结果
*/
@PostMapping
public ResponseEntity<String> uploadResource(@RequestBody PostResourceDTO postResourceDTO) {
// 存资源
Resource resource = postResourceDTO.getResource();
resourceService.save(resource);
// 存玩法列表
String[] gameplayList = postResourceDTO.getGameplayList();
for (String gameplayName : gameplayList) {
Gameplay gameplay = new Gameplay();
gameplay.setGameplayName(gameplayName);
gameplay.setResourceId(postResourceDTO.getResource().getResourceId());
gameplayService.save(gameplay);
}
// 完成对应悬赏
if (postResourceDTO.getCompleteRewardId() != 0) {
UpdateWrapper<Reward> rewardUpdate = new UpdateWrapper<>();
rewardUpdate.eq("reward_id", postResourceDTO.getCompleteRewardId()).set("completed_by", postResourceDTO.getUserId()).set("completed_at", postResourceDTO.getResource().getUploadTime()).set("resource_id", postResourceDTO.getResource().getResourceId());
rewardService.update(rewardUpdate);
}
// 存用户上传表
UserUpload userUpload = new UserUpload();
userUpload.setUserId(postResourceDTO.getUserId());
userUpload.setResourceId(postResourceDTO.getResource().getResourceId());
userUploadService.save(userUpload);
// 创建资源社区
Community community = new Community();
community.setCommunityName(postResourceDTO.getResource().getResourceName());
community.setCommunityPicture(postResourceDTO.getResource().getResourcePicture());
community.setDescription(postResourceDTO.getResource().getResourceDetail());
community.setType(postResourceDTO.getResource().getClassify());
community.setResourceId(postResourceDTO.getResource().getResourceId());
communityService.save(community);
return ResponseEntity.ok(String.valueOf(resource.getResourceId()));
}
/**
* 上传版本
*
* @param resourceVersion 上传版本信息
* @return 上传版本结果
*/
@PostMapping("/version")
public ResponseEntity<String> uploadResourceVersion(@RequestBody ResourceVersion resourceVersion) {
resourceVersionService.save(resourceVersion);
return ResponseEntity.ok(String.valueOf(resourceVersion.getResourceVersionId()));
}
/**
* 购买资源
*
* @param userResourceDTO 购买资源信息
* @return 购买资源结果
*/
@PostMapping("purchase")
public ResponseEntity<String> purchaseResource(@RequestBody UserResourceDTO userResourceDTO) {
QueryWrapper<User> userQuery = new QueryWrapper<>();
userQuery.eq("user_id", userResourceDTO.getUserId());
User user = userService.getOne(userQuery);
QueryWrapper<Resource> ResourceQuery = new QueryWrapper<>();
ResourceQuery.eq("resource_id", userResourceDTO.getResourceId());
Resource resource = resourceService.getOne(ResourceQuery);
if (user.getCredits() < resource.getPrice()) {
// 积分余额不足
logger.info("The balance of points is insufficient to cover the price of this resource: {}", resource.getPrice());
return ResponseEntity.status(412).body("");
} else {
// 扣除用户积分
UpdateWrapper<User> userUpdate = new UpdateWrapper<>();
userUpdate.eq("user_id", user.getUserId()).set("credits", user.getCredits() - resource.getPrice());
userService.update(userUpdate);
// 添加购买资源记录
UserPurchase userPurchase = new UserPurchase();
userPurchase.setUserId(user.getUserId());
userPurchase.setResourceId(resource.getResourceId());
userPurchaseService.save(userPurchase);
// 给上传该资源的用户发送通知
Notification notification = new Notification();
QueryWrapper<UserUpload> userUploadQuery = new QueryWrapper<>();
userUploadQuery.eq("resource_id", userResourceDTO.getResourceId());
UserUpload userUpload = userUploadService.getOne(userUploadQuery);
notification.setUserId(userUpload.getUserId());
notification.setTitle("资源被购买");
notification.setContent("你的资源:" + resource.getResourceName() + " 被: " + user.getUsername() + " 购买了!");
notification.setCreateAt(new Date());
notification.setRead(false);
notification.setTriggeredBy(userResourceDTO.getUserId());
notification.setRelatedId(userResourceDTO.getResourceId());
notificationService.save(notification);
return ResponseEntity.ok("");
}
}
/**
* 点赞资源
*
* @param userResourceDTO 点赞资源信息
* @return 点赞资源结果
*/
@PostMapping("like")
public ResponseEntity<String> likeResource(@RequestBody UserResourceDTO userResourceDTO) {
logger.info("User id: "+userResourceDTO.getUserId() + "Resource ID: " + userResourceDTO.getResourceId());
QueryWrapper<User> userQuery = new QueryWrapper<>();
userQuery.eq("user_id", userResourceDTO.getUserId());
User user = userService.getOne(userQuery);
QueryWrapper<Resource> ResourceQuery = new QueryWrapper<>();
ResourceQuery.eq("resource_id", userResourceDTO.getResourceId());
Resource resource = resourceService.getOne(ResourceQuery);
UserLike userLike = new UserLike();
userLike.setUserId(userResourceDTO.getUserId());
userLike.setResourceId(userResourceDTO.getResourceId());
userLikeService.save(userLike);
// 给上传该资源的用户发送通知
Notification notification = new Notification();
QueryWrapper<UserUpload> userUploadQuery = new QueryWrapper<>();
userUploadQuery.eq("resource_id", userResourceDTO.getResourceId());
UserUpload userUpload = userUploadService.getOne(userUploadQuery);
notification.setUserId(userUpload.getUserId());
notification.setTitle("资源被点赞");
notification.setContent("你的资源:" + resource.getResourceName() + " 被: " + user.getUsername() + " 点赞了!");
notification.setCreateAt(new Date());
notification.setRead(false);
notification.setTriggeredBy(userResourceDTO.getUserId());
notification.setRelatedId(userResourceDTO.getResourceId());
notificationService.save(notification);
return ResponseEntity.ok("");
}
/**
* 收藏资源
*
* @param userResourceDTO 收藏资源信息
* @return 收藏资源结果
*/
@PostMapping("collection")
public ResponseEntity<String> collectResource(@RequestBody UserResourceDTO userResourceDTO) {
QueryWrapper<User> userQuery = new QueryWrapper<>();
userQuery.eq("user_id", userResourceDTO.getUserId());
User user = userService.getOne(userQuery);
QueryWrapper<Resource> ResourceQuery = new QueryWrapper<>();
ResourceQuery.eq("resource_id", userResourceDTO.getResourceId());
Resource resource = resourceService.getOne(ResourceQuery);
UserCollection userCollection = new UserCollection();
userCollection.setUserId(userResourceDTO.getUserId());
userCollection.setResourceId(userResourceDTO.getResourceId());
userCollectionService.save(userCollection);
// 给上传该资源的用户发送通知
Notification notification = new Notification();
QueryWrapper<UserUpload> userUploadQuery = new QueryWrapper<>();
userUploadQuery.eq("resource_id", userResourceDTO.getResourceId());
UserUpload userUpload = userUploadService.getOne(userUploadQuery);
notification.setUserId(userUpload.getUserId());
notification.setTitle("资源被收藏");
notification.setContent("你的资源:" + resource.getResourceName() + " 被: " + user.getUsername() + " 收藏了!");
notification.setCreateAt(new Date());
notification.setRead(false);
notification.setTriggeredBy(userResourceDTO.getUserId());
notification.setRelatedId(userResourceDTO.getResourceId());
notificationService.save(notification);
return ResponseEntity.ok("");
}
/**
* 删除资源
*
* @param resourceId 资源id
* @param userId 用户id
* @param password 密码
* @return 删除资源结果
*/
@DeleteMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
public ResponseEntity<String> userDelete(@RequestParam int resourceId, @RequestParam int userId, @RequestParam String password) {
logger.warn("Delete resource with id: {}", resourceId);
// 根据用户id查询该用户
QueryWrapper<User> userQuery = new QueryWrapper<>();
userQuery.eq("user_id", userId);
User userCheck = userService.getOne(userQuery);
// 只允许在用户上传资源页进行删除操作,所以不需要验证该资源是由该用户上传的
if (userCheck.getPassword().equals(password)) {
// 删除资源
resourceService.removeById(resourceId);
return ResponseEntity.noContent().build();
} else {
logger.warn("Delete failed. Incorrect password for account: {}", password);
return ResponseEntity.status(408).body("");
}
}
/**
* 取消点赞
*
* @param userId 用户id
* @param resourceId 资源id
* @return 取消点赞结果
*/
@DeleteMapping("like")
@ResponseStatus(HttpStatus.NO_CONTENT)
public ResponseEntity<String> likeDelete(@RequestParam int userId, @RequestParam int resourceId) {
QueryWrapper<UserLike> userLikeQuery = new QueryWrapper<>();
userLikeQuery.eq("user_id", userId).eq("resource_id", resourceId);
userLikeService.remove(userLikeQuery);
return ResponseEntity.noContent().build();
}
/**
* 取消收藏
*
* @param userId 用户id
* @param resourceId 资源id
* @return 取消收藏结果
*/
@DeleteMapping("collection")
@ResponseStatus(HttpStatus.NO_CONTENT)
public ResponseEntity<String> collectionDelete(@RequestParam int userId, @RequestParam int resourceId) {
QueryWrapper<UserCollection> userCollectionQuery = new QueryWrapper<>();
userCollectionQuery.eq("user_id", userId).eq("resource_id", resourceId);
userCollectionService.remove(userCollectionQuery);
return ResponseEntity.noContent().build();
}
/**
* 搜索资源
*
* @param userId 用户id
* @param searchValue 输入(模糊搜索)
* @param classify 类型名称
* @param gameplayList 主要玩法列表
* @param gameVersionList 版本列表
* @param pageNumber 第几页
* @param rows 行数
* @return 搜索资源结果
*/
@GetMapping("/search")
public ResponseEntity<GetResourcePageDTO> getResourceSearch(@RequestParam int userId, @RequestParam String searchValue, @RequestParam String classify, @RequestParam String[] gameplayList, @RequestParam String[] gameVersionList, @RequestParam int pageNumber, @RequestParam int rows) {
IPage<Resource> page = new Page<>(pageNumber, rows);
QueryWrapper<Resource> resourceWrapper = new QueryWrapper<>();
// 搜索名称字段不为空时,根据搜索名称进行模糊匹配,并将该次搜索存到搜索历史表
if (!Objects.equals(searchValue, "")) {
logger.info("Filter by name: " + searchValue);
resourceWrapper.like("resource_name", searchValue);
SearchHistory searchHistory = new SearchHistory();
searchHistory.setSearchContent(searchValue);
searchHistory.setUserId(userId);
searchHistoryService.save(searchHistory);
}
// 分类字段不为空时,根据类别筛选
logger.info("Classify: " + classify + " Mapped: " + GAME_CLASSIFY.get(classify));
if (!Objects.equals(GAME_CLASSIFY.get(classify), "")) {
logger.info("Filter by classify: " + classify);
resourceWrapper.eq("classify", GAME_CLASSIFY.get(classify));
}
// 主要玩法列表不为空时,根据主要玩法列表筛选(用户传入一个玩法列表,需要去 gameplay 表中查询该资源的所有玩法列表,只有当用户传入的玩法列表的每个值都在资源实际有的玩法列表中时,该资源才符合条件)
if (gameplayList.length > 0) {
// 该子查询统计了用户传入的玩法列表中有多少玩法是在资源的实际玩法列表中有的
logger.info("Filter by gameplay: " + Arrays.toString(gameplayList));
String subQuery = "SELECT COUNT(*) " +
"FROM gameplay gp " +
"WHERE gp.resource_id = resource.resource_id " +
"AND gp.gameplay_name IN (" +
String.join(",", Arrays.stream(gameplayList).map(name -> "'" + name + "'").toArray(String[]::new)) + ")";
// 只有当子查询返回的数量等于用户传入的玩法列表长度时,说明用户传入的玩法列表完全被包含在资源的玩法列表中
resourceWrapper.apply("(" + subQuery + ") = " + gameplayList.length);
}
// 游戏版本列表不为空时,根据游戏版本列表筛选
if (gameVersionList.length > 0) {
// 拼接游戏版本列表的 IN 子句
logger.info("Filter by game version: " + Arrays.toString(gameplayList));
String gameVersionInClause = String.join(",", Arrays.stream(gameVersionList)
.map(v -> "'" + v + "'")
.toArray(String[]::new));
// 修改 HAVING 条件逻辑,只检查输入版本列表是否是实际版本列表的子集
String resourceCondition = "EXISTS ("
+ "SELECT 1 "
+ "FROM resource_version rv "
+ "JOIN game_version gv ON gv.resource_version_id = rv.resource_version_id "
+ "WHERE rv.resource_id = resource.resource_id "
+ "GROUP BY rv.resource_id "
+ "HAVING COUNT(DISTINCT CASE WHEN gv.game_version_name IN (" + gameVersionInClause + ") THEN gv.game_version_name END) = " + gameVersionList.length
+ ")";
// 应用条件
resourceWrapper.apply(resourceCondition);
}
IPage<Resource> resourcePage = resourceService.page(page, resourceWrapper);
List<Resource> resourceList = resourcePage.getRecords();
logger.info("Resource list" + resourceList);
long total = resourcePage.getTotal();
long pages = resourcePage.getPages();
long current = resourcePage.getCurrent();
long size = resourcePage.getSize();
List<List<Gameplay>> gameplayLists = new ArrayList<>();
for (Resource resource : resourceList) {
// 对于每个资源,获取游戏玩法列表
QueryWrapper<Gameplay> gameplayQuery = new QueryWrapper<>();
gameplayQuery.eq("resource_id", resource.getResourceId());
List<Gameplay> allGameplayList = gameplayService.list(gameplayQuery);
gameplayLists.add(allGameplayList);
}
GetResourcePageDTO getResourceSearchDTO = new GetResourcePageDTO(resourceList, gameplayLists, total, pages, current, size);
return ResponseEntity.ok(getResourceSearchDTO);
}
/**
* 获取资源信息
*
* @param resourceId 资源id
* @param userId 用户id
* @return 获取资源信息结果
*/
@GetMapping("/info")
public ResponseEntity<GetResourceInfoDTO> getResourceInfo(@RequestParam int resourceId, @RequestParam int userId) {
// 获取Resource表信息
Resource resource = resourceService.getById(resourceId);
// 获取Gameplay列表
List<Gameplay> gameplayList = gameplayService.list(new QueryWrapper<Gameplay>().eq("resource_id", resourceId));
// 获取ResourceVersion列表
List<ResourceVersion> resourceVersionList = resourceVersionService.list(new QueryWrapper<ResourceVersion>().eq("resource_id", resourceId));
// 获取GameVersion二维列表
List<List<GameVersion>> gameVersionLists = new ArrayList<>();
for (ResourceVersion resourceVersion : resourceVersionList) {
List<GameVersion> gameVersionList = gameVersionService.list(new QueryWrapper<GameVersion>().eq("resource_version_id", resourceVersion.getResourceVersionId()));
gameVersionLists.add(gameVersionList);
}
// 获取TorrentRecord二维列表
List<List<TorrentRecord>> torrentRecordLists = new ArrayList<>();
for (ResourceVersion resourceVersion : resourceVersionList) {
List<TorrentRecord> torrentRecordList = torrentRecordService.list(new QueryWrapper<TorrentRecord>().eq("resource_version_id", resourceVersion.getResourceVersionId()));
torrentRecordLists.add(torrentRecordList);
}
// 获取用户是否收藏
QueryWrapper<UserCollection> userCollectionQuery = new QueryWrapper<>();
userCollectionQuery.eq("user_id", userId).eq("resource_id", resourceId);
boolean isCollect = userCollectionService.getOne(userCollectionQuery) != null;
// 获取用户是否点赞
QueryWrapper<UserLike> userLikeQuery = new QueryWrapper<>();
userLikeQuery.eq("user_id", userId).eq("resource_id", resourceId);
boolean isLike = userLikeService.getOne(userLikeQuery) != null;
// 获取用户是否购买
QueryWrapper<UserPurchase> userPurchaseQuery = new QueryWrapper<>();
userPurchaseQuery.eq("user_id", userId).eq("resource_id", resourceId);
boolean isPurchase = userPurchaseService.getOne(userPurchaseQuery) != null;
// 获取用户是否上传
QueryWrapper<UserUpload> userUploadQuery = new QueryWrapper<>();
userUploadQuery.eq("user_id", userId).eq("resource_id", resourceId);
boolean isUpload = userUploadService.getOne(userUploadQuery) != null;
// 获取上传者ID
QueryWrapper<UserUpload> findUploaderQuery = new QueryWrapper<>();
findUploaderQuery.eq("resource_id", resourceId);
int uploaderId = userUploadService.getOne(findUploaderQuery).getUserId();
GetResourceInfoDTO getResourceInfoDTO = new GetResourceInfoDTO(resource, gameplayList, resourceVersionList, gameVersionLists, torrentRecordLists, isCollect, isLike, isPurchase, isUpload, uploaderId);
return ResponseEntity.ok(getResourceInfoDTO);
}
/**
* 获取热门资源
*
* @param classify 资源分类
* @param pageNumber 页数
* @param rows 行数
* @return 获取热门资源结果
*/
@GetMapping("/hot")
public ResponseEntity<GetResourcePageDTO> getHotResource(@RequestParam String classify, @RequestParam int pageNumber, @RequestParam int rows) {
IPage<Resource> page = new Page<>(pageNumber, rows);
QueryWrapper<Resource> resourceQuery = new QueryWrapper<>();
resourceQuery.eq("classify", GAME_CLASSIFY.get(classify));
// 动态计算热度并按降序排序
resourceQuery.orderByDesc("(downloads * 0.25 + likes * 0.25 + collections * 0.25 + comments * 0.25)");
IPage<Resource> resourcePage = resourceService.page(page, resourceQuery);
List<Resource> resourceList = resourcePage.getRecords();
long total = resourcePage.getTotal();
long pages = resourcePage.getPages();
long current = resourcePage.getCurrent();
long size = resourcePage.getSize();
List<List<Gameplay>> gameplayLists = new ArrayList<>();
for (Resource resource : resourceList) {
// 对于每个资源,获取游戏玩法列表
QueryWrapper<Gameplay> gameplayQuery = new QueryWrapper<>();
gameplayQuery.eq("resource_id", resource.getResourceId());
List<Gameplay> allGameplayList = gameplayService.list(gameplayQuery);
gameplayLists.add(allGameplayList);
}
GetResourcePageDTO getResourcePageDTO = new GetResourcePageDTO(resourceList, gameplayLists, total, pages, current, size);
return ResponseEntity.ok(getResourcePageDTO);
}
/**
* 获取热门资源幻灯片数据
*
* @return 获取用户收藏结果
*/
@GetMapping("/hot/slide")
public ResponseEntity<GetResourceHotSlideDTO> getResourceHotSlide() {
QueryWrapper<Resource> resourceQuery = new QueryWrapper<>();
// 动态计算热度并按降序排序
resourceQuery.orderByDesc("(downloads * 0.25 + likes * 0.25 + collections * 0.25 + comments * 0.25)");
// 限制返回3条记录
resourceQuery.last("LIMIT 3");
List<Resource> resourceList = resourceService.list(resourceQuery);
GetResourceHotSlideDTO getResourceHotSlideDTO = new GetResourceHotSlideDTO(resourceList);
return ResponseEntity.ok(getResourceHotSlideDTO);
}
/**
* 获取热门资源趋势图
*
* @return 获取热门资源趋势图结果
*/
@GetMapping("/hot-trend")
public ResponseEntity<GetResourceHotTrendDTO> getResourceHotTrend() {
List<HotTrend> hotTrendList = hotTrendService.list();
GetResourceHotTrendDTO getResourceHotTrendDTO = new GetResourceHotTrendDTO(hotTrendList);
return ResponseEntity.ok(getResourceHotTrendDTO);
}
/**
* 修改资源信息
*
* @param putResourceInfoDTO 要修改的资源信息
* @return 修改资源信息结果
*/
@PutMapping("/info")
public ResponseEntity<String> putResourceInfo(@RequestBody PutResourceInfoDTO putResourceInfoDTO) {
// 检查资源名是否重复
QueryWrapper<Resource> resourceQuery = new QueryWrapper<>();
resourceQuery.ne("resource_id", putResourceInfoDTO.getResourceId()).eq("resource_name", putResourceInfoDTO.getResourceName());
Resource resource = resourceService.getOne(resourceQuery);
if (resource != null) {
// 资源名重复
logger.warn("Modification attempt failed. Resource name already exists: {}", putResourceInfoDTO.getResourceName());
return ResponseEntity.status(411).body("");
}
UpdateWrapper<Resource> resourceUpdate = new UpdateWrapper<>();
resourceUpdate.eq("resource_id", putResourceInfoDTO.getResourceId())
.set("resource_name", putResourceInfoDTO.getResourceName())
.set("resource_picture", putResourceInfoDTO.getResourcePicture())
.set("resource_summary", putResourceInfoDTO.getResourceSummary())
.set("resource_detail", putResourceInfoDTO.getResourceDetail())
.set("price", putResourceInfoDTO.getPrice());
resourceService.update(resourceUpdate);
QueryWrapper<Gameplay> gameplayQuery = new QueryWrapper<>();
gameplayQuery.eq("resource_id", putResourceInfoDTO.getResourceId());
gameplayService.remove(gameplayQuery);
for (int i = 0; i < putResourceInfoDTO.getGameplayList().length; i++) {
Gameplay gameplay = new Gameplay();
gameplay.setGameplayName(putResourceInfoDTO.getGameplayList()[i]);
gameplay.setResourceId(putResourceInfoDTO.getResourceId());
gameplayService.save(gameplay);
}
return ResponseEntity.ok("");
}
}