用户留言功能实现

master
chenyuepan 1 month ago
parent 7ad15df234
commit 988d790ae4

@ -173,13 +173,11 @@
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.fasterxml.jackson.core</groupId>-->
<!-- <artifactId>jackson-databind</artifactId>-->
<!-- <version>2.13.0</version>-->
<!-- </dependency>-->
<!-- websocket dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>

@ -1,16 +1,38 @@
package com.example.venue_reservation_service.config;
import cn.hutool.json.JSON;
import com.example.venue_reservation_service.converter.ListConverter;
import com.example.venue_reservation_service.mapper.SensitiveWordMapper;
import com.example.venue_reservation_service.service.SensitiveWordService;
import com.example.venue_reservation_service.utils.RedisUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Slf4j
public class CacheInitializer {
@Resource
private SensitiveWordMapper sensitiveWordMapper;
@Resource
private RedisUtil redisUtil;
private final static String REDIS_KEY = "sensitive-word";
@PostConstruct // 在Bean初始化后执行[5](@ref)
public void init() {
log.info("敏感词库已加载到Redis");
List<String> list = sensitiveWordMapper.selectWordsOrderedByPriority();
try {
redisUtil.set(REDIS_KEY, ListConverter.listToString(list));
log.info("敏感词库已加载到Redis");
} catch (Exception e) {
e.printStackTrace();
log.error("服务异常,"+e.getMessage());
}
}
}

@ -11,9 +11,9 @@ public class InterceptorConfig implements WebMvcConfigurer {
registry.addInterceptor(new JWTInterceptor())
.addPathPatterns("/user/**")
.addPathPatterns("/reservation/**")
.addPathPatterns("/information/**")
// .addPathPatterns("/information/**")
.addPathPatterns("/hot/**")
.addPathPatterns("/type/**")
// .addPathPatterns("/type/**")
.addPathPatterns("/slot/**")
.addPathPatterns("/admin/**")
.addPathPatterns("/school/**")

@ -0,0 +1,25 @@
package com.example.venue_reservation_service.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOriginPatterns("*")
.withSockJS();
}
}

@ -1,6 +1,8 @@
package com.example.venue_reservation_service.controller;
import com.example.venue_reservation_service.domain.Comment;
import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.dto.SearchDTO;
import com.example.venue_reservation_service.service.CommentService;
import com.example.venue_reservation_service.vo.Result;
import io.swagger.annotations.Api;
@ -20,6 +22,31 @@ public class CommentController {
@ApiOperation("发布评论")
@PostMapping("/create")
public Result create(@RequestBody Comment comment){
return null;
return commentService.createComment(comment);
}
@ApiOperation("超级管理员查看评论信息")
@PostMapping("/admin")
public Result admin(@RequestBody PageDTO dto){
return commentService.queryComment(dto);
}
@ApiOperation("超级管理员撤回评论")
@GetMapping("/withdraw/{id}")
public Result withdraw(@PathVariable("id") Integer id){
return commentService.withdrawComment(id);
}
@ApiOperation("用户查看评论信息")
@PostMapping("/user")
public Result user(@RequestBody SearchDTO dto){
return commentService.queryByUser(dto);
}
@ApiOperation("点赞/取消点赞")
@GetMapping("like")
public Result like(@RequestParam("userId") Integer userId,
@RequestParam("commentId") Integer commentId){
return commentService.like(userId, commentId);
}
}

