Merge branch 'dev/dev_xp' into dev/dev
This commit is contained in:
6
pom.xml
6
pom.xml
@@ -282,6 +282,12 @@
|
||||
<artifactId>itextpdf</artifactId>
|
||||
<version>5.5.13.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -59,4 +59,10 @@ public class CommonConstant {
|
||||
|
||||
public static final List<String> IS_SUBSCRIBE = Arrays.asList("yes", "no");
|
||||
|
||||
public static final String DEFAULT_AVATAR = "aida-users/87/avatar/default.jpg";
|
||||
|
||||
/* 截止至2024/08/26,在Code-Create DB中pmr_users表中最大的用户id */
|
||||
public static final Long MAXIMUM_USER_ID = 704L;
|
||||
// public static final Long MAXIMUM_USER_ID = 225L;
|
||||
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
|
||||
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify",
|
||||
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
|
||||
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify"
|
||||
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify",
|
||||
"/notification"
|
||||
);
|
||||
|
||||
@Override
|
||||
|
||||
@@ -57,4 +57,12 @@ public class AccountTask {
|
||||
accountService.toVisitor(account);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Code-Create上注册的用户添加为AiDA的游客
|
||||
*/
|
||||
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||
public void registerUserToVisitor(){
|
||||
accountService.registerUserToVisitor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,4 +216,17 @@ public class RedisUtil {
|
||||
return redisTemplate.opsForValue().increment(key, 0);
|
||||
}
|
||||
|
||||
public final static String PERSONAL_HOMEPAGE_VIEW_KEY = "PersonalHomepage:view:";
|
||||
|
||||
public void increasePersonalHomepageViewCount(Long accountId) {
|
||||
String key = PERSONAL_HOMEPAGE_VIEW_KEY + accountId;
|
||||
redisTemplate.opsForValue().increment(key);
|
||||
}
|
||||
|
||||
public Long getPersonalHomepageViewCount(Long accountId) {
|
||||
String key = PERSONAL_HOMEPAGE_VIEW_KEY + accountId;
|
||||
return redisTemplate.opsForValue().increment(key, 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -590,4 +590,40 @@ public class SendEmailUtil {
|
||||
throw new BusinessException("failed.to.send.mail");
|
||||
}
|
||||
}
|
||||
|
||||
private final static Long NEW_USER_REGISTER_NOTIFICATION_EN = 126919L;
|
||||
|
||||
public static void notificationForRegisterUser(String receiverAddress){
|
||||
try{
|
||||
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
|
||||
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
|
||||
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
|
||||
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
|
||||
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
||||
HttpProfile httpProfile = new HttpProfile();
|
||||
httpProfile.setEndpoint("ses.tencentcloudapi.com");
|
||||
// 实例化一个client选项,可选的,没有特殊需求可以跳过
|
||||
ClientProfile clientProfile = new ClientProfile();
|
||||
clientProfile.setHttpProfile(httpProfile);
|
||||
// 实例化要请求产品的client对象,clientProfile是可选的
|
||||
SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
|
||||
// 实例化一个请求对象,每个接口都会对应一个request对象
|
||||
SendEmailRequest req = new SendEmailRequest();
|
||||
req.setFromEmailAddress(SEND_ADDRESS);
|
||||
req.setDestination(new String[]{receiverAddress});
|
||||
|
||||
req.setSubject("Welcome to AiDa");
|
||||
Template template = new Template();
|
||||
template.setTemplateID(NEW_USER_REGISTER_NOTIFICATION_EN);
|
||||
template.setTemplateData("{\"email\":\" " + receiverAddress + "\"}");
|
||||
req.setTemplate(template);
|
||||
|
||||
// 返回的resp是一个SendEmailResponse的实例,与请求对象对应
|
||||
SendEmailResponse resp = client.SendEmail(req);
|
||||
log.info("短信发送结果res###{}", SendEmailResponse.toJsonString(resp));
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.info("邮件发送失败###{}", e.toString());
|
||||
throw new BusinessException("failed.to.send.mail");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.ai.da.common.websocket;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
@ServerEndpoint(value = "/notification")
|
||||
@Component
|
||||
@Slf4j
|
||||
public class NotificationConnection {
|
||||
|
||||
static Map<String,Session> sessionMap = new ConcurrentHashMap<>();
|
||||
//连接建立时执行的操作
|
||||
@OnOpen
|
||||
public void onOpen(Session session){
|
||||
sessionMap.put(session.getId(),session);
|
||||
log.info("websocket is open");
|
||||
}
|
||||
//收到了客户端消息执行的操作
|
||||
@OnMessage
|
||||
public void onMessage(String text){
|
||||
log.info("收到了一条消息:"+text);
|
||||
// return "已收到你的消息";
|
||||
}
|
||||
//连接关闭的时候执行的操作
|
||||
@OnClose
|
||||
public void onClose(Session session){
|
||||
sessionMap.remove(session.getId());
|
||||
log.info("websocket is close");
|
||||
}
|
||||
|
||||
public void sendMsg(String message) throws IOException {
|
||||
for(String key:sessionMap.keySet()){
|
||||
sessionMap.get(key).getBasicRemote().sendText(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ai.da.common.websocket.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
/**
|
||||
* Configuration of WebSocket
|
||||
*
|
||||
* @author db1995
|
||||
*/
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,21 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.mapper.primary.entity.TrialOrder;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.vo.AccountLoginVO;
|
||||
import com.ai.da.model.vo.AccountPreLoginVO;
|
||||
import com.ai.da.model.vo.PersonalHomepageVO;
|
||||
import com.ai.da.service.AccountService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -194,4 +197,26 @@ public class AccountController {
|
||||
public Response<List<Long>> setUserValidToDayEnd(){
|
||||
return Response.success(accountService.setUserValidToDayEnd());
|
||||
}
|
||||
|
||||
// 用户上传头像
|
||||
@ApiOperation(value = "上传头像")
|
||||
@PostMapping(path = "/uploadAvatar")
|
||||
public Response<String> uploadAvatar(@RequestParam("file") MultipartFile file) {
|
||||
if (null == file || StringUtils.isEmpty(file.getOriginalFilename())) {
|
||||
throw new BusinessException("file.cannot.be.empty");
|
||||
}
|
||||
return Response.success(accountService.uploadAvatar(file));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "个人主页浏览量增加")
|
||||
@GetMapping("/viewsIncrease")
|
||||
public Response<Boolean> viewsGet(@RequestParam("id") Long id) {
|
||||
return Response.success(accountService.viewsIncrease(id));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取个人主页信息")
|
||||
@GetMapping("/personalHomepage")
|
||||
public Response<PersonalHomepageVO> getPersonalHomepage(@RequestParam("id") Long id){
|
||||
return Response.success(accountService.getPersonalHomepage(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ public class ConvenientInquiryController {
|
||||
|
||||
@ApiOperation("获取指定时间区间内所有用户design的使用情况")
|
||||
@GetMapping("/getDesignStatistic")
|
||||
public Response<List<UserDesignStatisticDTO>> getDesignStatistic(@RequestParam String startTime, @RequestParam String endTime) {
|
||||
public Response<List<UserDesignStatisticDTO>> getDesignStatistic(@RequestParam String startTime, @RequestParam String endTime,
|
||||
@RequestParam(required = false) List<Long> ids, @RequestParam(required = false) String email) {
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
if (accountId.equals(31L) || accountId.equals(87L) || accountId.equals(83L) || accountId.equals(6L) || accountId.equals(4L) || accountId.equals(73L)) {
|
||||
if (StringUtil.isNullOrEmpty(startTime)) startTime = "2024-02-01 00:00:00";
|
||||
@@ -60,7 +61,10 @@ public class ConvenientInquiryController {
|
||||
Date date = new Date();
|
||||
endTime = simpleDateFormat.format(date);
|
||||
}
|
||||
List<UserDesignStatisticDTO> designStatistic = designMapper.getDesignStatistic(startTime, endTime);
|
||||
if (!StringUtil.isNullOrEmpty(email)){
|
||||
email = email.trim();
|
||||
}
|
||||
List<UserDesignStatisticDTO> designStatistic = designMapper.getDesignStatistic(startTime, endTime, ids, email);
|
||||
return Response.success(designStatistic);
|
||||
} else {
|
||||
return Response.fail("Sorry, you don't have permission");
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.model.dto.GetNotificationDTO;
|
||||
import com.ai.da.model.vo.NotificationVO;
|
||||
import com.ai.da.model.dto.PublishSysNotificationDTO;
|
||||
import com.ai.da.service.MessageCenterService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Api(tags = "消息中心模块")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/message")
|
||||
public class MessageCenterController {
|
||||
|
||||
@Resource
|
||||
private MessageCenterService messageCenterService;
|
||||
|
||||
// 获取未读消息总数
|
||||
@ApiOperation(value = "获取未读消息数")
|
||||
@GetMapping("/getUnreadCount")
|
||||
public Response<Map<String, Long>> getUnreadMessage(){
|
||||
return Response.success(messageCenterService.getAllTypeMessageUnreadCount());
|
||||
}
|
||||
|
||||
// 获取历史消息
|
||||
@ApiOperation(value = "获取历史消息")
|
||||
@PostMapping("/getHistoryNotification")
|
||||
public Response<PageBaseResponse<NotificationVO>> getHistoryNotification(@Valid @RequestBody GetNotificationDTO getNotificationDTO) {
|
||||
return Response.success(messageCenterService.getHistoryNotification(getNotificationDTO));
|
||||
}
|
||||
|
||||
// 已读消息
|
||||
@ApiOperation(value = "设置消息状态为已读")
|
||||
@PostMapping("/setReadStatus")
|
||||
public Response<Boolean> setReadStatus(@RequestParam("notificationIdList") List<Long> notificationIdList, @RequestParam("type") String type) {
|
||||
return Response.success(messageCenterService.setReadStatus(notificationIdList, type));
|
||||
}
|
||||
|
||||
// 发布系统消息
|
||||
@ApiOperation(value = "发布系统消息")
|
||||
@PostMapping("/publishSysMessage")
|
||||
public Response<String> publishSysMessage(@Valid @RequestBody PublishSysNotificationDTO message) {
|
||||
messageCenterService.publishSystemNotification(message);
|
||||
return Response.success("success");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "一键已读")
|
||||
@PostMapping("/oneClickRead")
|
||||
public Response<String> setReadAll(@RequestParam("type") String type) {
|
||||
messageCenterService.setReadAll(type);
|
||||
return Response.success("success");
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.vo.CommentVO;
|
||||
import com.ai.da.model.vo.PortfolioVO;
|
||||
import com.ai.da.model.vo.UserLikeChooseVO;
|
||||
import com.ai.da.model.vo.UserLikeGroupVO;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.ai.da.service.PortfolioService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -16,6 +15,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "Portfolio模块")
|
||||
@Slf4j
|
||||
@@ -117,4 +117,31 @@ public class PortfolioController {
|
||||
public Response<Boolean> commentDelete(@Valid @RequestBody CommentDTO commentDTO) {
|
||||
return Response.success(portfolioService.commentDelete(commentDTO));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "关注")
|
||||
@GetMapping("/follow")
|
||||
public Response<String> follow(@RequestParam("followeeId") Long followeeId) {
|
||||
portfolioService.follow(followeeId);
|
||||
return Response.success(BusinessException.getMessageFromResource("subscription.success"));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "取消关注")
|
||||
@GetMapping("/cancelFollow")
|
||||
public Response<String> cancelFollow(@RequestParam("followeeId") Long followeeId) {
|
||||
portfolioService.cancelFollow(followeeId);
|
||||
return Response.success(BusinessException.getMessageFromResource("unsubscribe.success"));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取关注列表")
|
||||
@PostMapping("/getFolloweeList")
|
||||
public Response<List<AccountFollowVO>> getFolloweeList(@Valid @RequestBody GetFollowListDTO getFollowListDTO) {
|
||||
return Response.success(portfolioService.getFolloweeList(getFollowListDTO));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取粉丝列表")
|
||||
@PostMapping("/getFollowerList")
|
||||
public Response<List<AccountFollowVO>> getFollowerList(@Valid @RequestBody GetFollowListDTO getFollowListDTO) {
|
||||
return Response.success(portfolioService.getFollowerList(getFollowListDTO));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,5 +18,5 @@ public interface DesignMapper extends CommonMapper<Design> {
|
||||
//返回插入数据后生成的主键
|
||||
Long insertDesign(Design design);
|
||||
|
||||
List<UserDesignStatisticDTO> getDesignStatistic(String startTime, String endTime);
|
||||
List<UserDesignStatisticDTO> getDesignStatistic(String startTime, String endTime, List<Long> ids, String email);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||
import com.ai.da.mapper.primary.entity.Notification;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface NotificationMapper extends CommonMapper<Notification> {
|
||||
|
||||
List<Map<String, Object>> getTypeCount(Long receiverId);
|
||||
|
||||
/** 解决mybatis-plus自动过滤 is_deleted为1的数据 问题 */
|
||||
Notification getUniqueLikeAndFollow(String type, Long senderId, Long receiverId, Long portfolioId);
|
||||
|
||||
void updateUniqueLikeAndFollow(Long id, LocalDateTime time);
|
||||
|
||||
void deleteNotification(Long id, LocalDateTime time);
|
||||
|
||||
void setPersonalNotificationAllRead(String type, Long receiverId, LocalDateTime time);
|
||||
|
||||
List<Long> getUnreadSysNotification(Long accountId);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||
import com.ai.da.mapper.primary.entity.SysNotificationReadStatus;
|
||||
|
||||
public interface SysNotificationReadStatusMapper extends CommonMapper<SysNotificationReadStatus> {
|
||||
}
|
||||
19
src/main/java/com/ai/da/mapper/primary/UserFollowMapper.java
Normal file
19
src/main/java/com/ai/da/mapper/primary/UserFollowMapper.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||
import com.ai.da.mapper.primary.entity.UserFollow;
|
||||
import com.ai.da.model.vo.AccountFollowVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface UserFollowMapper extends CommonMapper<UserFollow> {
|
||||
List<AccountFollowVO> getFolloweeListByFollower(Long followerAccountId, Integer limit, Integer offset, String order);
|
||||
|
||||
List<AccountFollowVO> getFollowerListByFollowee(Long followeeAccountId, Integer limit, Integer offset, String order);
|
||||
|
||||
List<AccountFollowVO> getFolloweeListByName(String name, Long followerId);
|
||||
|
||||
List<AccountFollowVO> getFollowerListByName(String name, Long followeeId);
|
||||
|
||||
}
|
||||
@@ -99,4 +99,9 @@ public class Account implements Serializable {
|
||||
* 4 : 参加活动获取30天有效期和6000个积分的用户
|
||||
*/
|
||||
private Integer systemUser;
|
||||
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("t_notification")
|
||||
@Data
|
||||
public class Notification extends BaseEntity{
|
||||
/**
|
||||
* 操作类型 system/like/comment/follow
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 发起操作者用户id
|
||||
*/
|
||||
private Long senderId;
|
||||
/**
|
||||
* 被操作对象用户id
|
||||
*/
|
||||
private Long receiverId;
|
||||
/**
|
||||
* 点赞评论时的作品id
|
||||
*/
|
||||
private Long portfolioId;
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 评论id
|
||||
*/
|
||||
private Long commentId;
|
||||
/**
|
||||
* 个人消息已读状态
|
||||
*/
|
||||
private Integer isRead;
|
||||
/**
|
||||
* 系统消息发布状态
|
||||
*/
|
||||
private Integer publishFlag;
|
||||
|
||||
/**
|
||||
* 是否被删除
|
||||
*/
|
||||
private Integer isDeleted;
|
||||
|
||||
public Notification() {
|
||||
}
|
||||
|
||||
public Notification(String type, Long senderId, Long receiverId) {
|
||||
this.type = type;
|
||||
this.senderId = senderId;
|
||||
this.receiverId = receiverId;
|
||||
}
|
||||
|
||||
public Notification(String type, Long senderId, Long receiverId, Long portfolioId) {
|
||||
this.type = type;
|
||||
this.senderId = senderId;
|
||||
this.receiverId = receiverId;
|
||||
this.portfolioId = portfolioId;
|
||||
}
|
||||
|
||||
public Notification(String type, Long senderId, Long receiverId, Long portfolioId, String content, Long commentId) {
|
||||
this.type = type;
|
||||
this.senderId = senderId;
|
||||
this.receiverId = receiverId;
|
||||
this.portfolioId = portfolioId;
|
||||
this.content = content;
|
||||
this.commentId = commentId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("t_sys_notification_read_status")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysNotificationReadStatus extends BaseEntity{
|
||||
/**
|
||||
* 系统消息id
|
||||
*/
|
||||
private Long system_notification_id;
|
||||
|
||||
/**
|
||||
* 已读当前消息的用户id将被存储
|
||||
*/
|
||||
private Long account_id;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("t_user_follow")
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserFollow extends BaseEntity{
|
||||
|
||||
/**
|
||||
* 被关注者用户id
|
||||
*/
|
||||
private Long followeeId;
|
||||
/**
|
||||
* 关注者用户id
|
||||
*/
|
||||
private Long followerId;
|
||||
|
||||
|
||||
}
|
||||
19
src/main/java/com/ai/da/model/dto/GetFollowListDTO.java
Normal file
19
src/main/java/com/ai/da/model/dto/GetFollowListDTO.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import com.ai.da.model.vo.PageQueryBaseVo;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@ApiModel("按条件分页查询关注列表")
|
||||
public class GetFollowListDTO extends PageQueryBaseVo {
|
||||
|
||||
@ApiModelProperty("查找指定用户名")
|
||||
private String searchByName;
|
||||
|
||||
@ApiModelProperty("按关注时间排序 DESC 降序 || ASC 升序")
|
||||
private String order;
|
||||
}
|
||||
16
src/main/java/com/ai/da/model/dto/GetNotificationDTO.java
Normal file
16
src/main/java/com/ai/da/model/dto/GetNotificationDTO.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import com.ai.da.model.vo.PageQueryBaseVo;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel
|
||||
@Data
|
||||
public class GetNotificationDTO extends PageQueryBaseVo {
|
||||
|
||||
@ApiModelProperty("system/like/comment/follow/newPosted")
|
||||
private String type;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel("发布系统消息")
|
||||
public class PublishSysNotificationDTO {
|
||||
|
||||
@ApiModelProperty("系统消息标题")
|
||||
private String title;
|
||||
|
||||
@ApiModelProperty("系统消息内容")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty("系统消息 活动链接")
|
||||
private String link;
|
||||
}
|
||||
@@ -14,4 +14,6 @@ public class QueryPortfolioPageDTO extends PageQueryBaseVo {
|
||||
private Integer getMyPortfolio;
|
||||
|
||||
private Integer getLikePortfolio;
|
||||
|
||||
private Long accountId;
|
||||
}
|
||||
|
||||
33
src/main/java/com/ai/da/model/vo/AccountFollowVO.java
Normal file
33
src/main/java/com/ai/da/model/vo/AccountFollowVO.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AccountFollowVO {
|
||||
/**
|
||||
* userId
|
||||
*/
|
||||
private Long senderId;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* followTime
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* mutualFollowing 互粉
|
||||
*/
|
||||
private Integer isFollow;
|
||||
}
|
||||
@@ -34,4 +34,10 @@ public class AccountLoginVO {
|
||||
|
||||
private Integer systemUser;
|
||||
|
||||
private String avatar;
|
||||
|
||||
private Long followeeCount;
|
||||
|
||||
private Long followerCount;
|
||||
|
||||
}
|
||||
|
||||
29
src/main/java/com/ai/da/model/vo/NotificationVO.java
Normal file
29
src/main/java/com/ai/da/model/vo/NotificationVO.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import com.ai.da.mapper.primary.entity.Notification;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class NotificationVO extends Notification {
|
||||
|
||||
/**
|
||||
* senderUserName
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
// private String senderUserAvatar;
|
||||
|
||||
private String portfolioName;
|
||||
|
||||
/**
|
||||
* sender头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
private Integer isFollow;
|
||||
|
||||
private String canvas;
|
||||
|
||||
}
|
||||
31
src/main/java/com/ai/da/model/vo/PersonalHomepageVO.java
Normal file
31
src/main/java/com/ai/da/model/vo/PersonalHomepageVO.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel("个人主页返回信息")
|
||||
public class PersonalHomepageVO {
|
||||
|
||||
@ApiModelProperty("用户名")
|
||||
private String userName;
|
||||
|
||||
@ApiModelProperty("用户头像")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty("用户作品总数")
|
||||
private Long portfolioCount;
|
||||
|
||||
@ApiModelProperty("粉丝总数")
|
||||
private Long followerCount;
|
||||
|
||||
@ApiModelProperty("关注者总数")
|
||||
private Long followeeCount;
|
||||
|
||||
@ApiModelProperty("个人主页总浏览量")
|
||||
private Long homepageViewCount;
|
||||
|
||||
@ApiModelProperty("是否关注了主页用户")
|
||||
private Integer isFollow;
|
||||
}
|
||||
@@ -28,4 +28,8 @@ public class PortfolioVO extends Portfolio {
|
||||
private Integer selected;
|
||||
|
||||
private Integer jumpable;
|
||||
|
||||
private Integer isFollow;
|
||||
|
||||
private String avatar;
|
||||
}
|
||||
|
||||
@@ -3369,6 +3369,7 @@ public class PythonService {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("promptTranslation 用户输入翻译失败; error message => " + e.getMessage());
|
||||
response.close();
|
||||
throw new RuntimeException(e);
|
||||
|
||||
} finally {
|
||||
|
||||
@@ -5,8 +5,10 @@ import com.ai.da.mapper.primary.entity.TrialOrder;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.vo.AccountLoginVO;
|
||||
import com.ai.da.model.vo.AccountPreLoginVO;
|
||||
import com.ai.da.model.vo.PersonalHomepageVO;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
@@ -157,4 +159,12 @@ public interface AccountService extends IService<Account> {
|
||||
|
||||
IPage<Account> getPageByIds(List<Long> ids, int pageNum, int size);
|
||||
List<Account> getByIds(List<Long> ids);
|
||||
|
||||
String uploadAvatar(MultipartFile file);
|
||||
|
||||
PersonalHomepageVO getPersonalHomepage(Long accountId);
|
||||
|
||||
Boolean viewsIncrease(Long id);
|
||||
|
||||
void registerUserToVisitor();
|
||||
}
|
||||
|
||||
28
src/main/java/com/ai/da/service/MessageCenterService.java
Normal file
28
src/main/java/com/ai/da/service/MessageCenterService.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.mapper.primary.entity.Notification;
|
||||
import com.ai.da.model.dto.GetNotificationDTO;
|
||||
import com.ai.da.model.vo.NotificationVO;
|
||||
import com.ai.da.model.dto.PublishSysNotificationDTO;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface MessageCenterService extends IService<Notification> {
|
||||
|
||||
Map<String, Long> getAllTypeMessageUnreadCount();
|
||||
|
||||
PageBaseResponse<NotificationVO> getHistoryNotification(GetNotificationDTO getNotificationDTO);
|
||||
|
||||
void prePushMessage(Notification notification);
|
||||
|
||||
void cancelPushMessage(String type, Long senderId, Long receiverId, Long portfolioId, Long commentId);
|
||||
|
||||
Boolean setReadStatus(List<Long> notificationIdList, String type);
|
||||
|
||||
void setReadAll(String type);
|
||||
|
||||
void publishSystemNotification(PublishSysNotificationDTO message);
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.mapper.primary.entity.Portfolio;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.vo.CommentVO;
|
||||
import com.ai.da.model.vo.PortfolioVO;
|
||||
import com.ai.da.model.vo.UserLikeChooseVO;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PortfolioService extends IService<Portfolio> {
|
||||
Boolean publish(MultipartFile canvas, String data);
|
||||
|
||||
@@ -41,4 +42,22 @@ public interface PortfolioService extends IService<Portfolio> {
|
||||
Boolean delete(Long id);
|
||||
|
||||
Portfolio getByIdAll(Long originalPortfolioId);
|
||||
|
||||
void follow(Long followeeId);
|
||||
|
||||
void cancelFollow(Long followeeId);
|
||||
|
||||
Long getFolloweeCount(Long accountId);
|
||||
|
||||
List<AccountFollowVO> getFolloweeList(GetFollowListDTO getFollowListDTO);
|
||||
|
||||
Long getFollowerCount(Long accountId);
|
||||
|
||||
List<AccountFollowVO> getFollowerList(GetFollowListDTO getFollowListDTO);
|
||||
|
||||
Integer getIfFollowed(Long followeeId, Long followerId);
|
||||
|
||||
Long getPortfolioCount(Long accountId);
|
||||
|
||||
List<Long> getFolloweeList(Long accountId);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ai.da.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.constant.CommonConstant;
|
||||
import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.enums.AuthenticationOperationTypeEnum;
|
||||
import com.ai.da.common.enums.CreditsEventsEnum;
|
||||
@@ -16,10 +17,7 @@ import com.ai.da.mapper.primary.entity.*;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.enums.AutoApproved;
|
||||
import com.ai.da.model.enums.Language;
|
||||
import com.ai.da.model.vo.AccountLoginVO;
|
||||
import com.ai.da.model.vo.AccountPreLoginVO;
|
||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||
import com.ai.da.model.vo.QuestionnaireVO;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.ai.da.service.*;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
@@ -32,9 +30,11 @@ import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -83,6 +83,15 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
@Resource
|
||||
private CreditsService creditsService;
|
||||
|
||||
@Resource
|
||||
private MinioUtil minioUtil;
|
||||
|
||||
@Value("${minio.bucketName.users}")
|
||||
private String userBucket;
|
||||
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AccountPreLoginVO preLogin(AccountPreLoginDTO accountDTO) {
|
||||
@@ -137,6 +146,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
return new AccountPreLoginVO(account.getId());
|
||||
}
|
||||
|
||||
@Resource
|
||||
private PortfolioService portfolioService;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public AccountLoginVO login(AccountLoginDTO accountLoginDTO, HttpServletRequest request) {
|
||||
@@ -189,6 +201,16 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
}
|
||||
response.setUserId(account.getId());
|
||||
response.setSystemUser(account.getSystemUser());
|
||||
// 设置头像
|
||||
String avatar;
|
||||
if (StringUtil.isNullOrEmpty(account.getAvatar())){
|
||||
avatar = CommonConstant.DEFAULT_AVATAR;
|
||||
}else {
|
||||
avatar = account.getAvatar();
|
||||
}
|
||||
response.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
response.setFolloweeCount(portfolioService.getFolloweeCount(account.getId()));
|
||||
response.setFollowerCount(portfolioService.getFollowerCount(account.getId()));
|
||||
//判断是否常用ip 不是则发邮件提示
|
||||
calculateExceptionIp(RequestInfoUtil.getIpAddress(request), account);
|
||||
return response;
|
||||
@@ -300,6 +322,19 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("BINARY user_email", email);
|
||||
List<Account> accountList = accountMapper.selectList(queryWrapper);
|
||||
log.info(accountList.toString());
|
||||
if (CollectionUtil.isEmpty(accountList)) {
|
||||
throw new BusinessException("email.does.not.exist", ResultEnum.PROMPT.getCode());
|
||||
}
|
||||
return accountList.get(0);
|
||||
}
|
||||
|
||||
// 忽略大小写
|
||||
private Account getAccountByEmail(String email) {
|
||||
QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_email", email);
|
||||
List<Account> accountList = accountMapper.selectList(queryWrapper);
|
||||
log.info(accountList.toString());
|
||||
if (CollectionUtil.isEmpty(accountList)) {
|
||||
throw new BusinessException("email.does.not.exist", ResultEnum.PROMPT.getCode());
|
||||
}
|
||||
@@ -1011,7 +1046,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
account.setIsTrial(1);
|
||||
account.setIsBeginner(1);
|
||||
account.setCreateDate(new Date());
|
||||
account.setCredits(BigDecimal.valueOf(500));
|
||||
account.setCredits(BigDecimal.valueOf(100));
|
||||
accountMapper.insert(account);
|
||||
AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class);
|
||||
response.setEmail(account.getUserEmail());
|
||||
@@ -1044,6 +1079,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
config.setJdbcUrl("jdbc:mysql://code-create.com.hk:3306/db1nfvsgmjp3b8");
|
||||
config.setUsername("uafqtz4gsvfrw");
|
||||
config.setPassword("aida123456.");
|
||||
// config.setJdbcUrl("jdbc:mysql://localhost:3306/code-create-local?serverTimezone=UTC");
|
||||
// config.setUsername("root");
|
||||
// config.setPassword("root");
|
||||
config.addDataSourceProperty("cachePrepStmts", "true");
|
||||
config.addDataSourceProperty("prepStmtCacheSize", "250");
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
|
||||
@@ -1068,6 +1106,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
int orderId = queryOrderResultSet.getInt("order_id");
|
||||
int customerId = queryOrderResultSet.getInt("customer_id");
|
||||
double totalSales = queryOrderResultSet.getDouble("total_sales");
|
||||
log.info("Code-Create 订单:{}, 顾客id:{}, 付款金额:{}",orderId, customerId, totalSales);
|
||||
String email = "";
|
||||
String userName = "";
|
||||
// 为什么一般没有值
|
||||
@@ -1094,7 +1133,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
Boolean flag = Boolean.FALSE;
|
||||
try {
|
||||
// 不是新用户 直接延长使用期限
|
||||
userInfo = getOneByEmail(email);
|
||||
userInfo = getAccountByEmail(email);
|
||||
} catch (BusinessException e) {
|
||||
// 通过邮箱找不到用户 说明是新用户 => 创建用户
|
||||
flag = Boolean.TRUE;
|
||||
@@ -1106,23 +1145,24 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
Account account = extendValidity(validEndTime, totalSales);
|
||||
|
||||
int systemUserType = 0;
|
||||
|
||||
// 不管是不是新用户 都要更新用户角色和积分
|
||||
String credits = "0";
|
||||
if (totalSales == 5000.0){
|
||||
log.info("年付用户,初始积分6000");
|
||||
credits = CreditsEventsEnum.INIT_MONTHLY.getValue();
|
||||
systemUserType = 1;
|
||||
}else if (totalSales == 500.0){
|
||||
log.info("月付用户,初始积分5000");
|
||||
credits = CreditsEventsEnum.INIT_MONTHLY.getValue();
|
||||
systemUserType = 2;
|
||||
}else if (totalSales == 0.0){
|
||||
log.info("测试用户,初始积分10");
|
||||
credits = "10";
|
||||
systemUserType = 3;
|
||||
}
|
||||
if (flag) {
|
||||
// 是新用户 => 新增一条数据
|
||||
String credits = "0";
|
||||
if (totalSales == 5000.0){
|
||||
log.info("年付用户,初始积分6000");
|
||||
credits = CreditsEventsEnum.INIT_MONTHLY.getValue();
|
||||
systemUserType = 1;
|
||||
}else if (totalSales == 500.0){
|
||||
log.info("月付用户,初始积分5000");
|
||||
credits = CreditsEventsEnum.INIT_MONTHLY.getValue();
|
||||
systemUserType = 2;
|
||||
}else if (totalSales == 0.0){
|
||||
log.info("测试用户,初始积分10");
|
||||
credits = "10";
|
||||
systemUserType = 3;
|
||||
}
|
||||
|
||||
Boolean b = addUser(new AccountAddDTO(email,
|
||||
StringUtil.isNullOrEmpty(userName) ? email.substring(0, email.indexOf("@")) : userName,
|
||||
country,
|
||||
@@ -1131,6 +1171,8 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
if (b) log.info("付费新用户 {} 新增成功!", email);
|
||||
} else {
|
||||
userInfo.setValidEndTime(toDayEnd(account.getValidEndTime()));
|
||||
userInfo.setCredits(new BigDecimal(credits));
|
||||
userInfo.setSystemUser(systemUserType);
|
||||
baseMapper.updateById(userInfo);
|
||||
log.info("付费用户 {} 续订成功", email);
|
||||
}
|
||||
@@ -1196,6 +1238,86 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
return account;
|
||||
}
|
||||
|
||||
private static final String QUERY_MAXIMUM_USERID = "SELECT MAX(ID) AS max_id FROM pmr_users;";
|
||||
|
||||
private static final String QUERY_NEW_USER_EMAIL = "SELECT user_email FROM pmr_users " +
|
||||
"WHERE ID > ? ";
|
||||
|
||||
@Value("${redis.key.maximumUserId}")
|
||||
private String maximumUserIdKey;
|
||||
|
||||
/**
|
||||
* 将Code-Create上注册的用户添加为AiDA的游客
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void registerUserToVisitor(){
|
||||
ArrayList<String> newUserEmails = new ArrayList<>();
|
||||
long maxUserId = CommonConstant.MAXIMUM_USER_ID;
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement(QUERY_MAXIMUM_USERID)) {
|
||||
try (ResultSet queryOrderResultSet = preparedStatement.executeQuery()) {
|
||||
while (queryOrderResultSet.next()) {
|
||||
// 获取最新的最大用户id
|
||||
maxUserId = queryOrderResultSet.getLong("max_id");
|
||||
// 获取历史最大用户id
|
||||
long maxUserIdHistory = StringUtil.isNullOrEmpty(redisUtil.getFromString(maximumUserIdKey)) ? CommonConstant.MAXIMUM_USER_ID : Long.parseLong(redisUtil.getFromString(maximumUserIdKey));
|
||||
if (maxUserId > maxUserIdHistory){
|
||||
// 查出新增用户的邮箱
|
||||
PreparedStatement newUserEmail = connection.prepareStatement(QUERY_NEW_USER_EMAIL);
|
||||
// 填充参数 - 历史最大用户ID
|
||||
newUserEmail.setLong(1, maxUserIdHistory);
|
||||
try (ResultSet queryEmailResultSet = newUserEmail.executeQuery()) {
|
||||
if (queryEmailResultSet.next()) {
|
||||
String email = queryEmailResultSet.getString("user_email");
|
||||
newUserEmails.add(email);
|
||||
} /*else {
|
||||
log.error("未知错误。code-create的用户表中没有付费用户的信息");
|
||||
throw new BusinessException("user info missing");
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 记录异常并处理
|
||||
e.printStackTrace();
|
||||
// return null;
|
||||
}
|
||||
|
||||
if (!newUserEmails.isEmpty()){
|
||||
// 查询这些邮箱在aida上是否有账号
|
||||
QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.in("user_email", newUserEmails).select("user_email");
|
||||
|
||||
List<String> collect = baseMapper.selectList(queryWrapper).stream().map(Account::getUserEmail).collect(Collectors.toList());
|
||||
if (!collect.isEmpty()){
|
||||
// 移除Code-Create新增用户中在AiDA已有账号的邮箱
|
||||
newUserEmails.removeAll(collect);
|
||||
}
|
||||
// 将新增用户添加到AiDA,身份为游客
|
||||
if (!newUserEmails.isEmpty()){
|
||||
newUserEmails.forEach(email -> {
|
||||
Account account = new Account();
|
||||
account.setUserEmail(email);
|
||||
account.setUserName(email);
|
||||
account.setUserPassword("Third-000000");
|
||||
account.setLanguage(Language.ENGLISH.name());
|
||||
account.setCreateDate(new Date());
|
||||
account.setIsTrial(0);
|
||||
account.setIsBeginner(1);
|
||||
account.setCredits(new BigDecimal(0));
|
||||
account.setSystemUser(0);
|
||||
baseMapper.insert(account);
|
||||
// 邮件通知用户
|
||||
SendEmailUtil.notificationForRegisterUser(email);
|
||||
});
|
||||
}
|
||||
// 记录当前最大的用户id
|
||||
redisUtil.addToString(maximumUserIdKey, String.valueOf(maxUserId));
|
||||
}
|
||||
}
|
||||
|
||||
// 收集调查问卷的信息
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -1404,7 +1526,63 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
return baseMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
public String uploadAvatar(MultipartFile file){
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 1、上传图片到minio
|
||||
String avatarPath = minioUtil.upload(userBucket, accountId.toString() + "/avatar", file);
|
||||
// 2、查询该用户之前的头像
|
||||
String avatar = baseMapper.selectById(accountId).getAvatar();
|
||||
if (!StringUtil.isNullOrEmpty(avatar) && !avatar.equals(CommonConstant.DEFAULT_AVATAR)){
|
||||
minioUtil.deleteObject(avatar);
|
||||
}
|
||||
|
||||
// 3、替换新的头像
|
||||
Account account = new Account();
|
||||
account.setId(accountId);
|
||||
account.setAvatar(avatarPath);
|
||||
baseMapper.updateById(account);
|
||||
|
||||
return minioUtil.getPreSignedUrl(avatarPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME);
|
||||
}
|
||||
|
||||
public PersonalHomepageVO getPersonalHomepage(Long accountId){
|
||||
// 需要返回 用户头像 用户名 作品总量 粉丝量 关注量 主页访问量 当前用户是否被查看者关注
|
||||
Long currentUserId = UserContext.getUserHolder().getId();
|
||||
PersonalHomepageVO personalHomepageVO = new PersonalHomepageVO();
|
||||
|
||||
Account account = baseMapper.selectById(accountId);
|
||||
personalHomepageVO.setUserName(account.getUserName());
|
||||
String avatar = StringUtil.isNullOrEmpty(account.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : account.getAvatar();
|
||||
personalHomepageVO.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
|
||||
personalHomepageVO.setPortfolioCount(portfolioService.getPortfolioCount(accountId));
|
||||
personalHomepageVO.setFolloweeCount(portfolioService.getFolloweeCount(accountId));
|
||||
personalHomepageVO.setFollowerCount(portfolioService.getFollowerCount(accountId));
|
||||
personalHomepageVO.setHomepageViewCount(viewPersonalHomepageCount(0L));
|
||||
|
||||
|
||||
if (accountId.equals(currentUserId)){
|
||||
personalHomepageVO.setIsFollow(0);
|
||||
Long viewCount = viewPersonalHomepageCount(accountId);
|
||||
// 只有本人才能看到个人主页浏览量
|
||||
personalHomepageVO.setHomepageViewCount(viewCount == null ? 0 : viewCount);
|
||||
}else {
|
||||
personalHomepageVO.setIsFollow(portfolioService.getIfFollowed(accountId, currentUserId));
|
||||
// 非本人浏览主页时增加浏览量
|
||||
viewsIncrease(accountId);
|
||||
}
|
||||
return personalHomepageVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean viewsIncrease(Long id) {
|
||||
redisUtil.increasePersonalHomepageViewCount(id);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
private Long viewPersonalHomepageCount(Long accountId) {
|
||||
redisUtil.getPersonalHomepageViewCount(accountId);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.mysql.cj.util.StringUtils;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
@@ -434,11 +435,20 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl<QuestionnaireMappe
|
||||
|
||||
|
||||
// 新增用户
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean addUser(AccountAddDTO accountAddDTO) {
|
||||
// 需要给的数据 用户邮箱、用户名、账号有效期截止时间、账号类型
|
||||
Account account = CopyUtil.copyObject(accountAddDTO, Account.class);
|
||||
QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_email", account.getUserEmail());
|
||||
|
||||
Account existsAccount = accountMapper.selectOne(queryWrapper);
|
||||
if (!Objects.isNull(existsAccount)){
|
||||
throw new BusinessException("The email address already exists. One email address can only register one AiDA account");
|
||||
}
|
||||
|
||||
// 添加正式用户
|
||||
assert accountAddDTO != null;
|
||||
if (Objects.isNull(accountAddDTO.getSystemUser())) {
|
||||
throw new BusinessException("you have to choose user type");
|
||||
} else {
|
||||
|
||||
@@ -401,6 +401,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
designPythonOutfitDetail.setUserId(userId);
|
||||
designPythonOutfitDetail.setOffset(String.valueOf(priorityOffset.get(Math.abs(Integer.parseInt(jsonObject.getString("priority"))))));
|
||||
designPythonOutfitDetail.setPriority((Integer) jsonObject.get("priority"));
|
||||
designPythonOutfitDetail.setCreateDate(LocalDateTime.now());
|
||||
list.add(designPythonOutfitDetail);
|
||||
}
|
||||
return list;
|
||||
|
||||
@@ -744,7 +744,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
|
||||
|
||||
Long accountId = Long.parseLong(taskId.substring(taskId.lastIndexOf("-") + 1));
|
||||
if (!status.equals("Invalid")){
|
||||
if (!status.equals("Invalid")) {
|
||||
// 4、扣除积分
|
||||
Boolean b = creditsService.taskCreditsDeduction(accountId, taskId);
|
||||
// 3、记录积分变更
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.constant.CommonConstant;
|
||||
import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.utils.CopyUtil;
|
||||
import com.ai.da.common.utils.MinioUtil;
|
||||
import com.ai.da.common.utils.RedisUtil;
|
||||
import com.ai.da.common.websocket.NotificationConnection;
|
||||
import com.ai.da.mapper.primary.CanvasMapper;
|
||||
import com.ai.da.mapper.primary.NotificationMapper;
|
||||
import com.ai.da.mapper.primary.SysNotificationReadStatusMapper;
|
||||
import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.mapper.primary.entity.Notification;
|
||||
import com.ai.da.mapper.primary.entity.Portfolio;
|
||||
import com.ai.da.mapper.primary.entity.SysNotificationReadStatus;
|
||||
import com.ai.da.model.dto.GetNotificationDTO;
|
||||
import com.ai.da.model.dto.PublishSysNotificationDTO;
|
||||
import com.ai.da.model.vo.NotificationVO;
|
||||
import com.ai.da.service.AccountService;
|
||||
import com.ai.da.service.MessageCenterService;
|
||||
import com.ai.da.service.PortfolioService;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.gson.Gson;
|
||||
import com.mysql.cj.util.StringUtils;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class MessageCenterServiceImpl extends ServiceImpl<NotificationMapper, Notification> implements MessageCenterService {
|
||||
|
||||
@Resource
|
||||
private NotificationConnection notificationConnection;
|
||||
@Resource
|
||||
private SysNotificationReadStatusMapper sysNotificationReadStatusMapper;
|
||||
@Resource
|
||||
private AccountService accountService;
|
||||
@Resource
|
||||
private MinioUtil minioUtil;
|
||||
@Resource
|
||||
private PortfolioService portfolioService;
|
||||
@Resource
|
||||
private CanvasMapper canvasMapper;
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
@Value("${redis.key.newPosted}")
|
||||
private String lastViewNewPostedTimeKey;
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Long> getAllTypeMessageUnreadCount() {
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
List<Map<String, Object>> typeCount = baseMapper.getTypeCount(accountId);
|
||||
Map<String, Long> msgTypeCount = typeCount.stream()
|
||||
.collect(Collectors.toMap(
|
||||
map -> (String) map.get("type"),
|
||||
map -> Objects.isNull(map.get("count")) ? 0L : (Long) map.get("count")));
|
||||
msgTypeCount.put("system", getUnreadSystemNotification());
|
||||
msgTypeCount.put("newPosted", getNewPostedCount(accountId));
|
||||
log.info(msgTypeCount.toString());
|
||||
// 整理数据 加上系统消息未读数
|
||||
return msgTypeCount;
|
||||
}
|
||||
|
||||
// 获取历史消息 可指定消息类型 分页查询
|
||||
@Override
|
||||
public PageBaseResponse<NotificationVO> getHistoryNotification(GetNotificationDTO getNotificationDTO) {
|
||||
log.info("获取历史消息:parameter => {}", getNotificationDTO);
|
||||
if (StringUtil.isNullOrEmpty(getNotificationDTO.getType())){
|
||||
throw new BusinessException("type cannot be empty");
|
||||
}
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 查动态
|
||||
if (!StringUtils.isNullOrEmpty(getNotificationDTO.getType()) && getNotificationDTO.getType().equals("newPosted")){
|
||||
return getNewPosted(accountId, getNotificationDTO.getPage(), getNotificationDTO.getSize());
|
||||
}
|
||||
|
||||
QueryWrapper<Notification> queryWrapper = new QueryWrapper<>();
|
||||
if (!StringUtils.isNullOrEmpty(getNotificationDTO.getType())) {
|
||||
queryWrapper.eq("type", getNotificationDTO.getType());
|
||||
}
|
||||
if (!getNotificationDTO.getType().equals("system")){
|
||||
queryWrapper.eq("receiver_id", accountId);
|
||||
}
|
||||
Page<Notification> notificationPage = baseMapper.selectPage(new Page<>(getNotificationDTO.getPage(), getNotificationDTO.getSize()), queryWrapper);
|
||||
|
||||
List<Long> unreadSysNotificationIds = baseMapper.getUnreadSysNotification(accountId);
|
||||
IPage<NotificationVO> convert = notificationPage.convert(o -> {
|
||||
NotificationVO notificationVO = CopyUtil.copyObject(o, NotificationVO.class);
|
||||
Account senderAccount = accountService.getById(notificationVO.getSenderId());
|
||||
notificationVO.setUserName(senderAccount.getUserName());
|
||||
// notificationVO.setSenderUserAvatar(StringUtils.isNullOrEmpty(senderAccount.getAvatar()) ? null : minioUtil.getPreSignedUrl(senderAccount.getAvatar(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
notificationVO.setPortfolioName(Objects.isNull(notificationVO.getPortfolioId()) ? null : portfolioService.getById(notificationVO.getPortfolioId()).getPortfolioName());
|
||||
// 设置单个人 系统消息是否已读
|
||||
if (notificationVO.getType().equals("system")){
|
||||
if (unreadSysNotificationIds.contains(notificationVO.getId())){
|
||||
notificationVO.setIsRead(0);
|
||||
}else {
|
||||
notificationVO.setIsRead(1);
|
||||
}
|
||||
}else {
|
||||
String avatar = StringUtil.isNullOrEmpty(senderAccount.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : senderAccount.getAvatar();
|
||||
notificationVO.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
}
|
||||
return notificationVO;
|
||||
});
|
||||
return PageBaseResponse.success(convert);
|
||||
}
|
||||
|
||||
public void prePushMessage(Notification notification){
|
||||
// 先判断点赞、关注记录是不是唯一
|
||||
if (!getUniqueLikeAndFollow(notification)){
|
||||
// 1、将数据存数据库
|
||||
if (!notification.getType().equals("system")) {
|
||||
notification.setIsRead(0);
|
||||
}
|
||||
notification.setIsDeleted(0);
|
||||
notification.setCreateTime(LocalDateTime.now());
|
||||
save(notification);
|
||||
}
|
||||
// 推送消息
|
||||
pushMessage(notification.getType(), notification.getSenderId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 只记录唯一点赞和关注
|
||||
* 重复点赞、关注只会记录最新的一次操作
|
||||
* @param notification
|
||||
* @return
|
||||
*/
|
||||
public Boolean getUniqueLikeAndFollow(Notification notification){
|
||||
Notification existNotification= null;
|
||||
// 对单个作品的点赞和对某个人的关注 具有唯一性
|
||||
if (notification.getType().equals("like") || notification.getType().equals("follow")){
|
||||
existNotification = baseMapper.getUniqueLikeAndFollow(notification.getType(), notification.getSenderId(),
|
||||
notification.getReceiverId(), notification.getPortfolioId());
|
||||
}
|
||||
|
||||
if (!Objects.isNull(existNotification)){
|
||||
// 有记录,则更新 1、删除状态 为0 2、已读状态 为0 3、创建时间 为最新时间 4、更新时间 为最新时间
|
||||
baseMapper.updateUniqueLikeAndFollow(existNotification.getId(), LocalDateTime.now());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
// 消息推送 只需要返回当前操作类型和该操作未读消息数量
|
||||
public void pushMessage(String type, Long receiverId) {
|
||||
// 推送消息到前端
|
||||
ArrayList<Map<String, Object>> resp = new ArrayList<>();
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
Long count;
|
||||
if (!type.equals("system")) {
|
||||
// 个人未读消息
|
||||
count = getUnreadCountByType(type, receiverId);
|
||||
} else {
|
||||
// 系统未读消息
|
||||
count = getUnreadSystemNotification();
|
||||
}
|
||||
|
||||
data.put(type, count);
|
||||
resp.add(data);
|
||||
String jsonString = JSON.toJSONString(resp);
|
||||
log.info("消息推送 : {}", jsonString);
|
||||
|
||||
try {
|
||||
notificationConnection.sendMsg(jsonString);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 取消点赞、删除评论、取消关注
|
||||
public void cancelPushMessage(String type, Long senderId, Long receiverId, Long portfolioId, Long commentId) {
|
||||
QueryWrapper<Notification> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("type", type)
|
||||
.eq("sender_id", senderId)
|
||||
.eq("receiver_id", receiverId)
|
||||
.eq("is_deleted", 0);
|
||||
|
||||
if (!type.equals("follow")){
|
||||
queryWrapper.eq("portfolio_id", portfolioId);
|
||||
}
|
||||
if (type.equals("comment")) {
|
||||
queryWrapper.eq("comment_id", commentId);
|
||||
}
|
||||
Notification notification = baseMapper.selectOne(queryWrapper);
|
||||
if (!Objects.isNull(notification)) {
|
||||
baseMapper.deleteNotification(notification.getId(), LocalDateTime.now());
|
||||
}
|
||||
// 推送消息
|
||||
pushMessage(type, senderId);
|
||||
}
|
||||
|
||||
// 获取个人指定消息类型未读消息数量
|
||||
private Long getUnreadCountByType(String type, Long receiverId) {
|
||||
QueryWrapper<Notification> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("type", type)
|
||||
.eq("is_read", 0)
|
||||
.eq("receiver_id", receiverId);
|
||||
|
||||
return baseMapper.selectCount(queryWrapper);
|
||||
}
|
||||
|
||||
private Long getUnreadSystemNotification() {
|
||||
// 计算总的系统通知数量
|
||||
QueryWrapper<Notification> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("type", "system");
|
||||
Long totalSysCount = baseMapper.selectCount(queryWrapper);
|
||||
|
||||
// 计算单个用户读了多少条系统数据
|
||||
QueryWrapper<SysNotificationReadStatus> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("account_id", UserContext.getUserHolder().getId());
|
||||
Long readCount = sysNotificationReadStatusMapper.selectCount(wrapper);
|
||||
|
||||
// 计算差
|
||||
return totalSysCount - readCount > 0 ? totalSysCount - readCount : 0;
|
||||
}
|
||||
|
||||
// 设置个人消息的已读状态 (允许一次已读多条个人消息)
|
||||
public Boolean setReadStatus(List<Long> notificationIdList, String type) {
|
||||
if (type.equals("system")) {
|
||||
setReadStatusSystem(notificationIdList);
|
||||
} else {
|
||||
UpdateWrapper<Notification> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.in("id", notificationIdList)
|
||||
// .eq("type", type)
|
||||
.set("is_read", 1)
|
||||
.set("update_time", LocalDateTime.now());
|
||||
|
||||
baseMapper.update(null, updateWrapper);
|
||||
}
|
||||
pushMessage(type, UserContext.getUserHolder().getId());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
// 设置系统消息的已读状态 (允许一次已读多条系统消息)
|
||||
public void setReadStatusSystem(List<Long> notificationIdList) {
|
||||
Long id = UserContext.getUserHolder().getId();
|
||||
for (Long notificationId : notificationIdList) {
|
||||
SysNotificationReadStatus sysNotificationReadStatus = new SysNotificationReadStatus(notificationId, id);
|
||||
sysNotificationReadStatus.setCreateTime(LocalDateTime.now());
|
||||
sysNotificationReadStatusMapper.insert(sysNotificationReadStatus);
|
||||
}
|
||||
}
|
||||
|
||||
// 一键已读
|
||||
public void setReadAll(String type){
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 指定某个用户的某种类型的数据,将未读数据全部已读
|
||||
if (!type.equals("system")){
|
||||
// 个人消息已读
|
||||
baseMapper.setPersonalNotificationAllRead(type, accountId, LocalDateTime.now());
|
||||
}else {
|
||||
// 系统消息已读
|
||||
// 1、先确定当前用户未读的系统消息有哪些
|
||||
List<Long> unreadSysNotificationIds = baseMapper.getUnreadSysNotification(accountId);
|
||||
// 2、将未读的设为已读
|
||||
if (!unreadSysNotificationIds.isEmpty()) setReadStatusSystem(unreadSysNotificationIds);
|
||||
}
|
||||
pushMessage(type, accountId);
|
||||
}
|
||||
|
||||
// 发布系统消息
|
||||
public void publishSystemNotification(PublishSysNotificationDTO message) {
|
||||
Notification notification = new Notification();
|
||||
notification.setType("system");
|
||||
notification.setSenderId(UserContext.getUserHolder().getId());
|
||||
notification.setContent(new Gson().toJson(message));
|
||||
// todo 是否需要定时发送系统通知
|
||||
prePushMessage(notification);
|
||||
}
|
||||
|
||||
public Long getNewPostedCount(Long accountId){
|
||||
// 1.1 获取我关注的所有用户
|
||||
List<Long> followeeList = portfolioService.getFolloweeList(accountId);
|
||||
// 1.2 查询我关注的用户在我上次查看动态之后发布的作品数量
|
||||
String lastViewTime = redisUtil.getFromString(lastViewNewPostedTimeKey + ":" + accountId);
|
||||
|
||||
QueryWrapper<Portfolio> queryWrapper = new QueryWrapper<>();
|
||||
if (!followeeList.isEmpty()){
|
||||
queryWrapper.in("account_id", followeeList);
|
||||
}else {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
if (!StringUtil.isNullOrEmpty(lastViewTime)){
|
||||
queryWrapper.gt("create_date", lastViewTime);
|
||||
}else {
|
||||
return 0L;
|
||||
}
|
||||
return portfolioService.getBaseMapper().selectCount(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关注用户发布的新作品 分页查询
|
||||
*/
|
||||
public PageBaseResponse<NotificationVO> getNewPosted(Long accountId, Integer page, Integer size){
|
||||
|
||||
// 1、获取关注用户发布的所有作品
|
||||
// 1.1 获取我关注的所有用户
|
||||
List<Long> followeeList = portfolioService.getFolloweeList(accountId);
|
||||
// 1.2 分页查询我关注的用户发布的作品
|
||||
QueryWrapper<Portfolio> queryWrapper = new QueryWrapper<>();
|
||||
if (!followeeList.isEmpty()){
|
||||
queryWrapper.in("account_id", followeeList);
|
||||
}else {
|
||||
return new PageBaseResponse<>(new ArrayList<>(), page, size, 0, 0);
|
||||
}
|
||||
queryWrapper.orderByDesc("create_date");
|
||||
Page<Portfolio> portfolioPage = portfolioService.getBaseMapper().selectPage(new Page<>(page, size), queryWrapper);
|
||||
// 2、组装返回的数据
|
||||
|
||||
IPage<NotificationVO> convert = portfolioPage.convert(o -> {
|
||||
NotificationVO notificationVO = CopyUtil.copyObject(o, NotificationVO.class);
|
||||
notificationVO.setPortfolioId(o.getId());
|
||||
notificationVO.setSenderId(o.getAccountId());
|
||||
notificationVO.setReceiverId(accountId);
|
||||
notificationVO.setCreateTime(o.getCreateDate());
|
||||
notificationVO.setType("newPosted");
|
||||
Account account = accountService.getById(o.getAccountId());
|
||||
notificationVO.setUserName(account.getUserName());
|
||||
String avatar = StringUtil.isNullOrEmpty(account.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : account.getAvatar();
|
||||
notificationVO.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
|
||||
notificationVO.setPortfolioName(o.getPortfolioName());
|
||||
String canvas = canvasMapper.selectById(o.getCanvasId()).getUrl();
|
||||
notificationVO.setCanvas(minioUtil.getPreSignedUrl(canvas, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
|
||||
String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
// 增加访问时间记录
|
||||
redisUtil.addToString(lastViewNewPostedTimeKey + ":" + accountId, format);
|
||||
|
||||
return notificationVO;
|
||||
});
|
||||
|
||||
return PageBaseResponse.success(convert);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.constant.CommonConstant;
|
||||
import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.utils.CopyUtil;
|
||||
@@ -8,6 +9,7 @@ import com.ai.da.common.utils.MinioUtil;
|
||||
import com.ai.da.common.utils.RedisUtil;
|
||||
import com.ai.da.mapper.primary.*;
|
||||
import com.ai.da.mapper.primary.entity.*;
|
||||
import com.ai.da.mapper.primary.entity.Collection;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.enums.Position;
|
||||
import com.ai.da.model.enums.Sex;
|
||||
@@ -20,20 +22,18 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.base.Function;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import sun.security.krb5.internal.crypto.Des;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio> implements PortfolioService {
|
||||
@@ -76,7 +76,6 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
@Resource
|
||||
private DesignItemDetailPrintMapper designItemDetailPrintMapper;
|
||||
|
||||
|
||||
@Resource
|
||||
private MinioUtil minioUtil;
|
||||
|
||||
@@ -110,6 +109,9 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
@Resource
|
||||
private WorkspaceRelStyleMapper workspaceRelStyleMapper;
|
||||
|
||||
@Resource
|
||||
private UserFollowMapper userFollowMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean publish(MultipartFile file, String data) {
|
||||
@@ -170,7 +172,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
portfolio.setOriginal(0);
|
||||
portfolio.setOriginalAccountId(userLikeGroup.getOriginalAccountId());
|
||||
portfolio.setOriginalPortfolioId(userLikeGroup.getOriginalPortfolioId());
|
||||
}else {
|
||||
} else {
|
||||
portfolio.setOriginal(1);
|
||||
// portfolio.setOriginalAccountId(authPrincipalVo.getId());
|
||||
}
|
||||
@@ -188,7 +190,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
portfolio.setPortfolioDes(portfolioDTO.getPortfolioDes());
|
||||
if (!CollectionUtils.isEmpty(portfolios)) {
|
||||
portfolioMapper.updateById(portfolio);
|
||||
}else {
|
||||
} else {
|
||||
portfolioMapper.insert(portfolio);
|
||||
}
|
||||
|
||||
@@ -262,7 +264,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
portfolio.setOriginal(0);
|
||||
portfolio.setOriginalAccountId(userLikeGroup.getOriginalAccountId());
|
||||
portfolio.setOriginalPortfolioId(userLikeGroup.getOriginalPortfolioId());
|
||||
}else {
|
||||
} else {
|
||||
portfolio.setOriginal(1);
|
||||
// portfolio.setOriginalAccountId(authPrincipalVo.getId());
|
||||
}
|
||||
@@ -279,7 +281,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
portfolio.setPortfolioDes(portfolioDTO.getPortfolioDes());
|
||||
if (!CollectionUtils.isEmpty(portfolios)) {
|
||||
portfolioMapper.updateById(portfolio);
|
||||
}else {
|
||||
} else {
|
||||
portfolioMapper.insert(portfolio);
|
||||
}
|
||||
}
|
||||
@@ -423,17 +425,19 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
QueryWrapper<Portfolio> qw = new QueryWrapper<>();
|
||||
if (query.getGetMyPortfolio() == 1) {
|
||||
qw.lambda().eq(Portfolio::getAccountId, userHolder.getId());
|
||||
} else if (!Objects.isNull(query.getAccountId())) {
|
||||
qw.lambda().eq(Portfolio::getAccountId, query.getAccountId());
|
||||
}
|
||||
if (query.getGetLikePortfolio() == 1) {
|
||||
List<Long> likedPortfolioIdList = redisUtil.getLikedPortfolios(userHolder.getId());
|
||||
if (!CollectionUtils.isEmpty(likedPortfolioIdList)) {
|
||||
qw.lambda().in(Portfolio::getId, likedPortfolioIdList);
|
||||
}else {
|
||||
} else {
|
||||
return PageBaseResponse.success(new Page<>());
|
||||
}
|
||||
}
|
||||
qw.lambda().orderByDesc(Portfolio::getUpdateDate);
|
||||
IPage<Portfolio> page = portfolioMapper.selectPage(new Page<>(query.getPage(), query.getSize()),qw);
|
||||
IPage<Portfolio> page = portfolioMapper.selectPage(new Page<>(query.getPage(), query.getSize()), qw);
|
||||
IPage<PortfolioVO> convert = page.convert((Function<Portfolio, PortfolioVO>) portfolio -> {
|
||||
if (portfolio != null) {
|
||||
PortfolioVO vo = CopyUtil.copyObject(portfolio, PortfolioVO.class);
|
||||
@@ -479,19 +483,28 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
Canvas canvas = canvasMapper.selectById(vo.getCanvasId());
|
||||
vo.setCanvasUrl(minioUtil.getPreSignedUrl(canvas.getUrl(), 24 * 60));
|
||||
vo.setLikeNum(redisUtil.getLikeCount(vo.getId()));
|
||||
String avatar;
|
||||
Account account = accountMapper.selectById(vo.getAccountId());
|
||||
if (userHolder == null) {
|
||||
vo.setIsLike(0);
|
||||
}else {
|
||||
vo.setIsFollow(0);
|
||||
avatar = CommonConstant.DEFAULT_AVATAR;
|
||||
} else {
|
||||
boolean postLikedByUser = redisUtil.isPostLikedByUser(portfolioDTO.getId(), userHolder.getId());
|
||||
if (postLikedByUser) {
|
||||
vo.setIsLike(1);
|
||||
}else {
|
||||
} else {
|
||||
vo.setIsLike(0);
|
||||
}
|
||||
// 设置当前用户是否关注了所查看作品的作者
|
||||
Integer ifFollowed = getIfFollowed(portfolio.getAccountId(), userHolder.getId());
|
||||
vo.setIsFollow(ifFollowed);
|
||||
avatar = StringUtil.isNullOrEmpty(account.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : account.getAvatar();
|
||||
}
|
||||
vo.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
redisUtil.increaseViewCount(portfolioDTO.getId());
|
||||
vo.setViewNums(redisUtil.getViewCount(portfolioDTO.getId()));
|
||||
vo.setUserName(accountMapper.selectById(vo.getAccountId()).getUserName());
|
||||
vo.setUserName(account.getUserName());
|
||||
if (vo.getOriginal() == 0) {
|
||||
vo.setOriginalUserName(accountMapper.selectById(vo.getOriginalAccountId()).getUserName());
|
||||
Portfolio byId = portfolioMapper.getByIdAll(vo.getOriginalPortfolioId());
|
||||
@@ -500,7 +513,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
vo.setOriginalPortfolioName(portfolioName);
|
||||
if (byId.getIsDeleted() == 0) {
|
||||
vo.setJumpable(1);
|
||||
}else {
|
||||
} else {
|
||||
vo.setJumpable(0);
|
||||
}
|
||||
}
|
||||
@@ -508,11 +521,11 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
if (userHolder == null) {
|
||||
vo.setIsMine(0);
|
||||
vo.setSelected(0);
|
||||
}else {
|
||||
} else {
|
||||
if (Objects.equals(vo.getAccountId(), userHolder.getId()) || Objects.equals(vo.getOriginalAccountId(), userHolder.getId())) {
|
||||
vo.setIsMine(1);
|
||||
vo.setSelected(1);
|
||||
}else {
|
||||
} else {
|
||||
vo.setIsMine(0);
|
||||
QueryWrapper<UserLikeGroup> getSelectedQw = new QueryWrapper<>();
|
||||
getSelectedQw.lambda().eq(UserLikeGroup::getAccountId, userHolder.getId());
|
||||
@@ -520,7 +533,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
List<UserLikeGroup> userLikeGroups = userLikeGroupMapper.selectList(getSelectedQw);
|
||||
if (CollectionUtils.isEmpty(userLikeGroups)) {
|
||||
vo.setSelected(0);
|
||||
}else {
|
||||
} else {
|
||||
vo.setSelected(1);
|
||||
}
|
||||
}
|
||||
@@ -547,12 +560,12 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
if (portfolio.getOriginal() == 1) {
|
||||
if (Objects.equals(portfolio.getAccountId(), authPrincipalVo.getId())) {
|
||||
userLikeGroupNew.setOriginal(1);
|
||||
}else {
|
||||
} else {
|
||||
userLikeGroupNew.setOriginal(0);
|
||||
userLikeGroupNew.setOriginalAccountId(portfolio.getAccountId());
|
||||
userLikeGroupNew.setOriginalPortfolioId(portfolio.getId());
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
userLikeGroupNew.setOriginal(0);
|
||||
userLikeGroupNew.setOriginalAccountId(portfolio.getOriginalAccountId());
|
||||
userLikeGroupNew.setOriginalPortfolioId(portfolio.getId());
|
||||
@@ -572,7 +585,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
if (workspace.getSex().equals(Sex.FEMALE.getValue())) {
|
||||
design.setTemplateId(workspace.getMannequinFemaleId());
|
||||
design.setModelType(workspace.getMannequinFemaleType());
|
||||
}else {
|
||||
} else {
|
||||
design.setTemplateId(workspace.getMannequinMaleId());
|
||||
design.setModelType(workspace.getMannequinMaleType());
|
||||
}
|
||||
@@ -580,7 +593,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
if (workspace.getPosition().equals(Position.OVERALL.getValue())) {
|
||||
design.setSingleOverall("overall");
|
||||
design.setSwitchCategory("");
|
||||
}else {
|
||||
} else {
|
||||
design.setSingleOverall("single");
|
||||
design.setSwitchCategory(workspace.getPosition());
|
||||
}
|
||||
@@ -698,7 +711,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
workspaceNew.setSystemDesignerPercentage((design1.getSystemScale().multiply(BigDecimal.valueOf(100)).intValue()));
|
||||
if (design1.getSingleOverall().equals("overall")) {
|
||||
workspaceNew.setPosition("Overall");
|
||||
}else {
|
||||
} else {
|
||||
workspaceNew.setPosition(design1.getSwitchCategory());
|
||||
}
|
||||
workspaceMapper.insert(workspaceNew);
|
||||
@@ -727,7 +740,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
workspaceNew.setMannequinMaleId(anotherOne.getId());
|
||||
workspaceNew.setMannequinMaleType("System");
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
workspaceNew.setSex("Male");
|
||||
workspaceNew.setMannequinMaleId(design1.getTemplateId());
|
||||
workspaceNew.setMannequinMaleType("System");
|
||||
@@ -751,7 +764,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
workspaceNew.setMannequinFemaleType("System");
|
||||
}
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
Library library = libraryMapper.selectById(design1.getTemplateId());
|
||||
if (library.getLevel2Type().equals("Female")) {
|
||||
workspaceNew.setSex("Female");
|
||||
@@ -766,7 +779,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
workspaceNew.setMannequinMaleId(anotherOne.getId());
|
||||
workspaceNew.setMannequinMaleType("System");
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
workspaceNew.setSex("Male");
|
||||
workspaceNew.setMannequinMaleId(design1.getTemplateId());
|
||||
workspaceNew.setMannequinMaleType("Library");
|
||||
@@ -795,15 +808,22 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Resource
|
||||
private MessageCenterService messageCenterService;
|
||||
|
||||
@Override
|
||||
public Boolean like(Long id) {
|
||||
AuthPrincipalVo userHolder = UserContext.getUserHolder();
|
||||
redisUtil.likePost(id, userHolder.getId());
|
||||
Portfolio byIdAll = baseMapper.getByIdAll(id);
|
||||
messageCenterService.prePushMessage(new Notification("like", userHolder.getId(), byIdAll.getAccountId(), id));
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Resource
|
||||
private CommentMapper commentMapper;
|
||||
|
||||
@Override
|
||||
public Boolean comment(CommentDTO commentDTO) {
|
||||
AuthPrincipalVo userHolder = UserContext.getUserHolder();
|
||||
@@ -811,6 +831,8 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
comment.setCreateTime(LocalDateTime.now());
|
||||
comment.setAccountId(userHolder.getId());
|
||||
commentMapper.insert(comment);
|
||||
Portfolio portfolio = baseMapper.selectById(comment.getPortfolioId());
|
||||
messageCenterService.prePushMessage(new Notification("comment", userHolder.getId(), portfolio.getAccountId(), portfolio.getId(), commentDTO.getComment(), comment.getId()));
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@@ -837,6 +859,8 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
public Boolean unlike(Long id) {
|
||||
AuthPrincipalVo userHolder = UserContext.getUserHolder();
|
||||
redisUtil.unLikePost(id, userHolder.getId());
|
||||
Portfolio portfolio = baseMapper.selectById(id);
|
||||
messageCenterService.cancelPushMessage("like", userHolder.getId(), portfolio.getAccountId(), portfolio.getId(), null);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@@ -869,6 +893,15 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
throw new BusinessException("You do not have the permission to delete this comment");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取消息接收者id(即该操作的接收者)
|
||||
Long receiverId;
|
||||
if (!comment.getParentLevel1Id().equals(0L)) {
|
||||
receiverId = commentMapper.selectById(comment.getParentLevel1Id()).getAccountId();
|
||||
} else {
|
||||
receiverId = portfolio.getAccountId();
|
||||
}
|
||||
|
||||
// 删除主评论
|
||||
commentMapper.deleteById(id);
|
||||
|
||||
@@ -879,6 +912,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
.eq(Comment::getParentLevel2Id, id);
|
||||
commentMapper.delete(lambdaQueryWrapper);
|
||||
|
||||
messageCenterService.cancelPushMessage("comment", userHolder.getId(), receiverId, portfolio.getId(), id);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@@ -925,4 +959,143 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
|
||||
// }
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public void follow(Long followeeId) {
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 1、不能关注自己
|
||||
if (Objects.equals(followeeId, accountId)) {
|
||||
throw new BusinessException("you.cannot.follow.yourself", 1);
|
||||
}
|
||||
// 2、不能重复关注
|
||||
QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("followee_id", followeeId).eq("follower_id", accountId);
|
||||
UserFollow userFollow = userFollowMapper.selectOne(queryWrapper);
|
||||
if (!Objects.isNull(userFollow)) {
|
||||
throw new BusinessException("you.have.already.followed.this.user", 1);
|
||||
}
|
||||
// 3、添加新follower到关注列表
|
||||
UserFollow newFollower = new UserFollow(followeeId, accountId);
|
||||
newFollower.setCreateTime(LocalDateTime.now());
|
||||
userFollowMapper.insert(newFollower);
|
||||
// 4、推送消息
|
||||
messageCenterService.prePushMessage(new Notification("follow", accountId, followeeId));
|
||||
}
|
||||
|
||||
// 取消关注
|
||||
public void cancelFollow(Long followeeId) {
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 1、确定是否关注了该用户
|
||||
QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("followee_id", followeeId).eq("follower_id", accountId);
|
||||
UserFollow userFollow = userFollowMapper.selectOne(queryWrapper);
|
||||
// 2、删除关注记录
|
||||
if (!Objects.isNull(userFollow)) {
|
||||
userFollowMapper.deleteById(userFollow.getId());
|
||||
// 3、逻辑删除关注消息
|
||||
messageCenterService.cancelPushMessage("follow", accountId, followeeId, null, null);
|
||||
} else {
|
||||
throw new BusinessException("you.have.not.followed.the.current.user", 1);
|
||||
}
|
||||
}
|
||||
|
||||
public Long getFolloweeCount(Long accountId) {
|
||||
QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("follower_id", accountId).select("followee_id");
|
||||
return userFollowMapper.selectCount(queryWrapper);
|
||||
}
|
||||
|
||||
// 获取某个用户的关注列表 + 按名字查询
|
||||
public List<AccountFollowVO> getFolloweeList(GetFollowListDTO getFollowListDTO) {
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 1、判断是否有按用户名查询
|
||||
List<AccountFollowVO> followeeList;
|
||||
if (!StringUtil.isNullOrEmpty(getFollowListDTO.getSearchByName())) {
|
||||
followeeList = userFollowMapper.getFolloweeListByName(getFollowListDTO.getSearchByName(), accountId);
|
||||
}else {
|
||||
// 2、查全部 分页查询
|
||||
String order = StringUtil.isNullOrEmpty(getFollowListDTO.getOrder()) ? "DESC" : getFollowListDTO.getOrder().equals("DESC") ? "DESC" : "ASC";
|
||||
Integer limit= getFollowListDTO.getSize() > 0 ? getFollowListDTO.getSize() : 20;
|
||||
Integer offset = getFollowListDTO.getPage() > 0 ? (getFollowListDTO.getPage() - 1) * getFollowListDTO.getSize() : 0;
|
||||
followeeList = userFollowMapper.getFolloweeListByFollower(accountId, limit, offset, order);
|
||||
}
|
||||
|
||||
if (!followeeList.isEmpty()){
|
||||
followeeList.forEach(followee -> {
|
||||
String avatar = StringUtil.isNullOrEmpty(followee.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : followee.getAvatar();
|
||||
followee.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
});
|
||||
return followeeList;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public Long getFollowerCount(Long accountId) {
|
||||
QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("followee_id", accountId).select("follower_id");
|
||||
return userFollowMapper.selectCount(queryWrapper);
|
||||
}
|
||||
|
||||
// 获取某个用户的粉丝列表 + 按名字查询 需返回是否关注该粉丝
|
||||
public List<AccountFollowVO> getFollowerList(GetFollowListDTO getFollowListDTO) {
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
|
||||
// 获取当前用户的所有粉丝
|
||||
QueryWrapper<UserFollow> qw = new QueryWrapper<>();
|
||||
qw.eq("follower_id", accountId).select("followee_id","create_time");
|
||||
List<UserFollow> userFollows = userFollowMapper.selectList(qw);
|
||||
Map<Long, LocalDateTime> followeeMap = userFollows.stream().collect(Collectors.toMap(UserFollow::getFolloweeId, UserFollow::getCreateTime));
|
||||
|
||||
List<AccountFollowVO> followerList;
|
||||
// 1、判断是否有按用户名查询粉丝
|
||||
if (!StringUtil.isNullOrEmpty(getFollowListDTO.getSearchByName())) {
|
||||
followerList = userFollowMapper.getFollowerListByName(getFollowListDTO.getSearchByName(), accountId);
|
||||
}else {
|
||||
// 2、查全部 分页查询
|
||||
String order = StringUtil.isNullOrEmpty(getFollowListDTO.getOrder()) ? "DESC" : getFollowListDTO.getOrder().equals("DESC") ? "DESC" : "ASC";
|
||||
Integer limit= getFollowListDTO.getSize() > 0 ? getFollowListDTO.getSize() : 20;
|
||||
Integer offset = getFollowListDTO.getPage() > 0 ? (getFollowListDTO.getPage() - 1) * getFollowListDTO.getSize() : 0;
|
||||
followerList = userFollowMapper.getFollowerListByFollowee(accountId, limit,offset, order);
|
||||
}
|
||||
|
||||
if (!followerList.isEmpty()){
|
||||
// 判断当前用户是否与粉丝互关
|
||||
followerList.forEach(follower -> {
|
||||
String avatar = StringUtil.isNullOrEmpty(follower.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : follower.getAvatar();
|
||||
follower.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
follower.setIsFollow(Objects.isNull(followeeMap.get(follower.getSenderId())) ? 0 : 1);
|
||||
// follower.setFollowTime(followeeMap.get(follower.getUserId()));
|
||||
});
|
||||
return followerList;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public Integer getIfFollowed(Long followeeId, Long followerId) {
|
||||
// 设置当前用户是否关注了所查看作品的作者
|
||||
QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("followee_id", followeeId).eq("follower_id", followerId);
|
||||
UserFollow userFollow = userFollowMapper.selectOne(queryWrapper);
|
||||
return Objects.isNull(userFollow) ? 0 : 1;
|
||||
}
|
||||
|
||||
public Long getPortfolioCount(Long accountId) {
|
||||
QueryWrapper<Portfolio> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("account_id", accountId);
|
||||
|
||||
return baseMapper.selectCount(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关注列表
|
||||
* @param accountId
|
||||
* @return
|
||||
*/
|
||||
public List<Long> getFolloweeList(Long accountId){
|
||||
QueryWrapper<UserFollow> qw = new QueryWrapper<>();
|
||||
qw.eq("follower_id", accountId).select("followee_id");
|
||||
|
||||
List<UserFollow> userFollows = userFollowMapper.selectList(qw);
|
||||
return userFollows.stream().map(UserFollow::getFolloweeId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,15 @@
|
||||
</where>
|
||||
and b.create_date not like '%:01'
|
||||
and b.create_date not like '%:02'
|
||||
<if test="ids != null and ids.size() > 0">
|
||||
and a.id in
|
||||
<foreach item="id" collection="ids" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="email != null and email != '' ">
|
||||
and a.user_email like CONCAT('%', #{email}, '%')
|
||||
</if>
|
||||
GROUP BY b.account_id
|
||||
ORDER BY b.account_id asc) d
|
||||
left join trial_order c on d.user_email = c.email
|
||||
|
||||
67
src/main/resources/mapper/primary/NotificationMapper.xml
Normal file
67
src/main/resources/mapper/primary/NotificationMapper.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ai.da.mapper.primary.NotificationMapper">
|
||||
|
||||
<select id="getTypeCount" resultType="java.util.Map">
|
||||
SELECT type, count(id) as count
|
||||
FROM `t_notification`
|
||||
WHERE receiver_id = #{receiverId}
|
||||
AND is_read = 0
|
||||
AND is_deleted = 0
|
||||
GROUP BY type
|
||||
</select>
|
||||
|
||||
<select id="getUniqueLikeAndFollow" resultType="com.ai.da.mapper.primary.entity.Notification">
|
||||
SELECT *
|
||||
FROM `t_notification`
|
||||
WHERE type = #{type}
|
||||
AND sender_id = #{senderId}
|
||||
AND receiver_id = #{receiverId}
|
||||
<if test="type == 'like'">
|
||||
AND portfolio_id = #{portfolioId}
|
||||
</if>
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<update id="updateUniqueLikeAndFollow" >
|
||||
UPDATE `t_notification`
|
||||
SET
|
||||
is_read = 0,
|
||||
create_time = #{time},
|
||||
update_time = #{time},
|
||||
is_deleted = 0
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="deleteNotification" >
|
||||
UPDATE `t_notification`
|
||||
SET
|
||||
update_time = #{time},
|
||||
is_deleted = 1
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="setPersonalNotificationAllRead">
|
||||
update `t_notification`
|
||||
SET
|
||||
is_read = 1,
|
||||
update_time = #{time}
|
||||
WHERE type = #{type}
|
||||
AND receiver_id = #{receiverId}
|
||||
AND is_read = 0
|
||||
AND is_deleted = 0
|
||||
</update>
|
||||
|
||||
<select id="getUnreadSysNotification" resultType="Long">
|
||||
SELECT id
|
||||
FROM `t_notification`
|
||||
WHERE type = 'system'
|
||||
AND id NOT IN (
|
||||
SELECT system_notification_id
|
||||
FROM `t_sys_notification_read_status`
|
||||
WHERE account_id = #{accountId}
|
||||
)
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
55
src/main/resources/mapper/primary/UserFollowMapper.xml
Normal file
55
src/main/resources/mapper/primary/UserFollowMapper.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ai.da.mapper.primary.UserFollowMapper">
|
||||
<select id="getFolloweeListByFollower" resultType="com.ai.da.model.vo.AccountFollowVO">
|
||||
SELECT a.id as sender_id, a.user_name AS user_name, a.avatar AS avatar, b.create_time AS create_time
|
||||
FROM t_account a
|
||||
INNER JOIN t_user_follow b ON a.id = b.followee_id
|
||||
WHERE b.follower_id = #{followerAccountId}
|
||||
<if test="order != null and order != ''">
|
||||
ORDER BY b.create_time ${order}
|
||||
</if>
|
||||
LIMIT #{limit} OFFSET #{offset}
|
||||
</select>
|
||||
<select id="getFollowerListByFollowee" resultType="com.ai.da.model.vo.AccountFollowVO">
|
||||
SELECT a.id as sender_id, a.user_name AS user_name, a.avatar AS avatar, b.create_time AS create_time
|
||||
FROM t_account a
|
||||
INNER JOIN t_user_follow b ON a.id = b.follower_id
|
||||
WHERE b.followee_id = #{followeeAccountId}
|
||||
<if test="order != null and order != ''">
|
||||
ORDER BY b.create_time ${order}
|
||||
</if>
|
||||
LIMIT #{limit} OFFSET #{offset}
|
||||
</select>
|
||||
|
||||
<select id="getFolloweeListByName" resultType="com.ai.da.model.vo.AccountFollowVO">
|
||||
SELECT a.id as sender_id, a.user_name, a.avatar, b.create_time as create_time
|
||||
FROM t_account a
|
||||
INNER JOIN t_user_follow b ON a.id = b.followee_id
|
||||
WHERE b.follower_id = #{followerId}
|
||||
AND b.followee_id in (
|
||||
SELECT id
|
||||
FROM t_account
|
||||
WHERE user_name = #{name} OR user_email = #{name}
|
||||
)
|
||||
GROUP BY a.user_email;
|
||||
|
||||
</select>
|
||||
|
||||
<select id="getFollowerListByName" resultType="com.ai.da.model.vo.AccountFollowVO">
|
||||
SELECT a.id as sender_id, a.user_name, a.avatar, b.create_time as create_time
|
||||
FROM t_account a
|
||||
INNER JOIN t_user_follow b ON a.id = b.follower_id
|
||||
WHERE b.followee_id = #{followeeId}
|
||||
AND b.follower_id in (
|
||||
SELECT id
|
||||
FROM t_account
|
||||
WHERE user_name = #{name} OR user_email = #{name}
|
||||
)
|
||||
GROUP BY a.user_email;
|
||||
</select>
|
||||
|
||||
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -139,6 +139,11 @@ slogan.style.cannot.be.empty=Slogan style text cannot be empty.
|
||||
slogan.image.cannot.be.empty=Slogan image cannot be empty.
|
||||
questionnaire.filled.out=You have filled out the current questionnaire.
|
||||
user.has.no.account=The current user has no account!
|
||||
you.cannot.follow.yourself=You cannot follow yourself
|
||||
you.have.already.followed.this.user=You have already followed this user
|
||||
subscription.success=Subscription Success
|
||||
unsubscribe.success=Unsubscribe Success
|
||||
you.have.not.followed.the.current.user=You have not followed the current user
|
||||
|
||||
# 可能会报异常
|
||||
# Informative:
|
||||
|
||||
@@ -134,6 +134,11 @@ slogan.style.cannot.be.empty=标语风格文本不能为空。
|
||||
slogan.image.cannot.be.empty=标语图片不能为空。
|
||||
questionnaire.filled.out=您已填写过当前问卷。
|
||||
user.has.no.account=当前用户没有账号。
|
||||
you.cannot.follow.yourself=您不能关注您自己
|
||||
you.have.already.followed.this.user=您已经关注当前用户
|
||||
subscription.success=关注成功
|
||||
unsubscribe.success=取消关注成功
|
||||
you.have.not.followed.the.current.user=您还未关注当前用户
|
||||
|
||||
# 可能会报异常
|
||||
# Informative:
|
||||
|
||||
Reference in New Issue
Block a user