|  | @@ -6,6 +6,7 @@ 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.google.common.collect.Lists;
 | 
	
		
			
				|  |  | +import com.google.common.collect.Maps;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.auth.api.entity.SysUser;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.dao.ActivityPlanDao;
 | 
	
	
		
			
				|  | @@ -23,6 +24,8 @@ import com.yonge.cooleshow.biz.dal.entity.ActivityPlanReward;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.entity.ActivityRegistration;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.entity.ActivityReward;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.enums.EQueryOp;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.enums.MK;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.enums.MessageTypeEnum;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationService;
 | 
	
	
		
			
				|  | @@ -39,14 +42,24 @@ import com.yonge.cooleshow.biz.dal.vo.MusicActivityVo;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.vo.activity.ActivityTeacherWrapper;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.common.entity.HttpResponseResult;
 | 
	
		
			
				|  |  | -import com.yonge.cooleshow.common.enums.*;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.enums.ActivityResourceEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.enums.ActivityShareEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.enums.ActivityTypeEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.enums.CacheNameEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.enums.EStatus;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.enums.RegistrationMethodEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 | 
	
		
			
				|  |  |  import com.yonge.toolset.base.exception.BizException;
 | 
	
		
			
				|  |  |  import com.yonge.toolset.base.util.StringUtil;
 | 
	
		
			
				|  |  | +import com.yonge.toolset.base.util.ThreadPool;
 | 
	
		
			
				|  |  |  import com.yonge.toolset.payment.util.DistributedLock;
 | 
	
		
			
				|  |  |  import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
 | 
	
		
			
				|  |  |  import org.apache.commons.collections.CollectionUtils;
 | 
	
		
			
				|  |  |  import org.apache.commons.lang3.StringUtils;
 | 
	
		
			
				|  |  | +import org.joda.time.DateTime;
 | 
	
		
			
				|  |  | +import org.redisson.api.RLock;
 | 
	
		
			
				|  |  |  import org.redisson.api.RedissonClient;
 | 
	
		
			
				|  |  |  import org.slf4j.Logger;
 | 
	
		
			
				|  |  |  import org.slf4j.LoggerFactory;
 | 
	
	
		
			
				|  | @@ -169,9 +182,50 @@ public class ActivityPlanServiceImpl extends ServiceImpl<ActivityPlanDao, Activi
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          List<ActivityPlanVo> wrappers = baseMapper.selectPage(page, query);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        if (CollectionUtils.isEmpty(wrappers)) {
 | 
	
		
			
				|  |  | +            return page.setRecords(wrappers);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        List<Long> activityIds = wrappers.stream()
 | 
	
		
			
				|  |  | +                .map(ActivityPlan::getId).distinct().collect(Collectors.toList());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 参与人数
 | 
	
		
			
				|  |  | +        Map<Long, Integer> participantNumMap = Maps.newConcurrentMap();
 | 
	
		
			
				|  |  | +        // 获奖人数
 | 
	
		
			
				|  |  | +        Map<Long, Integer> winnerNumMap = Maps.newConcurrentMap();
 | 
	
		
			
				|  |  | +        Lists.partition(activityIds, 30).parallelStream().forEach(item ->
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Lists.newArrayList(EQueryOp.values()).parallelStream().forEach(dataType -> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                switch (dataType) {
 | 
	
		
			
				|  |  | +                    case FUNCTION_1:
 | 
	
		
			
				|  |  | +                        // 参与人数
 | 
	
		
			
				|  |  | +                        Map<Long, Integer> participantMap = getBaseMapper().selectActivityParticipateStatInfo(activityIds).stream()
 | 
	
		
			
				|  |  | +                                .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        participantNumMap.putAll(participantMap);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case FUNCTION_2:
 | 
	
		
			
				|  |  | +                        // 获奖人数
 | 
	
		
			
				|  |  | +                        Map<Long, Integer> winnerMap = getBaseMapper().selectActivityWinnerStatInfo(activityIds).stream()
 | 
	
		
			
				|  |  | +                                .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        winnerNumMap.putAll(winnerMap);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    default:
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            })
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          // 分享活动-参与人数获奖人数相等
 | 
	
		
			
				|  |  |          for (ActivityPlanVo item : wrappers) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +            // 参与人数、获奖人数
 | 
	
		
			
				|  |  | +            item.registrationNum(participantNumMap.getOrDefault(item.getId(), 0))
 | 
	
		
			
				|  |  | +                    .rewardNum(winnerNumMap.getOrDefault(item.getId(), 0));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              // 重置分享活动获奖与参与人数
 | 
	
		
			
				|  |  |              if (ActivityTypeEnum.SHARE == item.getActivityType()) {
 | 
	
		
			
				|  |  |                  item.setRegistrationNum(item.getRewardNum());
 | 
	
	
		
			
				|  | @@ -576,43 +630,75 @@ public class ActivityPlanServiceImpl extends ServiceImpl<ActivityPlanDao, Activi
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  |      public void activityState() {
 | 
	
		
			
				|  |  | -        List<ActivityPlan> list = baseMapper.activityState();
 | 
	
		
			
				|  |  | -        for (ActivityPlan plan : list) {
 | 
	
		
			
				|  |  | -            DistributedLock.of(redissonClient)
 | 
	
		
			
				|  |  | -                    .runIfLockToFunction(CacheNameEnum.LOCK_ACTIVITY_STOCK.getRedisKey(plan.getId())
 | 
	
		
			
				|  |  | -                            , (id) -> {
 | 
	
		
			
				|  |  | -                                ActivityPlan activityPlan = getById(id);
 | 
	
		
			
				|  |  | -                                if (activityPlan.getActivityState() == 0) {
 | 
	
		
			
				|  |  | -                                    activityPlan.setActivityState(1);
 | 
	
		
			
				|  |  | -                                    baseMapper.updateById(activityPlan);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                    //开始活动
 | 
	
		
			
				|  |  | -                                    Consumer<Long> afterFunction = startActivity.get(activityPlan.getActivityType());
 | 
	
		
			
				|  |  | -                                    if (!Objects.isNull(afterFunction)) {
 | 
	
		
			
				|  |  | -                                        afterFunction.accept(activityPlan.getId());
 | 
	
		
			
				|  |  | -                                    }
 | 
	
		
			
				|  |  | -                                } else {
 | 
	
		
			
				|  |  | -                                    activityPlan.setActivityState(0);
 | 
	
		
			
				|  |  | -                                    activityPlan.setRewardFlag(1);
 | 
	
		
			
				|  |  | -                                    baseMapper.updateById(activityPlan);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                                    //完成活动
 | 
	
		
			
				|  |  | -                                    Consumer<Long> afterFunction = successActivity.get(activityPlan.getActivityType());
 | 
	
		
			
				|  |  | -                                    if (!Objects.isNull(afterFunction)) {
 | 
	
		
			
				|  |  | -                                        afterFunction.accept(activityPlan.getId());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 方法调整为异常执行,预防HTTP接口调用返回超时响应
 | 
	
		
			
				|  |  | +        ThreadPool.getExecutor().submit(() -> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            List<ActivityPlan> list = baseMapper.activityState();
 | 
	
		
			
				|  |  | +            for (ActivityPlan plan : list) {
 | 
	
		
			
				|  |  | +                DistributedLock.of(redissonClient)
 | 
	
		
			
				|  |  | +                        .runIfLockToFunction(CacheNameEnum.LOCK_ACTIVITY_STOCK.getRedisKey(plan.getId())
 | 
	
		
			
				|  |  | +                                , (id) -> {
 | 
	
		
			
				|  |  | +                                    ActivityPlan activityPlan = getById(id);
 | 
	
		
			
				|  |  | +                                    if (activityPlan.getActivityState() == 0) {
 | 
	
		
			
				|  |  | +                                        activityPlan.setActivityState(1);
 | 
	
		
			
				|  |  | +                                        baseMapper.updateById(activityPlan);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                                        //开始活动
 | 
	
		
			
				|  |  | +                                        Consumer<Long> afterFunction = startActivity.get(activityPlan.getActivityType());
 | 
	
		
			
				|  |  | +                                        if (!Objects.isNull(afterFunction)) {
 | 
	
		
			
				|  |  | +                                            afterFunction.accept(activityPlan.getId());
 | 
	
		
			
				|  |  | +                                        }
 | 
	
		
			
				|  |  | +                                    } else {
 | 
	
		
			
				|  |  | +                                        activityPlan.setActivityState(0);
 | 
	
		
			
				|  |  | +                                        activityPlan.setRewardFlag(1);
 | 
	
		
			
				|  |  | +                                        baseMapper.updateById(activityPlan);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                                        //完成活动
 | 
	
		
			
				|  |  | +                                        Consumer<Long> afterFunction = successActivity.get(activityPlan.getActivityType());
 | 
	
		
			
				|  |  | +                                        if (!Objects.isNull(afterFunction)) {
 | 
	
		
			
				|  |  | +                                            afterFunction.accept(activityPlan.getId());
 | 
	
		
			
				|  |  | +                                        }
 | 
	
		
			
				|  |  |                                      }
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                                return true;
 | 
	
		
			
				|  |  | -                            }, plan.getId(), 10l);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +                                    return true;
 | 
	
		
			
				|  |  | +                                }, plan.getId(), 10l);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @Override
 | 
	
		
			
				|  |  |      @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  |      public void activityIng() {
 | 
	
		
			
				|  |  | -        for (ActivityTypeEnum activityTypeEnum : activityIng.keySet()) {
 | 
	
		
			
				|  |  | -            activityIng.get(activityTypeEnum).accept(null);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 当前处理任务调整为异步执行
 | 
	
		
			
				|  |  | +        ThreadPool.getExecutor().submit(() -> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            RLock lock = redissonClient.getLock(CacheNameEnum.LOCK_STANDARD_GIFT_CRON.getCode());
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                if (lock.isLocked()) {
 | 
	
		
			
				|  |  | +                    log.warn("activityIng {}, lockName={}", DateTime.now().toString(MK.TIME_PATTERN), lock.getName());
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // 增加达标活动计算同步标识,前一个请求未执行完时忽略后续执行请求
 | 
	
		
			
				|  |  | +                lock.lock();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                for (ActivityTypeEnum activityTypeEnum : activityIng.keySet()) {
 | 
	
		
			
				|  |  | +                    activityIng.get(activityTypeEnum).accept(null);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            } catch (Exception e) {
 | 
	
		
			
				|  |  | +                log.error("activityIng time={}", DateTime.now().toString(MK.TIME_PATTERN), e);
 | 
	
		
			
				|  |  | +            } finally {
 | 
	
		
			
				|  |  | +                // 释放锁
 | 
	
		
			
				|  |  | +                if (lock.isLocked() && lock.isHeldByCurrentThread()) {
 | 
	
		
			
				|  |  | +                    lock.unlock(); // 删除同步标识
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 |