package com.syzb.common.service; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.collect.Table; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.map.IMap; import com.syzb.common.constant.CommentBlackScope; import com.syzb.common.constant.CommentBlackStatus; import com.syzb.common.constant.CommentBlackType; import com.syzb.common.entity.CommentBlack; import com.syzb.common.handler.BizException; import com.syzb.common.mapper.CommentBlackMapper; import com.syzb.common.query.AddCommentBlackQuery; import com.syzb.common.query.BaseProductQuery; import com.syzb.common.query.CommentBlackQuery; import com.syzb.common.query.RemoveCommentBlackQuery; import com.syzb.common.result.Pager; import com.syzb.common.result.ResponseStatus; import com.syzb.common.util.logger.LoggerUtil; import com.syzb.common.vo.BackendUserVO; import com.syzb.common.vo.CommentBlackVO; import com.syzb.common.vo.MergeProductInfoVO; import com.syzb.rbac.entity.Dept; import com.syzb.rbac.entity.UserDept; import com.syzb.rbac.service.DeptService; import com.syzb.rbac.service.UserService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; import static com.syzb.common.config.cache.CacheKey.COMMENT_BLACK; import static com.syzb.common.config.cache.CacheKey.CommentBlackKey.ALL_BLACK_COMMENT; import static com.syzb.common.config.cache.CacheKey.CommentBlackKey.ALL_BLACK_USER; @Service public class CommentBlackService { @Resource private CommentBlackMapper commentBlackMapper; @Resource private UserService userService; @Resource private MergeProductService mergeProductService; @Resource private HazelcastInstance hazelcastInstance; @Resource private CacheService cacheService; @Resource private DeptService deptService; private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Transactional(rollbackFor = Exception.class) public Integer addCommentBlack(BackendUserVO backendUserVO, AddCommentBlackQuery query) { String userPhone = query.getUserPhone(); LocalDateTime now = LocalDateTime.now(); //禁言开始时间-1s now = now.minusSeconds(1L); QueryWrapper wrapper = Wrappers.query(); wrapper.eq("phone", userPhone) .in("status", Arrays.asList(CommentBlackStatus.EFFECT.value, CommentBlackStatus.EXPIRED.value)) .lt("start_time", now) .ge("end_time", now); long validSize = commentBlackMapper.selectCount(wrapper); if (validSize > 0) { throw new BizException(ResponseStatus.REPETITIVE_ERROR); } CommentBlack commentBlack = query.toPO(); commentBlack.setStartTime(now); commentBlack.setStatus(CommentBlackStatus.EFFECT.value); commentBlack.setOperatorId(backendUserVO.getUserId()); commentBlack.setUpdateTime(now); commentBlack.setAdvisorId(backendUserVO.getAdvisorId()); if (CommentBlackType.DAY.value.equals(commentBlack.getType())) { commentBlack.setEndTime(now.plusDays(1)); } else if (CommentBlackType.MONTH.value.equals(commentBlack.getType())) { commentBlack.setEndTime(now.plusMonths(1)); } else { commentBlack.setEndTime(now.plusYears(100)); } int count = commentBlackMapper.insert(commentBlack); if (count < 1) { throw new BizException(ResponseStatus.DB_SAVE_ERROR); } this.clearCache(ALL_BLACK_USER, ALL_BLACK_COMMENT); return commentBlack.getId(); } @Transactional(rollbackFor = Exception.class) public void removeCommentBlack(BackendUserVO backendUserVO, RemoveCommentBlackQuery query) { LocalDateTime now = LocalDateTime.now(); QueryWrapper wrapper = Wrappers.query(); wrapper.eq("phone", query.getUserPhone()) .eq("product_id", query.getProductId()) .eq("product_type", query.getProductType()) .in("status", Arrays.asList(CommentBlackStatus.EFFECT.value, CommentBlackStatus.EXPIRED.value)) .lt("start_time", now) .ge("end_time", now); List commentBlackList = commentBlackMapper.selectList(wrapper); if (CollectionUtils.isEmpty(commentBlackList)) { throw new BizException(ResponseStatus.REMOVE_BLACK_USER_ERROR); } for (CommentBlack commentBlack : commentBlackList) { CommentBlack updateObj = new CommentBlack(); updateObj.setId(commentBlack.getId()); updateObj.setStatus(CommentBlackStatus.REMOVED.value); updateObj.setUpdateTime(now); updateObj.setEndTime(now); int count = commentBlackMapper.updateById(updateObj); if (count < 1) { throw new BizException(ResponseStatus.DB_SAVE_ERROR); } } this.clearCache(ALL_BLACK_USER, ALL_BLACK_COMMENT); } public Pager queryCommentBlackList(BackendUserVO backendUserVO, CommentBlackQuery query) { LocalDateTime startTime = null; LocalDateTime endTime = null; LocalDateTime startOpTime = null; LocalDateTime endOpTime = null; if (StrUtil.isNotEmpty(query.getStartTime())) { startTime = LocalDateTime.parse(query.getStartTime(), formatter); } if (StrUtil.isNotEmpty(query.getEndTime())) { endTime = LocalDateTime.parse(query.getEndTime(), formatter); } if (StrUtil.isNotEmpty(query.getStartOpTime())) { startOpTime = LocalDateTime.parse(query.getStartOpTime(), formatter); } if (StrUtil.isNotEmpty(query.getEndOpTime())) { endOpTime = LocalDateTime.parse(query.getEndOpTime(), formatter); } QueryWrapper wrapper = Wrappers.query(); wrapper.like(StrUtil.isNotEmpty(query.getUserName()), "user_name", query.getUserName()) .eq(StrUtil.isNotEmpty(query.getPhone()), "phone", query.getPhone()) .eq(query.getStatus() != null, "status", query.getStatus()) .eq(query.getType() != null, "type", query.getType()) .eq(query.getProductType() != null, "product_type", query.getProductType()) .eq(query.getProductType() != null && query.getProductId() != null, "product_id", query.getProductId()) .like(StrUtil.isNotBlank(query.getContent()), "content", query.getContent()) .like(StrUtil.isNotEmpty(query.getReason()), "reason", query.getReason()) .eq(query.getOperatorId() != null, "operator_id", query.getOperatorId()) .ge(startTime != null, "start_time", startTime) .lt(endTime != null, "start_time", endTime) .ge(startOpTime != null, "end_time", startOpTime) .lt(endOpTime != null, "end_time", endOpTime); wrapper.orderByDesc("start_time"); Page page = commentBlackMapper.selectPage(query.toPage(), wrapper); List list = page.getRecords(); if (CollectionUtils.isEmpty(list)) { return Pager.emptyPager(); } List baseProductQueryList = list.stream().map(commentBlack -> { if (commentBlack.getProductId() != null && commentBlack.getProductType() != null) { return new BaseProductQuery(commentBlack.getProductId(), commentBlack.getProductType()); } return null; }).filter(Objects::nonNull).collect(Collectors.toList()); Table productTable = mergeProductService.queryMergeProductInfo(baseProductQueryList); Map userMap = userService.getUserMap(); Map deptMap = deptService.getDeptMap(); List voList = list.stream().map(CommentBlackVO::new).collect(Collectors.toList()); for (CommentBlackVO commentBlackVO : voList) { // 查询产品信息 if (commentBlackVO.getProductId() != null && commentBlackVO.getProductType() != null) { MergeProductInfoVO mergeProductInfoVO = productTable.get(commentBlackVO.getProductType(), commentBlackVO.getProductId()); if (mergeProductInfoVO != null) { commentBlackVO.setProductName(mergeProductInfoVO.getProductName()); } } LocalDateTime now = LocalDateTime.now(); if (CommentBlackStatus.EFFECT.value.equals(commentBlackVO.getStatus()) && now.isAfter(commentBlackVO.getEndTime())) { commentBlackVO.setStatus(CommentBlackStatus.EXPIRED.value); } UserDept user = userMap.get(commentBlackVO.getOperatorId()); if (user != null) { commentBlackVO.setOperatorName(user.getName()); } if (StrUtil.isNotEmpty(commentBlackVO.getUserOrgNo())) { Dept dept = deptMap.get(commentBlackVO.getUserOrgNo()); if (dept != null) { commentBlackVO.setUserOrgName(dept.getName()); } } } return new Pager<>(voList, page.getTotal()); } /** * 校验是否禁言 */ public boolean checkIsBlack(String phone, Integer productId, Integer productType) { // 判断是否禁言用户 Set blackUsers = getAllBlackUser(); if (!blackUsers.contains(phone)) { return false; } List blackComments = getAllBlackComment(); if (CollectionUtils.isEmpty(blackComments)) { return false; } for (CommentBlack commentBlack : blackComments) { if (commentBlack.getPhone().equals(phone)) { if (CommentBlackScope.PRODUCT.value.equals(commentBlack.getScope())) { if (commentBlack.getProductId().equals(productId) && commentBlack.getProductType().equals(productType)) { return true; } } else if (CommentBlackScope.PRODUCT_TYPE.value.equals(commentBlack.getScope())) { if (commentBlack.getProductType().equals(productType)) { return true; } } else if (CommentBlackScope.GLOBAL.value.equals(commentBlack.getScope())) { return true; } } } return false; } private Set getAllBlackUser() { return cacheService.get(COMMENT_BLACK, ALL_BLACK_USER, () -> getAllBlackComment().stream().map(CommentBlack::getPhone).collect(Collectors.toSet())); } private List getAllBlackComment() { LocalDateTime now = LocalDateTime.now(); return cacheService.get(COMMENT_BLACK, ALL_BLACK_COMMENT, () -> { QueryWrapper wrapper = Wrappers.query() .in("status", Arrays.asList(CommentBlackStatus.EFFECT.value, CommentBlackStatus.EXPIRED.value)) .lt("start_time", now) .gt("end_time", now); List commentBlackList = commentBlackMapper.selectList(wrapper); LoggerUtil.info("db当前黑名单用户:" + JSONObject.toJSONString(commentBlackList)); return commentBlackList; }); } public Set getBlackUserIds(Integer productId, Integer productType) { Set blackUsers = new HashSet<>(); List blackComments = getAllBlackComment(); for (CommentBlack commentBlack : blackComments) { if (CommentBlackScope.PRODUCT.value.equals(commentBlack.getScope())) { if (commentBlack.getProductId().equals(productId) && commentBlack.getProductType().equals(productType)) { blackUsers.add(commentBlack.getPhone()); } } else if (CommentBlackScope.PRODUCT_TYPE.value.equals(commentBlack.getScope())) { if (commentBlack.getProductType().equals(productType)) { blackUsers.add(commentBlack.getPhone()); } } else if (CommentBlackScope.GLOBAL.value.equals(commentBlack.getScope())) { blackUsers.add(commentBlack.getPhone()); } } return blackUsers; } private void clearCache(String... cacheKeys) { IMap cacheMap = hazelcastInstance.getMap(COMMENT_BLACK); for (String key : cacheKeys) { cacheMap.remove(key); } } }