Compare commits
1 Commits
d53bc3966c
...
feature-Da
| Author | SHA1 | Date | |
|---|---|---|---|
| 34392f137f |
@@ -1,16 +0,0 @@
|
|||||||
package com.bao.dating.config;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Component
|
|
||||||
@ConfigurationProperties(prefix = "aliyun.oss")
|
|
||||||
public class AliyunOSSConfig {
|
|
||||||
private String endpoint;
|
|
||||||
private String accessKeyId;
|
|
||||||
private String accessKeySecret;
|
|
||||||
private String bucketName;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -34,8 +34,8 @@ public class WebConfig implements WebMvcConfigurer {
|
|||||||
"/user/emailLogin",
|
"/user/emailLogin",
|
||||||
"/api/verification/send-email-code",
|
"/api/verification/send-email-code",
|
||||||
"/ip/location",
|
"/ip/location",
|
||||||
"/user/sendCode",
|
"/user/login",
|
||||||
"/download/{postId}"
|
"/user/sendCode"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package com.bao.dating.controller;
|
|||||||
import com.bao.dating.context.UserContext;
|
import com.bao.dating.context.UserContext;
|
||||||
import com.bao.dating.service.ContactsService;
|
import com.bao.dating.service.ContactsService;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -14,7 +12,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/contacts")
|
|
||||||
public class ContactsController {
|
public class ContactsController {
|
||||||
@Resource
|
@Resource
|
||||||
private ContactsService contactsService;
|
private ContactsService contactsService;
|
||||||
@@ -45,56 +42,4 @@ public class ContactsController {
|
|||||||
result.put("data", friends);
|
result.put("data", friends);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拉黑联系人接口
|
|
||||||
* @param userId 当前用户ID
|
|
||||||
* @param contactUserId 被拉黑联系人ID
|
|
||||||
* @return 接口响应
|
|
||||||
*/
|
|
||||||
@PostMapping("/blacklist/{userId}/{contactUserId}")
|
|
||||||
public ResponseEntity<Map<String, Object>> blacklistContact(
|
|
||||||
@PathVariable Long userId,
|
|
||||||
@PathVariable Long contactUserId) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
boolean success = contactsService.blacklistContact(userId, contactUserId);
|
|
||||||
if (success) {
|
|
||||||
result.put("code", 200);
|
|
||||||
result.put("msg", "拉黑联系人成功");
|
|
||||||
result.put("data", null);
|
|
||||||
return ResponseEntity.ok(result);
|
|
||||||
} else {
|
|
||||||
result.put("code", 500);
|
|
||||||
result.put("msg", "拉黑联系人失败,联系人不存在或参数错误");
|
|
||||||
result.put("data", null);
|
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除联系人接口
|
|
||||||
* @param userId 当前用户ID
|
|
||||||
* @param contactUserId 被删除联系人ID
|
|
||||||
* @return 接口响应
|
|
||||||
*/
|
|
||||||
@PostMapping("/delete/{userId}/{contactUserId}")
|
|
||||||
public ResponseEntity<Map<String, Object>> deleteContact(
|
|
||||||
@PathVariable Long userId,
|
|
||||||
@PathVariable Long contactUserId) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
boolean success = contactsService.deleteContact(userId, contactUserId);
|
|
||||||
if (success) {
|
|
||||||
result.put("code", 200);
|
|
||||||
result.put("msg", "删除联系人成功");
|
|
||||||
result.put("data", null);
|
|
||||||
return ResponseEntity.ok(result);
|
|
||||||
} else {
|
|
||||||
result.put("code", 500);
|
|
||||||
result.put("msg", "删除联系人失败,联系人不存在或参数错误");
|
|
||||||
result.put("data", null);
|
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.bao.dating.controller;
|
||||||
|
|
||||||
|
import com.bao.dating.common.Result;
|
||||||
|
import com.bao.dating.common.ResultCode;
|
||||||
|
import com.bao.dating.pojo.vo.DataAnalysisVO;
|
||||||
|
import com.bao.dating.util.DataAnalysisRedisService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/dataAnalysis")
|
||||||
|
public class DataAnalysisController {
|
||||||
|
@Resource
|
||||||
|
private DataAnalysisRedisService dataAnalysisRedisService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计动态
|
||||||
|
* @param days 统计时常
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
@GetMapping("/postTotal")
|
||||||
|
public Result<DataAnalysisVO> postDataAnalysis(@RequestParam Integer days){
|
||||||
|
if (checkParam(days)){
|
||||||
|
return Result.error(ResultCode.PARAM_ERROR);
|
||||||
|
}
|
||||||
|
Long count = dataAnalysisRedisService.countPostTotalByDays(days);
|
||||||
|
String timePeriod = dataAnalysisRedisService.calculateTimeRanges(LocalDateTime.now(), days);
|
||||||
|
DataAnalysisVO dataAnalysisVO = new DataAnalysisVO();
|
||||||
|
dataAnalysisVO.setTotal(count);
|
||||||
|
dataAnalysisVO.setTimePeriod(timePeriod);
|
||||||
|
return Result.success(ResultCode.SUCCESS,dataAnalysisVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/loginUserTotal")
|
||||||
|
public Result<DataAnalysisVO> loginUserDataAnalysis(@RequestParam Integer days){
|
||||||
|
if (checkParam(days)){
|
||||||
|
return Result.error(ResultCode.PARAM_ERROR);
|
||||||
|
}
|
||||||
|
Long count = dataAnalysisRedisService.countLoginUserTotalByDays(days);
|
||||||
|
String timePeriod = dataAnalysisRedisService.calculateTimeRanges(LocalDateTime.now(), days);
|
||||||
|
DataAnalysisVO dataAnalysisVO = new DataAnalysisVO();
|
||||||
|
dataAnalysisVO.setTotal(count);
|
||||||
|
dataAnalysisVO.setTimePeriod(timePeriod);
|
||||||
|
return Result.success(ResultCode.SUCCESS,dataAnalysisVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检验参数
|
||||||
|
* @param days 查询天数
|
||||||
|
* @return 参数是否合法
|
||||||
|
*/
|
||||||
|
public Boolean checkParam(Integer days){
|
||||||
|
ArrayList<Integer> day = new ArrayList<>();
|
||||||
|
day.add(7);
|
||||||
|
day.add(15);
|
||||||
|
day.add(30);
|
||||||
|
day.add(365);
|
||||||
|
return days != null && day.contains(days);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,17 @@
|
|||||||
package com.bao.dating.controller;
|
package com.bao.dating.controller;
|
||||||
|
|
||||||
|
|
||||||
import com.bao.dating.anno.Log;
|
|
||||||
import com.bao.dating.common.Result;
|
import com.bao.dating.common.Result;
|
||||||
import com.bao.dating.common.ResultCode;
|
import com.bao.dating.common.ResultCode;
|
||||||
import com.bao.dating.pojo.dto.PostRequestDTO;
|
import com.bao.dating.pojo.dto.PostRequestDTO;
|
||||||
import com.bao.dating.pojo.entity.Post;
|
import com.bao.dating.pojo.entity.Post;
|
||||||
import com.bao.dating.pojo.vo.PostEditVO;
|
import com.bao.dating.pojo.vo.PostEditVO;
|
||||||
import com.bao.dating.service.PostService;
|
import com.bao.dating.service.PostService;
|
||||||
|
import com.bao.dating.util.DataAnalysisRedisService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,6 +26,9 @@ public class PostController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PostService postService;
|
private PostService postService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DataAnalysisRedisService dataAnalysisRedisService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传媒体文件接口 like
|
* 上传媒体文件接口 like
|
||||||
* @param files 媒体文件数组
|
* @param files 媒体文件数组
|
||||||
@@ -49,6 +49,9 @@ public class PostController {
|
|||||||
public Result<Post> createPostJson(@RequestBody PostRequestDTO postDTO) {
|
public Result<Post> createPostJson(@RequestBody PostRequestDTO postDTO) {
|
||||||
// 调用 Service 层处理发布动态业务逻辑
|
// 调用 Service 层处理发布动态业务逻辑
|
||||||
Post result = postService.createPost(postDTO);
|
Post result = postService.createPost(postDTO);
|
||||||
|
//这里将发布动态操作记录到redis中
|
||||||
|
Long postId = result.getPostId();
|
||||||
|
dataAnalysisRedisService.recordPostData(postId);
|
||||||
return Result.success(ResultCode.SUCCESS, "动态发布成功,等待审核。", result);
|
return Result.success(ResultCode.SUCCESS, "动态发布成功,等待审核。", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,20 +89,4 @@ public class PostController {
|
|||||||
PostEditVO result = postService.updatePost(postId, postRequestDTO);
|
PostEditVO result = postService.updatePost(postId, postRequestDTO);
|
||||||
return Result.success(ResultCode.SUCCESS, "动态更新成功", result);
|
return Result.success(ResultCode.SUCCESS, "动态更新成功", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/download/{postId}")
|
|
||||||
public void downloadPostImage(@PathVariable Long postId, HttpServletResponse response) throws Exception {
|
|
||||||
try {
|
|
||||||
//Service 返回已经加好水印的图片
|
|
||||||
BufferedImage image = postService.downloadWithWatermark(postId);
|
|
||||||
//设置响应头,触发浏览器下载
|
|
||||||
response.setContentType("image/jpeg");
|
|
||||||
response.setHeader("Content-Disposition", "attachment;filename=post_" + postId + ".jpg");
|
|
||||||
//输出到浏览器
|
|
||||||
ImageIO.write(image, "jpg", response.getOutputStream());
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,15 +6,16 @@ import com.bao.dating.common.ResultCode;
|
|||||||
import com.bao.dating.context.UserContext;
|
import com.bao.dating.context.UserContext;
|
||||||
import com.bao.dating.pojo.dto.UserInfoDTO;
|
import com.bao.dating.pojo.dto.UserInfoDTO;
|
||||||
import com.bao.dating.pojo.dto.UserLoginDTO;
|
import com.bao.dating.pojo.dto.UserLoginDTO;
|
||||||
import com.bao.dating.pojo.entity.User;
|
|
||||||
import com.bao.dating.pojo.vo.UserInfoVO;
|
import com.bao.dating.pojo.vo.UserInfoVO;
|
||||||
import com.bao.dating.pojo.vo.UserLoginVO;
|
import com.bao.dating.pojo.vo.UserLoginVO;
|
||||||
import com.bao.dating.service.UserService;
|
import com.bao.dating.service.UserService;
|
||||||
|
import com.bao.dating.util.DataAnalysisRedisService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -30,6 +31,9 @@ public class UserController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DataAnalysisRedisService dataAnalysisRedisService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录
|
* 登录
|
||||||
* @param userLoginDTO 登录参数
|
* @param userLoginDTO 登录参数
|
||||||
@@ -37,6 +41,12 @@ public class UserController {
|
|||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {
|
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {
|
||||||
UserLoginVO userloginVO = userService.userLogin(userLoginDTO);
|
UserLoginVO userloginVO = userService.userLogin(userLoginDTO);
|
||||||
|
//将用户登录记录到redis中
|
||||||
|
if (userloginVO != null){
|
||||||
|
Long userId = userloginVO.getUserId();
|
||||||
|
dataAnalysisRedisService.recordLoginUserData(userId);
|
||||||
|
}
|
||||||
|
|
||||||
return Result.success(ResultCode.SUCCESS, "登录成功", userloginVO);
|
return Result.success(ResultCode.SUCCESS, "登录成功", userloginVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +139,11 @@ public class UserController {
|
|||||||
}
|
}
|
||||||
//登录
|
//登录
|
||||||
UserLoginVO vo = userService.loginByPhone(phone);
|
UserLoginVO vo = userService.loginByPhone(phone);
|
||||||
|
//将用户登录操作记录到redis中
|
||||||
|
if (vo != null){
|
||||||
|
Long userId = vo.getUserId();
|
||||||
|
dataAnalysisRedisService.recordLoginUserData(userId);
|
||||||
|
}
|
||||||
return Result.success(ResultCode.SUCCESS, "登录成功", vo);
|
return Result.success(ResultCode.SUCCESS, "登录成功", vo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +216,9 @@ public class UserController {
|
|||||||
if (userLoginVO == null){
|
if (userLoginVO == null){
|
||||||
return Result.error(ResultCode.FAIL,"请先注册用户或添加邮箱");
|
return Result.error(ResultCode.FAIL,"请先注册用户或添加邮箱");
|
||||||
}
|
}
|
||||||
|
//将用户登录操作记录到redis中
|
||||||
|
Long userId = userLoginVO.getUserId();
|
||||||
|
dataAnalysisRedisService.recordLoginUserData(userId);
|
||||||
return Result.success(ResultCode.SUCCESS,"用户登录成功",userLoginVO);
|
return Result.success(ResultCode.SUCCESS,"用户登录成功",userLoginVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,20 +17,4 @@ public interface ContactMapper {
|
|||||||
*/
|
*/
|
||||||
List<Map<String, Object>> selectFriendsByUserId(@Param("userId") Long userId);
|
List<Map<String, Object>> selectFriendsByUserId(@Param("userId") Long userId);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拉黑联系人
|
|
||||||
* @param userId 当前用户ID
|
|
||||||
* @param contactUserId 被拉黑的联系人ID
|
|
||||||
* @return 影响行数
|
|
||||||
*/
|
|
||||||
int blacklistContact(@Param("userId") Long userId, @Param("contactUserId") Long contactUserId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除联系人(逻辑删除)
|
|
||||||
* @param userId 当前用户ID
|
|
||||||
* @param contactUserId 被删除的联系人ID
|
|
||||||
* @return 影响行数
|
|
||||||
*/
|
|
||||||
int deleteContact(@Param("userId") Long userId, @Param("contactUserId") Long contactUserId);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import org.apache.ibatis.annotations.Mapper;
|
|||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态Mapper
|
* 动态Mapper
|
||||||
@@ -118,12 +117,4 @@ public interface PostMapper {
|
|||||||
* @return 影响行数
|
* @return 影响行数
|
||||||
*/
|
*/
|
||||||
int decreaseFavoriteCount(Long postId);
|
int decreaseFavoriteCount(Long postId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据动态id查询用户名和媒体信息
|
|
||||||
*
|
|
||||||
* @param postId 动态id
|
|
||||||
* @return 用户名和媒体信息
|
|
||||||
*/
|
|
||||||
Map<String, Object> getUsernameByUserId(Long postId);
|
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main/java/com/bao/dating/pojo/vo/DataAnalysisVO.java
Normal file
11
src/main/java/com/bao/dating/pojo/vo/DataAnalysisVO.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.bao.dating.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DataAnalysisVO {
|
||||||
|
//所有总数
|
||||||
|
private Long total;
|
||||||
|
//时间段
|
||||||
|
private String timePeriod;
|
||||||
|
}
|
||||||
@@ -15,20 +15,6 @@ public interface ContactsService {
|
|||||||
List<Map<String, Object>> getFriendsByUserId(Long userId);
|
List<Map<String, Object>> getFriendsByUserId(Long userId);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拉黑联系人
|
|
||||||
* @param userId 当前用户ID
|
|
||||||
* @param contactUserId 被拉黑联系人ID
|
|
||||||
* @return 操作是否成功
|
|
||||||
*/
|
|
||||||
boolean blacklistContact(Long userId, Long contactUserId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除联系人(逻辑删除)
|
|
||||||
* @param userId 当前用户ID
|
|
||||||
* @param contactUserId 被删除联系人ID
|
|
||||||
* @return 操作是否成功
|
|
||||||
*/
|
|
||||||
boolean deleteContact(Long userId, Long contactUserId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import com.bao.dating.pojo.entity.Post;
|
|||||||
import com.bao.dating.pojo.vo.PostEditVO;
|
import com.bao.dating.pojo.vo.PostEditVO;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,11 +55,4 @@ public interface PostService {
|
|||||||
* @return 用户id
|
* @return 用户id
|
||||||
*/
|
*/
|
||||||
Long selectUserIdByPostId(Long postId);
|
Long selectUserIdByPostId(Long postId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 下载动态图片并添加水印
|
|
||||||
* @param postId 动态ID
|
|
||||||
* @return 带水印的图片
|
|
||||||
*/
|
|
||||||
BufferedImage downloadWithWatermark(Long postId) throws Exception;
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,6 @@ import com.bao.dating.service.ContactsService;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -20,34 +19,4 @@ public class ContactServiceImpl implements ContactsService {
|
|||||||
// 直接调用Mapper查询,无额外封装
|
// 直接调用Mapper查询,无额外封装
|
||||||
return contactMapper.selectFriendsByUserId(userId);
|
return contactMapper.selectFriendsByUserId(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 拉黑联系人
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public boolean blacklistContact(Long userId, Long contactUserId) {
|
|
||||||
// 参数校验
|
|
||||||
if (userId == null || contactUserId == null || userId.equals(contactUserId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// 执行拉黑操作
|
|
||||||
int affectRows = contactMapper.blacklistContact(userId, contactUserId);
|
|
||||||
return affectRows > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除联系人
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public boolean deleteContact(Long userId, Long contactUserId) {
|
|
||||||
// 参数校验
|
|
||||||
if (userId == null || contactUserId == null || userId.equals(contactUserId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// 执行删除操作
|
|
||||||
int affectRows = contactMapper.deleteContact(userId, contactUserId);
|
|
||||||
return affectRows > 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,11 @@ import com.bao.dating.mapper.PostLikeMapper;
|
|||||||
import com.bao.dating.mapper.PostMapper;
|
import com.bao.dating.mapper.PostMapper;
|
||||||
import com.bao.dating.pojo.dto.PostRequestDTO;
|
import com.bao.dating.pojo.dto.PostRequestDTO;
|
||||||
import com.bao.dating.pojo.entity.Post;
|
import com.bao.dating.pojo.entity.Post;
|
||||||
import com.bao.dating.pojo.entity.User;
|
|
||||||
import com.bao.dating.pojo.vo.PostEditVO;
|
import com.bao.dating.pojo.vo.PostEditVO;
|
||||||
import com.bao.dating.service.PostService;
|
import com.bao.dating.service.PostService;
|
||||||
import com.bao.dating.common.aliyun.AliOssUtil;
|
import com.bao.dating.common.aliyun.AliOssUtil;
|
||||||
import com.bao.dating.service.UserService;
|
import com.bao.dating.service.UserService;
|
||||||
import com.bao.dating.util.FileUtil;
|
import com.bao.dating.util.FileUtil;
|
||||||
import com.bao.dating.util.WatermarkUtil;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -24,7 +22,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -60,9 +57,6 @@ public class PostServiceImpl implements PostService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CommentsMapper commentsMapper;
|
private CommentsMapper commentsMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WatermarkUtil watermarkUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传媒体文件
|
* 上传媒体文件
|
||||||
* @param files 媒体文件数组
|
* @param files 媒体文件数组
|
||||||
@@ -350,61 +344,4 @@ public class PostServiceImpl implements PostService {
|
|||||||
return postMapper.selectUserIdByPostId(postId);
|
return postMapper.selectUserIdByPostId(postId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 下载动态图片并添加水印
|
|
||||||
*
|
|
||||||
* @param postId 动态ID
|
|
||||||
* @return 带水印的图片
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BufferedImage downloadWithWatermark(Long postId) throws Exception {
|
|
||||||
// 一次性查出 动态图片 + 作者信息
|
|
||||||
Map<String, Object> map = postMapper.getUsernameByUserId(postId);
|
|
||||||
|
|
||||||
if (map == null || map.isEmpty()) {
|
|
||||||
Post post = postMapper.selectById(postId);
|
|
||||||
if (post == null) {
|
|
||||||
throw new RuntimeException("未找到指定postId的帖子: " + postId);
|
|
||||||
}
|
|
||||||
throw new RuntimeException("未找到与postId相关的用户和媒体信息: " + postId);
|
|
||||||
}
|
|
||||||
|
|
||||||
String mediaUrl = (String) map.get("media_oss_keys");
|
|
||||||
String username = (String) map.get("user_name");
|
|
||||||
Object userIdObj = map.get("user_id");
|
|
||||||
|
|
||||||
if (mediaUrl == null || username == null || userIdObj == null) {
|
|
||||||
throw new RuntimeException("用户或媒体信息不完整: " + map);
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaUrl = mediaUrl.trim();
|
|
||||||
if (mediaUrl.isEmpty()) {
|
|
||||||
throw new RuntimeException("媒体URL为空,postId: " + postId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Long userId = userIdObj instanceof Number
|
|
||||||
? ((Number) userIdObj).longValue()
|
|
||||||
: Long.valueOf(userIdObj.toString());
|
|
||||||
|
|
||||||
// 解析 OSS ObjectKey(支持完整URL和直接存key两种)
|
|
||||||
String cleanUrl = mediaUrl.split("\\?")[0]; // 去掉 ? 后面的参数
|
|
||||||
String objectKey;
|
|
||||||
|
|
||||||
if (cleanUrl.startsWith("http")) {
|
|
||||||
// https://xxx.oss-cn-xxx.aliyuncs.com/post/xxx.jpg → post/xxx.jpg
|
|
||||||
objectKey = cleanUrl.substring(cleanUrl.indexOf(".com/") + 5);
|
|
||||||
} else {
|
|
||||||
objectKey = cleanUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (objectKey.trim().isEmpty()) {
|
|
||||||
throw new RuntimeException("解析后的ObjectKey为空,url: " + mediaUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载并动态加水印(只给下载的人看,OSS原图不改,数据库不动)
|
|
||||||
return watermarkUtil.downloadAndWatermark(objectKey, username, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
101
src/main/java/com/bao/dating/util/DataAnalysisRedisService.java
Normal file
101
src/main/java/com/bao/dating/util/DataAnalysisRedisService.java
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package com.bao.dating.util;
|
||||||
|
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于redis的数据分析工具 -统计动态总数和登录人数
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DataAnalysisRedisService {
|
||||||
|
// Redis Key 定义
|
||||||
|
//动态总数
|
||||||
|
private static final String REDIS_KEY_POST_TOTAL = "data:post:total";
|
||||||
|
//活跃人数
|
||||||
|
private static final String REDIS_KEY_LOGIN_USER_TOTAL = "data:loginUser:total";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录动态向redis中添加数据
|
||||||
|
* @param postId 动态id
|
||||||
|
*/
|
||||||
|
public void recordPostData(Long postId) {
|
||||||
|
// 获取当前毫秒级时间戳(作为Sorted Set的score)
|
||||||
|
long currentTimestamp = System.currentTimeMillis();
|
||||||
|
// 1. 记录动态数据
|
||||||
|
redisTemplate.opsForZSet().add(REDIS_KEY_POST_TOTAL, postId, currentTimestamp);
|
||||||
|
// 可选:设置Key的过期时间(1年+1天,避免数据无限累积)
|
||||||
|
setKeyExpire(REDIS_KEY_POST_TOTAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录动态向redis中添加数据
|
||||||
|
* @param userId 用户id
|
||||||
|
*/
|
||||||
|
public void recordLoginUserData(Long userId) {
|
||||||
|
// 获取当前毫秒级时间戳(作为Sorted Set的score)
|
||||||
|
long currentTimestamp = System.currentTimeMillis();
|
||||||
|
// 1. 记录动态数据
|
||||||
|
redisTemplate.opsForZSet().add(REDIS_KEY_LOGIN_USER_TOTAL, userId, currentTimestamp);
|
||||||
|
// 可选:设置Key的过期时间(1年+1天,避免数据无限累积)
|
||||||
|
setKeyExpire(REDIS_KEY_LOGIN_USER_TOTAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置Redis Key的过期时间(1年+1天,确保1年内的数据都能被查询)
|
||||||
|
*/
|
||||||
|
private void setKeyExpire(String redisKey) {
|
||||||
|
if (Boolean.FALSE.equals(redisTemplate.hasKey(redisKey))) {
|
||||||
|
redisTemplate.expire(redisKey, 366, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计指定时间段内发布的动态
|
||||||
|
* @param days 指定时间段
|
||||||
|
* @return 总数
|
||||||
|
*/
|
||||||
|
public Long countPostTotalByDays(int days) {
|
||||||
|
// 1. 计算时间范围:结束时间=当前时间,起始时间=当前时间 - N天的毫秒数
|
||||||
|
long endTimestamp = System.currentTimeMillis();
|
||||||
|
long startTimestamp = endTimestamp - (long) days * 24 * 60 * 60 * 1000;
|
||||||
|
// 2. key min max - 统计指定score范围内的成员数量(高效,直接返回数量)
|
||||||
|
return redisTemplate.opsForZSet().count(REDIS_KEY_POST_TOTAL, startTimestamp, endTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long countLoginUserTotalByDays(int days) {
|
||||||
|
// 1. 计算时间范围:结束时间=当前时间,起始时间=当前时间 - N天的毫秒数
|
||||||
|
long endTimestamp = System.currentTimeMillis();
|
||||||
|
long startTimestamp = endTimestamp - (long) days * 24 * 60 * 60 * 1000;
|
||||||
|
// 2. key min max - 统计指定score范围内的成员数量(高效,直接返回数量)
|
||||||
|
return redisTemplate.opsForZSet().count(REDIS_KEY_LOGIN_USER_TOTAL, startTimestamp, endTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核心方法:传入当前时间,返回各时间段的结果
|
||||||
|
* @param currentDateTime 当前时间(LocalDateTime类型,可直接通过LocalDateTime.now()获取)
|
||||||
|
*/
|
||||||
|
public String calculateTimeRanges(LocalDateTime currentDateTime,int days) {
|
||||||
|
// 1. 计算各时间段的起始时间(当前时间往前推对应时长)
|
||||||
|
LocalDateTime sevenDaysAgo = currentDateTime.minusDays(7);
|
||||||
|
LocalDateTime fifteenDaysAgo = currentDateTime.minusDays(15);
|
||||||
|
LocalDateTime thirtyDaysAgo = currentDateTime.minusDays(30);
|
||||||
|
LocalDateTime oneYearAgo = currentDateTime.minusYears(1);
|
||||||
|
if (days == 7)
|
||||||
|
return sevenDaysAgo + " - " + currentDateTime;
|
||||||
|
if (days == 15)
|
||||||
|
return fifteenDaysAgo + " - " + currentDateTime;
|
||||||
|
if (days == 30)
|
||||||
|
return thirtyDaysAgo + " - " + currentDateTime;
|
||||||
|
if (days == 365)
|
||||||
|
return oneYearAgo + " - " + currentDateTime;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package com.bao.dating.util;
|
|
||||||
|
|
||||||
import com.aliyun.oss.OSS;
|
|
||||||
import com.aliyun.oss.OSSClientBuilder;
|
|
||||||
import com.bao.dating.config.AliyunOSSConfig;
|
|
||||||
import com.bao.dating.mapper.PostMapper;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class WatermarkUtil {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AliyunOSSConfig aliyunOSSConfig;
|
|
||||||
|
|
||||||
|
|
||||||
public BufferedImage downloadAndWatermark(String objectKey, String username, Long userId) throws Exception {
|
|
||||||
OSS ossClient = new OSSClientBuilder().build(
|
|
||||||
aliyunOSSConfig.getEndpoint(),
|
|
||||||
aliyunOSSConfig.getAccessKeyId(),
|
|
||||||
aliyunOSSConfig.getAccessKeySecret()
|
|
||||||
);
|
|
||||||
|
|
||||||
InputStream inputStream = ossClient.getObject(aliyunOSSConfig.getBucketName(), objectKey).getObjectContent();
|
|
||||||
BufferedImage image = ImageIO.read(inputStream);
|
|
||||||
Graphics2D g2d = image.createGraphics();
|
|
||||||
|
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
|
||||||
|
|
||||||
// 字体小一点
|
|
||||||
Font font = new Font("微软雅黑", Font.BOLD, 24);
|
|
||||||
g2d.setFont(font);
|
|
||||||
|
|
||||||
String text = "作者:" + username + " (ID:" + userId + ")";
|
|
||||||
|
|
||||||
FontMetrics fm = g2d.getFontMetrics();
|
|
||||||
int textWidth = fm.stringWidth(text);
|
|
||||||
int textHeight = fm.getHeight();
|
|
||||||
|
|
||||||
// 右下角留边距
|
|
||||||
int x = image.getWidth() - textWidth - 20;
|
|
||||||
int y = image.getHeight() - 20;
|
|
||||||
|
|
||||||
// 黑色描边
|
|
||||||
g2d.setColor(Color.BLACK);
|
|
||||||
g2d.drawString(text, x - 1, y - 1);
|
|
||||||
g2d.drawString(text, x + 1, y - 1);
|
|
||||||
g2d.drawString(text, x - 1, y + 1);
|
|
||||||
g2d.drawString(text, x + 1, y + 1);
|
|
||||||
|
|
||||||
// 白色正文
|
|
||||||
g2d.setColor(Color.WHITE);
|
|
||||||
g2d.drawString(text, x, y);
|
|
||||||
|
|
||||||
g2d.dispose();
|
|
||||||
ossClient.shutdown();
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,29 +21,5 @@
|
|||||||
AND c.relation_type != 3 -- 排除黑名单
|
AND c.relation_type != 3 -- 排除黑名单
|
||||||
AND c.user_id != c.contact_user_id -- 排除自己
|
AND c.user_id != c.contact_user_id -- 排除自己
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<!-- 拉黑联系人:更新relation_type为3(黑名单)、contact_status为3(已拉黑) -->
|
|
||||||
<update id="blacklistContact">
|
|
||||||
UPDATE contacts
|
|
||||||
SET relation_type = 3,
|
|
||||||
contact_status = 3,
|
|
||||||
updated_at = CURRENT_TIMESTAMP
|
|
||||||
WHERE user_id = #{userId}
|
|
||||||
AND contact_user_id = #{contactUserId}
|
|
||||||
AND contact_status != 2
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<!-- 删除联系人:更新contact_status为2(已删除) -->
|
|
||||||
<update id="deleteContact">
|
|
||||||
UPDATE contacts
|
|
||||||
SET contact_status = 2,
|
|
||||||
updated_at = CURRENT_TIMESTAMP
|
|
||||||
WHERE user_id = #{userId}
|
|
||||||
AND contact_user_id = #{contactUserId}
|
|
||||||
AND contact_status != 2
|
|
||||||
</update>
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -135,11 +135,5 @@
|
|||||||
<select id="selectFavoriteCount" resultType="java.lang.Integer">
|
<select id="selectFavoriteCount" resultType="java.lang.Integer">
|
||||||
select dating.post.favorite_count from dating.post where post.post_id = #{postId}
|
select dating.post.favorite_count from dating.post where post.post_id = #{postId}
|
||||||
</select>
|
</select>
|
||||||
<select id="getUsernameByUserId" resultType="map">
|
|
||||||
SELECT u.user_name, u.user_id, p.media_oss_keys
|
|
||||||
FROM post p
|
|
||||||
LEFT JOIN user u ON p.user_id = u.user_id
|
|
||||||
WHERE p.post_id = #{postId}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -111,9 +111,9 @@
|
|||||||
<result property="latitude" column="user_latitude"/>
|
<result property="latitude" column="user_latitude"/>
|
||||||
<result property="longitude" column="user_longitude"/>
|
<result property="longitude" column="user_longitude"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<select id="findByLatLngRange" resultMap="UserInfoVOResultMap">
|
<select id="findByLatLngRange" resultMap="UserInfoVOResultMap">
|
||||||
SELECT
|
SELECT
|
||||||
user_id,
|
user_id,
|
||||||
user_name,
|
user_name,
|
||||||
nickname,
|
nickname,
|
||||||
|
|||||||
Reference in New Issue
Block a user