diff --git a/luoo_user/src/main/java/com/luoo/user/controller/MyController.java b/luoo_user/src/main/java/com/luoo/user/controller/MyController.java index d94f9cb..f2f8d34 100644 --- a/luoo_user/src/main/java/com/luoo/user/controller/MyController.java +++ b/luoo_user/src/main/java/com/luoo/user/controller/MyController.java @@ -9,6 +9,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import com.luoo.user.pojo.Feedback; import com.luoo.user.pojo.UserCollect; import com.luoo.user.service.UserCollectService; @@ -23,6 +24,7 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import constants.Constants; @@ -31,6 +33,7 @@ import controller.BaseController; import com.luoo.user.dto.UserInfoUpdateDto; import com.luoo.user.dto.response.UserRespDTO; import com.luoo.user.pojo.UserInfo; +import com.luoo.user.service.FeedbackService; import com.luoo.user.service.S3Service; import com.luoo.user.service.UserInfoService; import com.luoo.user.util.IpUtil; @@ -43,11 +46,14 @@ import api.StatusCode; import dto.UserLoginDto; import enums.CollectTypeEnum; import enums.DateTimePatternEnum; +import enums.RequestFrequencyTypeEnum; import enums.UserRelationEnum; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.SneakyThrows; import util.DateUtil; import util.IdWorker; import util.ScaleFilter; @@ -67,23 +73,27 @@ public class MyController extends BaseController { @Autowired // private UserCollectInfoService userCollectInfoService; private UserCollectService userCollectService; + @Autowired + private FeedbackService feedbackService; - public static String UPLOAD_DIRECTORY = "user/avatar/"; + public static String USER_AVATAR_DIRECTORY = "user/avatar/"; + public static String USER_FEEDBACK_IMAGE_DIRECTORY = "user/feedback/"; @ApiOperation(value = "1.获取个人信息", notes = "游客无法获取个人信息") @GetMapping("/userInfo") @GlobalInterceptor(checkAppUserLogin = true) - public Result getUserInfo(@RequestHeader(value = "Authorization", required = false) String authorization) { + public Result getUserInfo( + @RequestHeader(value = "Authorization", required = true) String authorization) { UserLoginDto userLoginDto = getUserLoginDto(authorization); UserInfo user = userInfoService.findById(userLoginDto.getUserId()); - UserRespDTO userRespDTO = getUserRespDTO(user,true,Collections.emptySet()); + UserRespDTO userRespDTO = getUserRespDTO(user, true, Collections.emptySet()); return Result.success(userRespDTO); } @ApiOperation(value = "2.更新个人信息", notes = "游客无法编辑个人信息") @PutMapping("/userInfo") @GlobalInterceptor(checkAppUserLogin = true) - public Result updateUserInfo(@RequestHeader(value = "Authorization", required = false) String authorization, + public Result updateUserInfo(@RequestHeader(value = "Authorization", required = true) String authorization, @VerifyParam(required = true) @RequestBody UserInfoUpdateDto userInfoUpdateDto) { UserLoginDto userLoginDto = getUserLoginDto(authorization); UserInfo user = userInfoService.findById(userLoginDto.getUserId()); @@ -116,15 +126,15 @@ public class MyController extends BaseController { @ApiOperation(value = "3.上传个人头像", notes = "图片压缩为70X70 JPEG,存入S3,桶为indie,目录为 user/avatar/") @PostMapping("/avatar") @GlobalInterceptor(checkAppUserLogin = true) - public Result uploadAvatar(@RequestHeader(value = "Authorization", required = false) String authorization, + public Result uploadAvatar(@RequestHeader(value = "Authorization", required = true) String authorization, @VerifyParam(required = true) MultipartFile file) throws IOException { UserLoginDto userLoginDto = getUserLoginDto(authorization); byte[] thumbnail = ScaleFilter.createThumbnail(file.getInputStream(), Constants.LENGTH_70, Constants.LENGTH_70); String avatarName = userLoginDto.getUserId() + "_" + idWorker.nextId() + StringTools.getFileSuffix(file.getOriginalFilename()); - String filePath = UPLOAD_DIRECTORY + avatarName; - s3Service.uploadAvatar("indie", filePath, thumbnail); + String filePath = USER_AVATAR_DIRECTORY + avatarName; + s3Service.uploadImage("indie", filePath, thumbnail); UserInfo user = userInfoService.findById(userLoginDto.getUserId()); user.setAvatar(filePath); @@ -136,23 +146,24 @@ public class MyController extends BaseController { @ApiOperation(value = "4.查看他人信息", notes = "游客无法查看他人信息") @GetMapping("/otherUserInfo/{userId}") @GlobalInterceptor(checkAppUserLogin = true) - public Result getOtherUserInfo(@RequestHeader(value = "Authorization", required = false) String authorization, + public Result getOtherUserInfo( + @RequestHeader(value = "Authorization", required = true) String authorization, @VerifyParam(required = true) @PathVariable String userId) { UserInfo user = userInfoService.findById(userId); if (null == user) { return Result.failed(StatusCode.USER_INVALID_USER_ID); } - - UserRespDTO userRespDTO = getUserRespDTO(user,false,Collections.emptySet()); + + UserRespDTO userRespDTO = getUserRespDTO(user, false, Collections.emptySet()); userRespDTO.setIpLocation(IpUtil.getIpLocation(user.getLastLoginIp())); - + UserLoginDto userLoginDto = getUserLoginDto(authorization); - + Optional loginOptional = userCollectService.findByUserId(userLoginDto.getUserId()); if (loginOptional.isPresent()) { UserCollect loginCollect = loginOptional.get(); - Set loginBlackList=new HashSet<>(loginCollect.getBlackList()); - if(loginBlackList.contains(userId)) { + Set loginBlackList = new HashSet<>(loginCollect.getBlackList()); + if (loginBlackList.contains(userId)) { userRespDTO.setRelation(UserRelationEnum.SELF_BLACK_LIST.getStatus()); return Result.success(userRespDTO); } @@ -160,22 +171,22 @@ public class MyController extends BaseController { Optional otherOptional = userCollectService.findByUserId(userId); if (otherOptional.isPresent()) { UserCollect otherCollect = otherOptional.get(); - Set otherBlackList=new HashSet<>(otherCollect.getBlackList()); - if(otherBlackList.contains(userLoginDto.getUserId())) { + Set otherBlackList = new HashSet<>(otherCollect.getBlackList()); + if (otherBlackList.contains(userLoginDto.getUserId())) { userRespDTO.setRelation(UserRelationEnum.OTHER_BLACK_LIST.getStatus()); return Result.success(userRespDTO); } - - Set follows=new HashSet<>(otherCollect.getFollows()); - Set fans=new HashSet<>(otherCollect.getFans()); + + Set follows = new HashSet<>(otherCollect.getFollows()); + Set fans = new HashSet<>(otherCollect.getFans()); userRespDTO.setFollowCount(follows.size()); userRespDTO.setFansCount(fans.size()); - boolean isFollow=fans.contains(userLoginDto.getUserId()); - boolean isFan=follows.contains(userLoginDto.getUserId()); - if(isFollow&&isFan) { + boolean isFollow = fans.contains(userLoginDto.getUserId()); + boolean isFan = follows.contains(userLoginDto.getUserId()); + if (isFollow && isFan) { userRespDTO.setRelation(UserRelationEnum.BOTH_FOLLOW.getStatus()); return Result.success(userRespDTO); - }else if(isFollow&&!isFan) { + } else if (isFollow && !isFan) { userRespDTO.setRelation(UserRelationEnum.FOLLOW.getStatus()); return Result.success(userRespDTO); } @@ -183,64 +194,102 @@ public class MyController extends BaseController { userRespDTO.setRelation(UserRelationEnum.NOT_FOLLOW.getStatus()); return Result.success(userRespDTO); } - + @ApiOperation(value = "5.查询黑名单") - @ApiImplicitParams({ - @ApiImplicitParam(name = "pageNum", value = "分页: 页码,以1开始", required = true), - @ApiImplicitParam(name = "pageSize", value = "分页: 每页数量", required = true) }) + @ApiImplicitParams({ @ApiImplicitParam(name = "pageNum", value = "分页: 页码,以1开始", required = true), + @ApiImplicitParam(name = "pageSize", value = "分页: 每页数量", required = true) }) @GetMapping("/blackList/{pageNum}/{pageSize}") @GlobalInterceptor(checkAppUserLogin = true) - public Result> getBlackList(@RequestHeader(value = "Authorization", required = false) String authorization, + public Result> getBlackList( + @RequestHeader(value = "Authorization", required = true) String authorization, @PathVariable @VerifyParam(required = true) Integer pageNum, @PathVariable @VerifyParam(required = true) Integer pageSize) { UserLoginDto userLoginDto = getUserLoginDto(authorization); return getCollectedUserInfo(userLoginDto.getUserId(), pageNum, pageSize, CollectTypeEnum.BLACK_LIST); } - @ApiOperation(value = "6.查询关注人信息") @ApiImplicitParams({ @ApiImplicitParam(name = "userId", value = "用户id", required = true), - @ApiImplicitParam(name = "pageNum", value = "分页: 页码,以1开始", required = true), - @ApiImplicitParam(name = "pageSize", value = "分页: 每页数量", required = true) }) + @ApiImplicitParam(name = "pageNum", value = "分页: 页码,以1开始", required = true), + @ApiImplicitParam(name = "pageSize", value = "分页: 每页数量", required = true) }) @GetMapping("/follows/{userId}/{pageNum}/{pageSize}") @GlobalInterceptor(checkAppUserLogin = true) - public Result> getFollows(@RequestHeader(value = "Authorization", required = false) String authorization, + public Result> getFollows( + @RequestHeader(value = "Authorization", required = true) String authorization, @PathVariable @VerifyParam(required = true) String userId, @PathVariable @VerifyParam(required = true) Integer pageNum, @PathVariable @VerifyParam(required = true) Integer pageSize) { - + return getCollectedUserInfo(userId, pageNum, pageSize, CollectTypeEnum.FOLLOWS); } @ApiOperation(value = "7.查询粉丝信息") @ApiImplicitParams({ @ApiImplicitParam(name = "userId", value = "用户id", required = true), - @ApiImplicitParam(name = "pageNum", value = "分页: 页码,以1开始", required = true), - @ApiImplicitParam(name = "pageSize", value = "分页: 每页数量", required = true) }) + @ApiImplicitParam(name = "pageNum", value = "分页: 页码,以1开始", required = true), + @ApiImplicitParam(name = "pageSize", value = "分页: 每页数量", required = true) }) @GetMapping("/fans/{userId}/{pageNum}/{pageSize}") @GlobalInterceptor(checkAppUserLogin = true) - public Result> getFans(@RequestHeader(value = "Authorization", required = false) String authorization, + public Result> getFans( + @RequestHeader(value = "Authorization", required = true) String authorization, @PathVariable @VerifyParam(required = true) String userId, @PathVariable @VerifyParam(required = true) Integer pageNum, @PathVariable @VerifyParam(required = true) Integer pageSize) { return getCollectedUserInfo(userId, pageNum, pageSize, CollectTypeEnum.FANS); } - + + @ApiOperation(value = "8.意见反馈", notes = "每天最多反馈10条") + @PostMapping("/feedback") + @GlobalInterceptor(checkAppUserLogin = true, frequencyType = RequestFrequencyTypeEnum.DAY, requestFrequencyThreshold = 10) + public Result sendFeedback(@RequestHeader(value = "Authorization", required = true) String authorization, + @ApiParam(value = "反馈类型,3个值,0:bug, 1:建议,2:其它", required = true) @VerifyParam(required = true) @RequestParam("type") Integer type, + @ApiParam(value = "反馈内容,最多300字", required = true) @VerifyParam(required = true, max = 300) @RequestParam("content") String content, + @ApiParam(value = "图片,单张图片最大5M,一次上传最多10张图片", required = false) @RequestParam("files") List files, + @ApiParam(value = "联系方式(可选),最多50字", required = false) @RequestParam("contact") @VerifyParam(max = 50) String contact) { + UserLoginDto userLoginDto = getUserLoginDto(authorization); + Feedback feedback = new Feedback(); + feedback.setFeedbackId(String.valueOf(idWorker.nextId())); + feedback.setType(type); + feedback.setUserId(userLoginDto.getUserId()); + feedback.setNickName(userLoginDto.getNickName()); + feedback.setContent(content); + feedback.setImages(uploadImages(feedback, files)); + feedbackService.save(feedback); + return Result.success(); + } + + private String uploadImages(Feedback feedback, List files) { + if (null == files || files.isEmpty()) { + return null; + } + return files.parallelStream().map(f -> uploadImages(feedback, f)).collect(Collectors.joining(",")); + } + + @SneakyThrows + private String uploadImages(Feedback feedback, MultipartFile file) { + String imageName = feedback.getUserId() + "_" + feedback.getFeedbackId() + "_" + idWorker.nextId() + + StringTools.getFileSuffix(file.getOriginalFilename()); + String filePath = USER_FEEDBACK_IMAGE_DIRECTORY + imageName; + s3Service.uploadImage("indie", filePath, file.getBytes()); + return imageName; + } + private Result> getCollectedUserInfo(String userId, Integer pageNum, Integer pageSize, CollectTypeEnum collectTypeEnum) { - Pair,Set> pair = userCollectService.getCollectListWithBothFollowSet(userId, pageNum, pageSize, collectTypeEnum); + Pair, Set> pair = userCollectService.getCollectListWithBothFollowSet(userId, pageNum, + pageSize, collectTypeEnum); List objectIds = pair.getKey(); - if(objectIds.isEmpty()) { + if (objectIds.isEmpty()) { return Result.success(new PageResult(0L, Collections.emptyList())); } List userInfos = userInfoService.orderByField(objectIds); - List results = userInfos.stream().map(s -> getUserRespDTO(s,false,pair.getRight())) + List results = userInfos.stream().map(s -> getUserRespDTO(s, false, pair.getRight())) .collect(Collectors.toList()); - + return Result.success(new PageResult(Long.valueOf(results.size()), results)); } - private UserRespDTO getUserRespDTO(UserInfo user,boolean withCount, Set bothFollowSet) { + private UserRespDTO getUserRespDTO(UserInfo user, boolean withCount, Set bothFollowSet) { UserRespDTO userRespDTO = new UserRespDTO(); BeanUtils.copyProperties(user, userRespDTO); if (null != userRespDTO.getAvatar()) { @@ -250,10 +299,10 @@ public class MyController extends BaseController { userRespDTO.setBirthDay( DateUtil.format(user.getBirthday(), DateTimePatternEnum.YYYY_DOT_MM_DOT_DD.getPattern())); } - if(!bothFollowSet.isEmpty()&&bothFollowSet.contains(userRespDTO.getId())) { + if (!bothFollowSet.isEmpty() && bothFollowSet.contains(userRespDTO.getId())) { userRespDTO.setRelation(UserRelationEnum.BOTH_FOLLOW.getStatus()); } - if(!withCount) { + if (!withCount) { return userRespDTO; } Optional optional = userCollectService.findByUserId(userRespDTO.getId()); @@ -264,7 +313,7 @@ public class MyController extends BaseController { userRespDTO.setFansCount(userCollect.getFans().size()); userRespDTO.setFollowCount(userCollect.getFollows().size()); } - + return userRespDTO; } } diff --git a/luoo_user/src/main/java/com/luoo/user/dao/FeedbackDao.java b/luoo_user/src/main/java/com/luoo/user/dao/FeedbackDao.java new file mode 100644 index 0000000..2f55df3 --- /dev/null +++ b/luoo_user/src/main/java/com/luoo/user/dao/FeedbackDao.java @@ -0,0 +1,7 @@ +package com.luoo.user.dao; + +import com.luoo.user.pojo.Feedback; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FeedbackDao extends JpaRepository { +} diff --git a/luoo_user/src/main/java/com/luoo/user/dto/UserFeedbackDto.java b/luoo_user/src/main/java/com/luoo/user/dto/UserFeedbackDto.java new file mode 100644 index 0000000..33732db --- /dev/null +++ b/luoo_user/src/main/java/com/luoo/user/dto/UserFeedbackDto.java @@ -0,0 +1,27 @@ +package com.luoo.user.dto; + +import java.util.List; + +import org.springframework.web.multipart.MultipartFile; + +import annotation.VerifyParam; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class UserFeedbackDto { + @ApiModelProperty(value = "反馈类型,3个值,0:bug, 1:建议,2:其它", example = "0") + @VerifyParam(required = true) + private int type; + + @ApiModelProperty(value = "反馈内容,最多300字") + @VerifyParam(required = true, max = 300) + private String content; + + @ApiModelProperty(value = "图片,单张图片最大5M,一次上传最多10张图片") + private List files; + + @ApiModelProperty(value = "联系方式(可选),最多50字") + @VerifyParam(max = 50) + private String contact; +} diff --git a/luoo_user/src/main/java/com/luoo/user/pojo/Feedback.java b/luoo_user/src/main/java/com/luoo/user/pojo/Feedback.java new file mode 100644 index 0000000..7eb9e4b --- /dev/null +++ b/luoo_user/src/main/java/com/luoo/user/pojo/Feedback.java @@ -0,0 +1,92 @@ +package com.luoo.user.pojo; + +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; + + +@Getter +@Setter +@Entity +@Table(name="tb_user_feedback") +@EntityListeners(AuditingEntityListener.class) +public class Feedback implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Id + private String feedbackId; + + /** + * 用户ID + */ + private String userId; + + /** + * 昵称 + */ + private String nickName; + + /** + * 反馈内容 + */ + private String content; + /** + * 反馈类型,3个值,0:bug, 1:建议,2:其它 + */ + private int type; + /** + * 反馈图片 + */ + private String images; + + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @CreatedDate + private Date createTime; + + /** + * 父级ID + */ + private String pFeedbackId; + + /** + * 状态0:未回复 1:已回复 + */ + private int status; + + /** + * 0:访客 1:管理员 + */ + private int sendType; + + /** + * 访客最后发送时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @LastModifiedDate + private Date clientLastSendTime; +} diff --git a/luoo_user/src/main/java/com/luoo/user/service/FeedbackService.java b/luoo_user/src/main/java/com/luoo/user/service/FeedbackService.java new file mode 100644 index 0000000..54f2653 --- /dev/null +++ b/luoo_user/src/main/java/com/luoo/user/service/FeedbackService.java @@ -0,0 +1,17 @@ +package com.luoo.user.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.luoo.user.dao.FeedbackDao; +import com.luoo.user.pojo.Feedback; + +@Service +public class FeedbackService { + @Autowired + private FeedbackDao feedbackDao; + + public void save(Feedback appFeedback) { + feedbackDao.save(appFeedback); + } +} diff --git a/luoo_user/src/main/java/com/luoo/user/service/S3Service.java b/luoo_user/src/main/java/com/luoo/user/service/S3Service.java index 79da1b0..65cb52d 100644 --- a/luoo_user/src/main/java/com/luoo/user/service/S3Service.java +++ b/luoo_user/src/main/java/com/luoo/user/service/S3Service.java @@ -1,7 +1,5 @@ package com.luoo.user.service; -import com.google.common.collect.Lists; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import software.amazon.awssdk.core.sync.RequestBody; @@ -14,11 +12,9 @@ import software.amazon.awssdk.services.s3.presigner.S3Presigner; import javax.annotation.Resource; import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; -import java.util.function.Consumer; @Service @@ -97,7 +93,7 @@ public class S3Service { return 1; } - public void uploadAvatar(String bucket, String key, byte[] buffer) { + public void uploadImage(String bucket, String key, byte[] buffer) { PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket(bucket) .key(key)