@ -0,0 +1,35 @@
package com.example.venue_reservation_service.controller;
import com.example.venue_reservation_service.dto.MessageDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/message")
@Api("预约通知管理")
@CrossOrigin
public class MessageController {
private final SimpMessagingTemplate messagingTemplate;
public MessageController(SimpMessagingTemplate messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
// 发送消息到指定用户
@GetMapping("/send")
public String sendMessageToUser(@RequestParam("userId") Integer userId) {
MessageDTO message = new MessageDTO();
message.setUserId(userId);
message.setContent("测试");
String destination = "/queue/messages/" + userId;
messagingTemplate.convertAndSend(destination, message);
return "消息已发送给用户ID: " + userId;
}
}

@ -42,7 +42,6 @@ public class SensitiveWordController {
log.info("添加敏感词{}", dto);
return sensitiveWordService.addSensitiveWord(dto);
}
/**
*
*/

@ -0,0 +1,19 @@
package com.example.venue_reservation_service.converter;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class ListConverter {
private static final ObjectMapper objectMapper = new ObjectMapper();
// List<String> 转 String
public static String listToString(List<String> list) throws Exception {
return objectMapper.writeValueAsString(list);
}
// String 转回 List<String>
public static List<String> stringToList(String str) throws Exception {
return objectMapper.readValue(str, objectMapper.getTypeFactory()
.constructCollectionType(List.class, String.class));
}
}

@ -36,9 +36,9 @@ public class Comment implements Serializable {
private String content;
/**
* 012
* 12
*/
private String status;
private Integer status;
/**
*

@ -45,6 +45,7 @@ public class UserLike implements Serializable {
/**
*
*/
private Integer isDelete;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -0,0 +1,15 @@
package com.example.venue_reservation_service.dto;
import lombok.Data;
// 消息数据模型
@Data
public class MessageDTO {
private Integer userId;
private String content;
private String sender = "系统通知";
}

@ -0,0 +1,11 @@
package com.example.venue_reservation_service.dto;
import lombok.Data;
@Data
public class SearchDTO extends PageDTO{
private Integer userId;
private Integer onlyOne;
}

@ -4,6 +4,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.venue_reservation_service.domain.SensitiveWord;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SensitiveWordMapper extends BaseMapper<SensitiveWord> {
List<String> selectWordsOrderedByPriority();
}

@ -2,6 +2,8 @@ package com.example.venue_reservation_service.service;
import com.example.venue_reservation_service.domain.Comment;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.dto.SearchDTO;
import com.example.venue_reservation_service.vo.Result;
/**
@ -11,6 +13,13 @@ import com.example.venue_reservation_service.vo.Result;
*/
public interface CommentService extends IService<Comment> {
Result queryComment(PageDTO dto);
Result queryByUser(SearchDTO dto);
Result createComment(Comment comment);
Result withdrawComment(Integer id);
Result like(Integer userId, Integer commentId);
}

@ -1,12 +1,13 @@
package com.example.venue_reservation_service.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.venue_reservation_service.domain.SensitiveWord;
import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.dto.SensitiveWordDTO;
import com.example.venue_reservation_service.dto.WordDTO;
import com.example.venue_reservation_service.vo.Result;
public interface SensitiveWordService {
public interface SensitiveWordService extends IService<SensitiveWord> {
// 获取敏感词数据
Result getSensitiveWords(WordDTO dto);

@ -1,13 +1,34 @@
package com.example.venue_reservation_service.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.converter.ListConverter;
import com.example.venue_reservation_service.domain.Comment;
import com.example.venue_reservation_service.domain.User;
import com.example.venue_reservation_service.domain.UserLike;
import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.dto.SearchDTO;
import com.example.venue_reservation_service.filter.SensitiveFilter;
import com.example.venue_reservation_service.mapper.CommentMapper;
import com.example.venue_reservation_service.mapper.UserMapper;
import com.example.venue_reservation_service.service.CommentService;
import com.example.venue_reservation_service.service.UserLikeService;
import com.example.venue_reservation_service.utils.RedisUtil;
import com.example.venue_reservation_service.vo.AvatarVO;
import com.example.venue_reservation_service.vo.QueryVO;
import com.example.venue_reservation_service.vo.Result;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* @author 31586
@ -18,14 +39,115 @@ import java.time.LocalDateTime;
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
implements CommentService{
@Resource
private RedisUtil redisUtil;
private final static String REDIS_KEY = "sensitive-word";
@Resource
private UserLikeService userLikeService;
@Resource
private UserMapper userMapper;
@Value("${access.url}")
private String accessUrl;
@Override
public Result queryComment(PageDTO dto) {
Page<Comment> page = new Page(dto.getCurrent(), dto.getSize());
page = page(page, null);
QueryVO<Comment> vo = new QueryVO<>();
vo.setTotal(page.getTotal());
vo.setList(page.getRecords());
return Result.ok(vo).message("数据加载完成");
}
@Override
public Result queryByUser(SearchDTO dto) {
Page<Comment> page = new Page<>(dto.getCurrent(), dto.getSize());
LambdaQueryWrapper<Comment> wrapper = Wrappers.lambdaQuery();
if (dto.getOnlyOne() == 1) {
wrapper.eq(Comment::getUserId, dto.getUserId());
}
wrapper.eq(Comment::getStatus, 2);
page = page(page, wrapper);
QueryVO<AvatarVO> vo = new QueryVO<>();
vo.setTotal(page.getTotal());
List<AvatarVO> list = new ArrayList<>();
page.getRecords().forEach(item -> {
User user = userMapper.selectById(item.getUserId());
if(user.getIsUpload() == 1){
user.setAvatar(accessUrl + user.getAvatar());
}
AvatarVO ele = BeanUtil.copyProperties(user, AvatarVO.class);
UserLike like = userLikeService.getOne(Wrappers.<UserLike>lambdaQuery()
.eq(UserLike::getUserId, dto.getUserId())
.eq(UserLike::getCommentId, item.getId()));
if (Optional.ofNullable(like).isEmpty() || like.getIsDelete() == 1) {
ele.setIsLike(0);
}else{
ele.setIsLike(1);
}
BeanUtil.copyProperties(item, ele);
list.add(ele);
});
vo.setList(list);
return Result.ok(vo).message("数据加载完成");
}
@Override
public Result createComment(Comment comment) {
// TODO 对敏感词进行脱敏处理 --
List<String> list;
try {
list = ListConverter.stringToList((String) redisUtil.get(REDIS_KEY));
} catch (Exception e) {
e.printStackTrace();
return Result.fail().message("服务异常");
}
SensitiveFilter filter = new SensitiveFilter();
filter.buildTrie(list);
String content = filter.filter(comment.getContent());
comment.setContent(content);
comment.setStatus(2); // 过滤完成后默认为发布状态
comment.setCreateTime(LocalDateTime.now());
comment.setUpdateTime(LocalDateTime.now());
// TODO 保存评论记录
return null;
save(comment);
return Result.ok().message("评论发布成功");
}
@Override
public Result withdrawComment(Integer id) {
Comment comment = getById(id);
if (Optional.ofNullable(comment).isEmpty()) {
return Result.fail().message("未查询到评论信息");
}
comment.setStatus(comment.getStatus() == 1 ? 2 : 1);
updateById(comment);
return Result.ok().message(comment.getStatus() == 1 ? "撤回成功" : "恢复成功");
}
@Override
public Result like(Integer userId, Integer commentId) {
UserLike like = userLikeService.getOne(Wrappers.<UserLike>lambdaQuery()
.eq(UserLike::getUserId, userId)
.eq(UserLike::getCommentId, commentId));
if (Optional.ofNullable(like).isEmpty()) {
// 用户之前未点赞过该条评论
like = new UserLike();
like.setCommentId(commentId);
like.setUserId(userId);
like.setCreateTime(LocalDateTime.now());
like.setIsDelete(0);
userLikeService.save(like);
}else{
like.setIsDelete(like.getIsDelete() == 1 ? 0 : 1);
userLikeService.updateById(like);
}
return Result.ok().message(like.getIsDelete() == 1 ? "取消点赞" : "点赞成功");
}
}

@ -4,11 +4,13 @@ import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.converter.ListConverter;
import com.example.venue_reservation_service.domain.SensitiveWord;
import com.example.venue_reservation_service.dto.SensitiveWordDTO;
import com.example.venue_reservation_service.dto.WordDTO;
import com.example.venue_reservation_service.mapper.SensitiveWordMapper;
import com.example.venue_reservation_service.service.SensitiveWordService;
import com.example.venue_reservation_service.utils.RedisUtil;
import com.example.venue_reservation_service.vo.QueryVO;
import com.example.venue_reservation_service.vo.Result;
import jakarta.annotation.Resource;
@ -26,6 +28,12 @@ public class SensitiveWordServiceImpl extends ServiceImpl<SensitiveWordMapper, S
@Resource
private SensitiveWordMapper sensitiveWordMapper;
@Resource
private RedisUtil redisUtil;
private final static String REDIS_KEY = "sensitive-word";
/**
*
*/
@ -108,6 +116,11 @@ public class SensitiveWordServiceImpl extends ServiceImpl<SensitiveWordMapper, S
Integer status = word.getStatus();
word.setStatus(status == 1 ? 0 : 1);
updateById(word);
try {
redisUtil.set(REDIS_KEY, ListConverter.listToString(sensitiveWordMapper.selectWordsOrderedByPriority()));
} catch (Exception e) {
log.error("服务异常,"+e.getMessage());
}
return Result.ok().message("设置成功");
}

@ -8,7 +8,8 @@ import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;@Component
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
@Autowired

@ -0,0 +1,47 @@
package com.example.venue_reservation_service.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
public class AvatarVO {
/**
*
*/
private String username;
/**
*
*/
private String avatar;
/**
*
*/
private Integer isUpload;
/**
*
*/
private String content;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
private Integer isLike;
}

@ -9,5 +9,6 @@ import lombok.Data;
public class LoginVo {
private User user;
private String token;
}

@ -17,4 +17,13 @@
id,word,level,status,
create_time,update_time
</sql>
<select id="selectWordsOrderedByPriority" resultType="java.lang.String">
SELECT word FROM venue_word
where status = 1
ORDER BY
level DESC,
update_time DESC,
create_time DESC
</select>
</mapper>

@ -27,6 +27,7 @@ class VenueReservationServiceApplicationTests {
@Test
void contextLoads() throws Exception {
System.out.println(MD5Util.generateRandomString(10));
}
public static void main(String[] args) {

Loading…
Cancel
Save