Преглед на файлове

Merge remote-tracking branch '20220319/master'

xst преди 4 години
родител
ревизия
81708dcbb3
променени са 44 файла, в които са добавени 1132 реда и са изтрити 250 реда
  1. 5 5
      pom.xml
  2. 5 1
      src/main/java/com/td/boss/config/enums/ResultEnum.java
  3. 2 2
      src/main/java/com/td/boss/game/comcntorder/service/ComCntOrderService.java
  4. 10 0
      src/main/java/com/td/boss/game/comcnttosnb/service/ComCntToSnbService.java
  5. 28 3
      src/main/java/com/td/boss/game/comcnttosnb/service/ComCntToSnbServiceImpl.java
  6. 8 1
      src/main/java/com/td/boss/game/comcnttosnb/vo/ComCntToSnbVo.java
  7. 103 19
      src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java
  8. 77 66
      src/main/java/com/td/boss/game/complayerland/controller/ComPlayerLandController.java
  9. 30 17
      src/main/java/com/td/boss/game/complayerland/service/ComPlayerDisasterLogServiceImpl.java
  10. 1 1
      src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandServiceImpl.java
  11. 3 0
      src/main/java/com/td/boss/game/complayerprofit/pojo/ComPlayerProfit.java
  12. 3 3
      src/main/java/com/td/boss/game/complayerprofit/repository/ComPlayerProfitRepository.java
  13. 4 4
      src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitService.java
  14. 49 20
      src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java
  15. 4 0
      src/main/java/com/td/boss/game/complayerprofit/vo/ComPlayerProfitVo.java
  16. 114 28
      src/main/java/com/td/boss/game/comsnbapply/controller/ComSnbApplyController.java
  17. 2 0
      src/main/java/com/td/boss/game/comsnbapply/pojo/ComSnbApply.java
  18. 5 3
      src/main/java/com/td/boss/game/comsnbapply/scheduled/BackService.java
  19. 4 0
      src/main/java/com/td/boss/game/comsnbapply/service/ComSnbApplyService.java
  20. 19 0
      src/main/java/com/td/boss/game/comsnbapply/service/ComSnbApplyServiceImpl.java
  21. 16 0
      src/main/java/com/td/boss/game/comsnbapply/vo/ComSnbApplyBetweenVo.java
  22. 2 2
      src/main/java/com/td/boss/game/comsnbapply/vo/ComSnbApplySimpleVo.java
  23. 2 0
      src/main/java/com/td/boss/game/comsnbapply/vo/ComSnbApplyVo.java
  24. 74 29
      src/main/java/com/td/boss/game/comsnbfreeze/controller/ComSnbFreezeController.java
  25. 6 2
      src/main/java/com/td/boss/game/comsnbtran/repository/ComSnbTranRepository.java
  26. 2 0
      src/main/java/com/td/boss/game/comsnbtran/service/ComSnbTranService.java
  27. 6 0
      src/main/java/com/td/boss/game/comsnbtran/service/ComSnbTranServiceImpl.java
  28. 27 0
      src/main/java/com/td/boss/game/comsnbtran/vo/ComSnbTranAbnormalVo.java
  29. 2 2
      src/main/java/com/td/boss/game/comsnbtran/vo/ComSnbTranTranTypeSumVo.java
  30. 66 5
      src/main/java/com/td/boss/sys/sysGame/controller/sysGamePropertyController.java
  31. 2 0
      src/main/java/com/td/boss/sys/syssettingtask/pojo/SysSettingTask.java
  32. 2 0
      src/main/java/com/td/boss/sys/syssettingtask/vo/SysSettingTaskVo.java
  33. 10 2
      src/main/java/com/td/boss/util/RedisData.java
  34. 1 1
      src/main/resources/application.yml
  35. 47 2
      src/main/resources/static/sys/aComApplySNBToCNT/js/applySNBToCNT.js
  36. 101 10
      src/main/resources/static/sys/aComCNTAndSNB/js/CNTAndSNB.js
  37. 22 0
      src/main/resources/static/sys/aComCntToSnb/aComCntToSnb.css
  38. 132 0
      src/main/resources/static/sys/aComCntToSnb/aComCntToSnb.js
  39. 24 4
      src/main/resources/static/sys/aComUser/js/user.js
  40. 1 1
      src/main/resources/static/sys/aComUser/js/userPlayerGoods.js
  41. 51 16
      src/main/resources/view/sys/aComApplySNBToCNT/applySNBToCNT.html
  42. 17 0
      src/main/resources/view/sys/aComCNTAnbSNB/CNTAndSNB.html
  43. 42 0
      src/main/resources/view/sys/aComCntToSnb/aComCntToSnb.html
  44. 1 1
      src/test/java/com/td/boss/ComPlayerDisasterLogTests.java

+ 5 - 5
pom.xml

@@ -155,11 +155,11 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
-            <version>5.7.22</version>
-        </dependency>
+        <!--<dependency>-->
+        <!--    <groupId>cn.hutool</groupId>-->
+        <!--    <artifactId>hutool-all</artifactId>-->
+        <!--    <version>5.7.22</version>-->
+        <!--</dependency>-->
 
     </dependencies>
 

+ 5 - 1
src/main/java/com/td/boss/config/enums/ResultEnum.java

@@ -21,6 +21,7 @@ public enum ResultEnum {
     SETTING_IS_NULL(306,"配置信息不存在"),
     //redis部分
     REDIS_IS_LOCK(307,"操作过于频繁,稍后再试!"),
+    REDIS_IS_LOCK_ERROR(308,"操作失败,稍后再试!"),
     //用户数据
     USER_DOES_NOT_EXIST(400,"不能存在用户信息!"),
     USER_ENERGY_IS_INSUFFICIENT(401,"用户能量不足!"),
@@ -56,7 +57,7 @@ public enum ResultEnum {
     APPLY_SNB_AMOUNT_ERROR(605,"snb参数错误!"),
     APPLY_SNB_TOO_MUCH(606,"snb申请过多,待审核完成后再申请!"),
     APPLY_SNB_HAS_APPLY(607,"已有一笔snb申请中,待审核完成后再申请!"),
-
+    APPLY_SNB_STATE_ERROR(608,"状态信息错误!"),
     //土地数据
     LAND_DATA_ERROR(701,"土地数据不能初始化!"),
     LAND_NOT_LEASE(702,"土地未租赁!"),
@@ -75,6 +76,9 @@ public enum ResultEnum {
     LAND_USE_TOOL(714,"该土地正在使用工具中!"),
     LAND_LAND_LEVELUPPING(715,"该土地正在升级中!"),
 
+    //土地受灾中,稍后重试!
+    LAND_DISATER_LOCK(715,"土地正在遭受灾害,稍后重试!"),
+
 
     //种子数据不能存在
     SEED_DATA_ERROR(801,"种子数据不存在!"),

+ 2 - 2
src/main/java/com/td/boss/game/comcntorder/service/ComCntOrderService.java

@@ -15,10 +15,10 @@ public interface ComCntOrderService extends CommonService<ComCntOrderVo, ComCntO
 
     List<ComCntOrder>  findByUserIdAndPayType(String userId,Integer payType);
 
-    //返回一个全部总量
+    //返回一个全部总量,需要去除负数情况,负数另外计算
     List<ComCntOrderPayTypeSumVo> findAllCNTSumGroupByPayType();
 
-    //返回一个日期查找的总量
+    //返回一个日期查找的总量,需要去除负数情况,负数另外计算
     List<ComCntOrderPayTypeSumVo> findAllCNTSumGroupByPayTypeFromDate(Date startTime, Date endTime);
 
 

+ 10 - 0
src/main/java/com/td/boss/game/comcnttosnb/service/ComCntToSnbService.java

@@ -1,10 +1,15 @@
 package com.td.boss.game.comcnttosnb.service;
 
+import cn.hutool.core.date.DateTime;
 import com.td.boss.common.pojo.Result;
 import com.td.boss.common.service.CommonService;
+import com.td.boss.game.comcntorder.pojo.ComCntOrder;
 import com.td.boss.game.comcnttosnb.pojo.ComCntToSnb;
 import com.td.boss.game.comcnttosnb.vo.ComCntToSnbVo;
 
+import java.util.Date;
+import java.util.List;
+
 /**
  * Cnt转Snb服务实现
  *
@@ -26,4 +31,9 @@ public interface ComCntToSnbService extends CommonService<ComCntToSnbVo, ComCntT
      * @param userId 用户id
      */
     Result<String> receiveByUserId(String userId);
+
+
+    //根据时间段,导出全部数据
+    List<ComCntToSnb> getBetweenTimeList(Date begin, Date end);
+
 }

+ 28 - 3
src/main/java/com/td/boss/game/comcnttosnb/service/ComCntToSnbServiceImpl.java

@@ -1,15 +1,18 @@
 package com.td.boss.game.comcnttosnb.service;
 
 import cn.hutool.core.convert.Convert;
+import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
 import com.td.boss.common.pojo.Result;
 import com.td.boss.common.service.CommonServiceImpl;
 import com.td.boss.config.enums.ResultEnum;
+import com.td.boss.game.comcntorder.pojo.ComCntOrder;
 import com.td.boss.game.comcnttosnb.pojo.ComCntToSnb;
 import com.td.boss.game.comcnttosnb.repository.ComCntToSnbRespository;
 import com.td.boss.game.comcnttosnb.vo.ComCntToSnbVo;
+import com.td.boss.game.complayerland.pojo.ComPlayerDisasterLog;
 import com.td.boss.game.comsnbtran.service.ComSnbTranService;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import com.td.boss.game.comusers.service.ComUsersService;
@@ -19,12 +22,19 @@ import com.td.boss.util.RedisData;
 import com.td.boss.util.RedisLock;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
 
 @Slf4j
 @Service
@@ -132,9 +142,9 @@ public class ComCntToSnbServiceImpl extends CommonServiceImpl<ComCntToSnbVo, Com
             snbTran.setTranId(Convert.toStr(comCntToSnb.getId()));
             snbTran.setUserId(userId);
             snbTran.setTranName("领取SNB");
-//            snbTran.setTranType();
-            snbTran.setTranAmount(0);
-//            snbTran.setTranPrice();
+            snbTran.setTranType(8);
+            snbTran.setTranAmount(1);
+            snbTran.setTranPrice(0);
             snbTran.setTranDescribe(StrUtil.format("user领取SNB、本次领取:{},剩余:{}", thisReceiveQuantity, comCntToSnb.getTotalQuantity().subtract(comCntToSnb.getReceivedQuantity())));
             snbTran.setIsAdd(1);
             snbTran.setBeforeSnb(comUsersVo.getSnb());
@@ -160,4 +170,19 @@ public class ComCntToSnbServiceImpl extends CommonServiceImpl<ComCntToSnbVo, Com
             redisLock.unlock(redisKey, String.valueOf(time));
         }
     }
+
+
+
+    @Override
+    public List<ComCntToSnb> getBetweenTimeList(Date begin, Date end) {
+        Specification specification = new Specification<ComCntToSnb>() {
+            @Override
+            public Predicate toPredicate(Root<ComCntToSnb> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
+                List<Predicate> predicates = new ArrayList<>();
+                predicates.add(criteriaBuilder.between(root.get("beginTime"), begin, end));
+                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        };
+        return comCntToSnbRespository.findAll(specification);
+    }
 }

+ 8 - 1
src/main/java/com/td/boss/game/comcnttosnb/vo/ComCntToSnbVo.java

@@ -1,5 +1,6 @@
 package com.td.boss.game.comcnttosnb.vo;
 
+import com.td.boss.common.pojo.PageCondition;
 import lombok.Data;
 
 import javax.persistence.*;
@@ -14,9 +15,15 @@ import java.util.Date;
  * @date 2022/03/05
  */
 @Data
-public class ComCntToSnbVo implements Serializable {
+public class ComCntToSnbVo extends PageCondition implements Serializable {
 
     private Long id;
+
+    /**
+     * 钱包地址
+     */
+    private String address;
+
     /**
      * 需要返还的总数
      */

+ 103 - 19
src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java

@@ -255,10 +255,21 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
             _redisKey = comPlayerLand.getUserId() + "or" + comPlayerLand.getConfigLandId();
         }
+        //受灾时候,不给收获
+        String _disasterKey = RedisData.getPlayerDisastersFirstKey() + comPlayerLand.getConfigLandId() + comPlayerLand.getUserId();
+        long _disasterTime = System.currentTimeMillis() + RedisData.getPlayerDisastersFirstTimeout();
+
         Map map = new HashMap();
         //todo 总共偷去的数量
         Double _stealProfits = 0d;
+        //todo 灾难影响的数量
+        Double _disasterProfits = 0d;
         try {
+            //加一层受灾锁
+            if (!redisLock.lock(_disasterKey, String.valueOf(_disasterTime))) {
+                return Result.of(null, false, ResultEnum.LAND_DISATER_LOCK.getMessage(), ResultEnum.LAND_DISATER_LOCK.getCode());
+            }
+
             // 如果存在plantFlag 说明是新种植的
             if (!redisLock.lock(_redisKey, String.valueOf(time))) {
                 return Result.of(null, false, ResultEnum.LAND_STEAL_LOCK.getMessage(), ResultEnum.LAND_STEAL_LOCK.getCode());
@@ -285,9 +296,9 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             // 配置的参数。这里先直接定义
             Double profitConfig = comSettingVo.getProfit(), stealRatioMaxConfig = comSettingVo.getStealMaxRatio(), stealRatioMinConfig = comSettingVo.getStealMinRatio(), finallyGetRatioConfig = comSettingVo.getFinalRatio();
             Double landLevelInCome = getLandLevelInCome(comPlayerLand, comMallSeedVo.getPriceSnb());
-            Double _profitDouble = DoubleUtil.add(_profit.doubleValue(),landLevelInCome);
+            Double _profitDouble = DoubleUtil.add(_profit.doubleValue(), landLevelInCome);
             Double _residualProfit = DoubleUtil.mul(_profitDouble, DoubleUtil.sub(1d, profitConfig));//如果 profitConfig 0.2,剩余利润就是0.8;
-            Double _stealAmount = DoubleUtil.sub(_profitDouble, _residualProfit); //可偷取的利润
+            //Double _stealAmount = DoubleUtil.sub(_profitDouble, _residualProfit); //可偷取的利润
 
             //todo 计算总共损失的数量
             List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(userId, _redisKey, comPlayerLand.getConfigLandId());
@@ -295,21 +306,29 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 ComPlayerProfit temp = comPlayerProfits.get(i);
                 _stealProfits = DoubleUtil.add(_stealProfits, temp.getStolen());
             }
-            Double _userHarvestPart = DoubleUtil.sub(_stealAmount, _stealProfits);
+            // Double _userHarvestPart = DoubleUtil.sub(_stealAmount, _stealProfits);
+            Double _userHarvestPart = DoubleUtil.sub(_profitDouble, _stealProfits);
+            Double _endLossProfits = 0d;
             if (_userHarvestPart < 0.0) {
                 //差值不能为负数
                 _userHarvestPart = 0d;
                 //相当于被偷取全部利润,这里返回一个被偷去的全部利润值
-                map.put("lossAmount", _stealAmount);
+                //map.put("lossAmount", _stealAmount);
+                map.put("lossAmount", _profitDouble);
+                _endLossProfits = _profitDouble;
             } else {
                 //todo 返回一个被偷的数量
                 map.put("lossAmount", _stealProfits);
+                _endLossProfits = _stealProfits;
             }
 
+            //上面计算被偷的,下面计算灾难影响的
+
+
             //todo 利润
             _amount -= _profit;
-            //用户收取的对应数量,固定收入+被偷取后剩余的部分
-            _amountPart = DoubleUtil.add(_residualProfit, _userHarvestPart);
+            //用户收取的对应数量,固定收入+被偷取后剩余的部分 (改成全部影响利润了。没有固定收入)
+            _amountPart = _userHarvestPart;// DoubleUtil.add(_residualProfit, _userHarvestPart);
             //果实 Type =1
             ComPlayerGoods comPlayerGoodsSimpleVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 1);
             Integer _beforeAmount = 0;
@@ -355,7 +374,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             _playerLog.setAfterAmount(comPlayerGoodsSimpleVo.getAmount());
             //收取时候信息记录
             _playerLog.setTPart(_amountPart);
-            _playerLog.setTLoss(_stealProfits); //损失的部分
+            _playerLog.setTLoss(_endLossProfits); //(_stealProfits); //损失的部分
             _playerLog.setBeforePart(_beforeProfitPart);
             _playerLog.setAfterPart(_afterProfitPart);
             _playerLog.setLMultiple(comPlayerLand.getLeaseMultiple());
@@ -364,9 +383,11 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
 
             //对应的,存在plantFlag则解锁
             redisLock.unlock(_redisKey, String.valueOf(time));
+            redisLock.unlock(_disasterKey, String.valueOf(_disasterTime));
         } catch (Exception e) {
             //对应的,存在plantFlag则解锁
             redisLock.unlock(_redisKey, String.valueOf(time));
+            redisLock.unlock(_disasterKey, String.valueOf(_disasterTime));
             throw new RuntimeException(e.getMessage());
         }
         map.put("msg", "成功收取果实!");
@@ -507,7 +528,17 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
         //需要redis 加锁
         long time = System.currentTimeMillis() + RedisData.getPlayerGoodsTimeout();
 
+        //受灾时候,不给收获
+        String _disasterKey = RedisData.getPlayerDisastersFirstKey() + otherPlayerLand.getConfigLandId() + otherPlayerLand.getUserId();
+        long _disasterTime = System.currentTimeMillis() + RedisData.getPlayerDisastersFirstTimeout();
+
+
         try {
+            //加一层受灾锁
+            if (!redisLock.lock(_disasterKey, String.valueOf(_disasterTime))) {
+                return Result.of(null, false, ResultEnum.LAND_DISATER_LOCK.getMessage(), ResultEnum.LAND_DISATER_LOCK.getCode());
+            }
+
             if (!redisLock.lock(_redisSNBKey, String.valueOf(time))) {
                 //如果有snb冲突锁
                 return Result.of(null, false, ResultEnum.USER_LOGIN_LOCK.getMessage(), ResultEnum.USER_LOGIN_LOCK.getCode());
@@ -530,7 +561,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             //todo 拿出计算利润,收获量减去种子的成本(snb)后的百分之30 ,后面需要后台可调整
             Double landLevelInCome = getLandLevelInCome(otherPlayerLand, comMallSeedVo.getPriceSnb());
             Integer _profitInt = _otherAmount - otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
-            Double _profit =  DoubleUtil.add(_profitInt.doubleValue(),landLevelInCome);
+            Double _profit = DoubleUtil.add(_profitInt.doubleValue(), landLevelInCome);
             // 配置的参数。这里先直接定义
             // 需要根据 狗是否生效,小偷是否装备打狗棒来确定参数
             Double profitConfig = _dogWork ? comSettingVo.getProfitDog() : comSettingVo.getProfit(),
@@ -543,27 +574,70 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             if (_dogWork) {
                 _stealRatio = _holdTheStick ? comSettingVo.getStealRatioHasStick() : comSettingVo.getStealRatioNoStick();
             }
-            Double _stolenAmount = DoubleUtil.mul(_profit.doubleValue(), _stealRatio);
+            Double _stolenAmount = DoubleUtil.mul(_profit, _stealRatio);
             //这里根据plantFlag判断目标用户当前种植被偷取完,记录更新用户 comPlayerLand plantSteal 字段;保存一个偷取状态
-            Double _sumStolen = comPlayerProfitService.getStolenSumByOtherUserIdAndPlantFlag(otherUserId, _redisKey);
+            //这里只拿去被偷的利润,灾难扣除的不算再这里,但是总利润需要限制计算
+            //Double _sumStolen = comPlayerProfitService.getStolenSumByOtherUserIdAndPlantFlagAndLossType(otherUserId, _redisKey,0);
+            Double _sumStolen = 0d,_allStolen = 0d;
+            List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(otherUserId, _redisKey, otherPlayerLand.getConfigLandId());
+            for (int i = 0; i < comPlayerProfits.size(); i++) {
+                ComPlayerProfit temp = comPlayerProfits.get(i);
+                if(temp.getLossType().equals(0)){
+                    //偷取时候的利润总和
+                    _sumStolen = DoubleUtil.add(_sumStolen, temp.getStolen());
+                }
+                //当前全部损失的利润
+                _allStolen = DoubleUtil.add(_allStolen, temp.getStolen());
+            }
+
             //todo 这里的可偷利润应该是最大值,用户不能超过这个,需要限制判断
-            Double _maxAmount = DoubleUtil.mul(_profit.doubleValue(), profitConfig); //可偷取的利润
+            Double _maxAmount = DoubleUtil.mul(_profit, profitConfig); //可偷取的利润
             //1 单偷操作 就是 _sumStolen>_maxAmount 或者 _sumStolen == _maxAmount ,被偷完了
-            if (!DoubleUtil.compare(_sumStolen, _maxAmount).equals(-1)) {
+            //if (!DoubleUtil.compare(_sumStolen, _maxAmount).equals(-1)) {
+            //    // 需要redis 解锁
+            //    redisLock.unlock(_redisKey, String.valueOf(time));
+            //    redisLock.unlock(_redisSNBKey, String.valueOf(time));
+            //    redisLock.unlock(_disasterKey, String.valueOf(_disasterTime));
+            //    //记录一个不可偷取的状态
+            //    otherPlayerLand.setPlantSteal(0);
+            //    comPlayerLandService.save(CopyUtil.copy(otherPlayerLand, ComPlayerLandVo.class));
+            //    map.put("plant_steal", otherPlayerLand.getPlantSteal());
+            //    return Result.of(map, false, ResultEnum.LAND_CAN_STEAL_IS_MAX.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_MAX.getCode());
+            //}
+            //计算剩下可偷利润的差,防止过多偷取用户利润 _stolenAmount
+            //Double _diff = Math.abs(DoubleUtil.sub(_maxAmount, _sumStolen));
+            Double _diff = DoubleUtil.sub(_maxAmount, _sumStolen);
+            Boolean isUpdateCanSteal = false;
+            if (DoubleUtil.compare(_diff,0.0).equals(1)) {
+                if(DoubleUtil.compare(_stolenAmount, _diff).equals(1)){
+                    _stolenAmount = _diff;
+                    isUpdateCanSteal = true;
+                }
+            }else{
+                _stolenAmount = 0d;
+                isUpdateCanSteal = true;
+            }
+            //这里需要拦截处理最终偷取的利润,比如 总利润_profit=530(可能会加上收益),
+            // _allStolen + _stolenAmount 不能大于总利润
+            Double _endLossProfit = DoubleUtil.add(_allStolen,_stolenAmount);
+            Double _endLossDiff = DoubleUtil.sub(_profit,_endLossProfit);
+            if(!DoubleUtil.compare(_sumStolen, _maxAmount).equals(-1) || DoubleUtil.compare(_endLossDiff,0.0).equals(-1)){
+                //如果差值为零
                 // 需要redis 解锁
                 redisLock.unlock(_redisKey, String.valueOf(time));
                 redisLock.unlock(_redisSNBKey, String.valueOf(time));
+                redisLock.unlock(_disasterKey, String.valueOf(_disasterTime));
                 //记录一个不可偷取的状态
                 otherPlayerLand.setPlantSteal(0);
                 comPlayerLandService.save(CopyUtil.copy(otherPlayerLand, ComPlayerLandVo.class));
                 map.put("plant_steal", otherPlayerLand.getPlantSteal());
                 return Result.of(map, false, ResultEnum.LAND_CAN_STEAL_IS_MAX.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_MAX.getCode());
             }
-            //计算剩下可偷利润的差,防止过多偷取用户利润 _stolenAmount
-            Double _diff = Math.abs(DoubleUtil.sub(_maxAmount, _sumStolen));
-            if (DoubleUtil.compare(_stolenAmount, _diff).equals(1)) {
-                //_stolenAmount>_diff
-                _stolenAmount = _diff;
+            if(isUpdateCanSteal){
+                //记录一个不可偷取的状态
+                otherPlayerLand.setPlantSteal(0);
+                comPlayerLandService.save(CopyUtil.copy(otherPlayerLand, ComPlayerLandVo.class));
+                map.put("plant_steal", otherPlayerLand.getPlantSteal());
             }
             //最终偷窃人获取的是偷取的是目标用户损失量的10% finallyGetRatioConfig
             Double _finalStealAmount = DoubleUtil.mul(_stolenAmount, finallyGetRatioConfig);
@@ -603,15 +677,20 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             comPlayerProfit.setLeaseMultiple(otherPlayerLand.getLeaseMultiple());
             comPlayerProfit.setLeaseDate(otherPlayerLand.getLeaseDate());
             comPlayerProfit.setHarvest(_otherAmount);
-            comPlayerProfit.setProfit(_profit.doubleValue());//目标用户可偷的初始利润值
+            comPlayerProfit.setProfit(_profit);//目标用户可偷的初始利润值
             comPlayerProfit.setStolen(_stolenAmount);//目标用户被偷的数量
             comPlayerProfit.setFinalSteal(_finalStealAmount);//用户最终偷取的量,是被偷的数量 10%左右
-            comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(_stolenAmount, _sumStolen))); //可偷的减去被偷的
+            comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit, DoubleUtil.add(_stolenAmount, _sumStolen))); //可偷的减去被偷的
             //记录相关比例
             comPlayerProfit.setProfitRatio(profitConfig);
             comPlayerProfit.setStealRatio(_stealRatio);
             comPlayerProfit.setFinalRatio(finallyGetRatioConfig);
             comPlayerProfit.setLossType(0);
+
+            //
+            comPlayerProfit.setDsasterId(-10L);
+            comPlayerProfit.setAddedPart(landLevelInCome);
+
             ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
             comPlayerProfitService.save(comPlayerProfitVo);
 
@@ -736,11 +815,14 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
 
             //解除snb锁
             redisLock.unlock(_redisSNBKey, String.valueOf(time));
+
+            redisLock.unlock(_disasterKey, String.valueOf(_disasterTime));
             return Result.of(map);
         } catch (Exception e) {
             // 需要redis 解锁
             redisLock.unlock(_redisKey, String.valueOf(time));
             redisLock.unlock(_redisSNBKey, String.valueOf(time));
+            redisLock.unlock(_disasterKey, String.valueOf(_disasterTime));
             throw new RuntimeException(e.getMessage());
         }
 
@@ -979,8 +1061,10 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
 //    }
     @Autowired
     private ComConfigService comConfigService;
+
     /**
      * 获得土地级别收益,普通土地最后结果为0
+     *
      * @param comPlayerLand
      * @param priceSnb
      * @return

+ 77 - 66
src/main/java/com/td/boss/game/complayerland/controller/ComPlayerLandController.java

@@ -140,7 +140,7 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
                         //说明可以收获了
                         comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                         comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
-                        //生成第一次受灾
+                        //生成第一次受灾 获取用户土地 getList
                         _InitFirstDisasterProfit(comPlayerLandAndPlantVo, comMallSeedVo);
                     } else {
                         comPlayerLandAndPlantVo.setPlantDaysRemaining(DateUtil.getDays(diff).intValue());
@@ -156,7 +156,8 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
             }).collect(Collectors.toList());
 
         } catch (Exception e) {
-            throw new RuntimeException(e.getMessage());
+            //throw new RuntimeException(e.getMessage());
+            return  Result.of(null,false,"服务器繁忙,请刷新游戏重新进入!",ResultEnum.REDIS_IS_LOCK.getCode());
         }
 
         return Result.of(_list);
@@ -211,7 +212,7 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
                         //说明可以收获了
                         comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                         comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
-                        //生成第一次受灾
+                        //生成第一次受灾 getCanStealDetailList
                         _InitFirstDisasterProfit(comPlayerLandAndPlantVo, comMallSeedVo);
 
                     } else {
@@ -302,8 +303,6 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
             @RequestParam(value = "landId") Integer landId,
             @RequestParam(value = "seedId") Integer seedId) {
 
-        long time = System.currentTimeMillis() + RedisData.getPlayerDisastersFirstTimeout();
-
         try {
             ComPlayerLand comPlayerLand = comPlayerLandService.findByUserIdAndLandId(userId, landId);
             //土地数据不存在
@@ -432,7 +431,7 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
                 comPlayerLandAndPlantVo.setPlantDaysRemaining(0);
                 comPlayerLandAndPlantVo.setPlantHoursRemaining(0);
 
-                //生成第一次受灾
+                //生成第一次受灾 plant
                 _InitFirstDisasterProfit(comPlayerLandAndPlantVo, comMallSeedVo);
 
 
@@ -495,8 +494,8 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
                 .sorted(Comparator.comparing(ComPlayerDisasterProtected::getProtectTime).reversed())
                 .findFirst().orElse(null);
         Map map = new HashMap();
-        map.put("naturalProtected",CopyUtil.copy(_naturalDisasterProtected, ComPlayerDisasterProtectedSimpleVo.class));
-        map.put("beastProtected",CopyUtil.copy(_beastDisasterProtected, ComPlayerDisasterProtectedSimpleVo.class));
+        map.put("naturalProtected",_naturalDisasterProtected == null? null: CopyUtil.copy(_naturalDisasterProtected, ComPlayerDisasterProtectedSimpleVo.class));
+        map.put("beastProtected",_beastDisasterProtected == null? null:CopyUtil.copy(_beastDisasterProtected, ComPlayerDisasterProtectedSimpleVo.class));
         return Result.of(map);
     }
 
@@ -505,73 +504,85 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
         //todo 添加一个灾难损失,灾难损失的时间点是种植开始到成熟阶段的一个随机时间
         // 加个锁判断,是否在其他地方触发了这次灾难计算(自解锁)
         long time = System.currentTimeMillis() + RedisData.getPlayerDisastersFirstTimeout();
-        String _disasterKey = RedisData.getPlayerDisastersFirstKey() + comPlayerLandAndPlantVo.getPlantFlag();
-        if (redisLock.lock(_disasterKey, String.valueOf(time))) {
-            //查询当前人员购买防护历史记录
-            List<ComPlayerDisasterProtected> protectList = disasterProtectedService.getComPlayerDisasterProtectedByUserIdOrderByProtectTimeDesc(comPlayerLandAndPlantVo.getUserId());
-
-            //灾难发生时间
-            Date endDate = DateUtil.getOldDateAddDay(comPlayerLandAndPlantVo.getPlantStart(), comPlayerLandAndPlantVo.getPlantMature());
-            //log.info(comPlayerLandAndPlantVo.getPlantStart().getTime() + "= " + endDate.getTime());
-            long randomDate =comPlayerLandAndPlantVo.getPlantStart().compareTo(endDate) == 0?
-                    endDate.getTime(): RandomUtil.randomLong(comPlayerLandAndPlantVo.getPlantStart().getTime(), endDate.getTime());
-            Date disasterDate = new Date(randomDate);
-            //获取损失的数据
-            List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(comPlayerLandAndPlantVo.getUserId(), comPlayerLandAndPlantVo.getPlantFlag(), comPlayerLandAndPlantVo.getConfigLandId());
-            //todo 总共受损的数量
-            Double _allLossProfit = 0d;
-            boolean isNaturalProfit = false, isBeastProfit = false;
-            for (int j = 0; j < comPlayerProfits.size(); j++) {
-                ComPlayerProfit _profit = comPlayerProfits.get(j);
-                _allLossProfit = DoubleUtil.add(_allLossProfit, _profit.getStolen());
-                if (_profit.getLossType().equals(2)) {
-                    isNaturalProfit = true;
-                } else if (_profit.getLossType().equals(3)) {
-                    isBeastProfit = true;
+        String _disasterKey = RedisData.getPlayerDisastersFirstKey() + comPlayerLandAndPlantVo.getConfigLandId() + comPlayerLandAndPlantVo.getUserId();
+        try {
+            if (redisLock.lock(_disasterKey, String.valueOf(time))) {
+                //查询当前人员购买防护历史记录
+                List<ComPlayerDisasterProtected> protectList = disasterProtectedService.getComPlayerDisasterProtectedByUserIdOrderByProtectTimeDesc(comPlayerLandAndPlantVo.getUserId());
+
+                //灾难发生时间
+                Date endDate = DateUtil.getOldDateAddDay(comPlayerLandAndPlantVo.getPlantStart(), comPlayerLandAndPlantVo.getPlantMature());
+                //log.info(comPlayerLandAndPlantVo.getPlantStart().getTime() + "= " + endDate.getTime());
+                long randomDate =comPlayerLandAndPlantVo.getPlantStart().compareTo(endDate) == 0?
+                        endDate.getTime(): RandomUtil.randomLong(comPlayerLandAndPlantVo.getPlantStart().getTime(), endDate.getTime());
+                Date disasterDate = new Date(randomDate);
+                //获取损失的数据
+                List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(comPlayerLandAndPlantVo.getUserId(), comPlayerLandAndPlantVo.getPlantFlag(), comPlayerLandAndPlantVo.getConfigLandId());
+                //todo 总共受损的数量
+                Double _allLossProfit = 0d;
+                boolean isNaturalProfit = false, isBeastProfit = false;
+                for (int j = 0; j < comPlayerProfits.size(); j++) {
+                    ComPlayerProfit _profit = comPlayerProfits.get(j);
+                    _allLossProfit = DoubleUtil.add(_allLossProfit, _profit.getStolen());
+                    if (_profit.getLossType().equals(2)) {
+                        if(DoubleUtil.compare(-1D, _profit.getDsasterId().doubleValue()).equals(0)){
+                            isNaturalProfit = true;
+                        }
+                    } else if (_profit.getLossType().equals(3)) {
+                        if(DoubleUtil.compare(-1D, _profit.getDsasterId().doubleValue()).equals(0)){
+                            isBeastProfit = true;
+                        }
+                    }
                 }
-            }
-            log.info("用户编号:{},防护历史记录:{}", comPlayerLandAndPlantVo.getUserId(), JSONUtil.toJsonStr(protectList));
-            //获得对应灾难类型的防护记录    并得到这个 防护到期时间. 自然灾害类型
-            //如果没有防护或者防护到期。则直接发生灾难进行减产
-            if (!isNaturalProfit) {
-                Date _protectedDate = protectList.stream()
-                        .filter(a -> a.getDsasterType().equals(2))
-                        .sorted(Comparator.comparing(ComPlayerDisasterProtected::getProtectTime).reversed())
-                        .map(ComPlayerDisasterProtected::getProtectTime)
-                        .findFirst().orElse(cn.hutool.core.date.DateUtil.parse(null));
+                log.info("用户编号:{},防护历史记录:{}", comPlayerLandAndPlantVo.getUserId(), JSONUtil.toJsonStr(protectList));
+                //获得对应灾难类型的防护记录    并得到这个 防护到期时间. 自然灾害类型
                 //如果没有防护或者防护到期。则直接发生灾难进行减产
-                if (_protectedDate != null && disasterDate.before(_protectedDate)) {
-                    //灾难的随机时间比防护包时间后,说明防护包到期
-                    //成熟的时候触发第一次自然灾难
-                    ComPlayerProfitVo naturalProfitVo = comPlayerProfitService.addFirstDisasterAndLoss(CopyUtil.copy(comPlayerLandAndPlantVo, ComPlayerLand.class),
-                            comMallSeedVo, 2, _allLossProfit);
-                    //多次执行需要加上当前操作的利润
-                    _allLossProfit += naturalProfitVo.getStolen();
-
-                    //添加自然灾害灾难记录
-                    comPlayerDisasterLogService.addDisasterEnable(comPlayerLandAndPlantVo.getUserId(),-1L,2,_protectedDate);
+
+                if (!isNaturalProfit) {
+                    Date _protectedDate = protectList.stream()
+                            .filter(a -> a.getDsasterType().equals(2))
+                            .sorted(Comparator.comparing(ComPlayerDisasterProtected::getProtectTime).reversed())
+                            .map(ComPlayerDisasterProtected::getProtectTime)
+                            .findFirst().orElse(cn.hutool.core.date.DateUtil.parse(null));
+                    //如果没有防护或者防护到期。则直接发生灾难进行减产
+                    if (_protectedDate == null || disasterDate.after(_protectedDate)) {
+                        //灾难的随机时间比防护包时间后,说明防护包到期
+                        //成熟的时候触发第一次自然灾难
+                        ComPlayerProfitVo naturalProfitVo = comPlayerProfitService.addFirstDisasterAndLoss(CopyUtil.copy(comPlayerLandAndPlantVo, ComPlayerLand.class),
+                                comMallSeedVo, 2, _allLossProfit,-1);
+                        //多次执行需要加上当前操作的利润
+                        _allLossProfit += naturalProfitVo.getStolen();
+
+                        //添加自然灾害灾难记录
+                        comPlayerDisasterLogService.addDisasterEnable(comPlayerLandAndPlantVo.getUserId(),-1L,2,_protectedDate);
+                    }
                 }
-            }
-            if (!isBeastProfit) {
-                Date _protectedDate = protectList.stream()
-                        .filter(a -> a.getDsasterType().equals(3))
-                        .sorted(Comparator.comparing(ComPlayerDisasterProtected::getProtectTime).reversed())
-                        .map(ComPlayerDisasterProtected::getProtectTime)
-                        .findFirst().orElse(cn.hutool.core.date.DateUtil.parse(null));
-                //如果没有防护或者防护到期。则直接发生灾难进行减产
-                if (_protectedDate != null && disasterDate.before(_protectedDate)) {
-                    //灾难的随机时间比防护包时间后,说明防护包到期
-                    //成熟的时候触发第一次自然灾难
-                    ComPlayerProfitVo beastProfitVo = comPlayerProfitService.addFirstDisasterAndLoss(CopyUtil.copy(comPlayerLandAndPlantVo, ComPlayerLand.class),
-                            comMallSeedVo, 3, _allLossProfit);
+                if (!isBeastProfit) {
+                    Date _protectedDate = protectList.stream()
+                            .filter(a -> a.getDsasterType().equals(3))
+                            .sorted(Comparator.comparing(ComPlayerDisasterProtected::getProtectTime).reversed())
+                            .map(ComPlayerDisasterProtected::getProtectTime)
+                            .findFirst().orElse(cn.hutool.core.date.DateUtil.parse(null));
+                    //如果没有防护或者防护到期。则直接发生灾难进行减产
+                    if (_protectedDate == null || disasterDate.after(_protectedDate)) {
+                        //灾难的随机时间比防护包时间后,说明防护包到期
+                        //成熟的时候触发第一次自然灾难
+                        ComPlayerProfitVo beastProfitVo = comPlayerProfitService.addFirstDisasterAndLoss(CopyUtil.copy(comPlayerLandAndPlantVo, ComPlayerLand.class),
+                                comMallSeedVo, 3, _allLossProfit,-1);
 //                    //多次执行需要加上当前操作的利润
 //                    _allLossProfit += beastProfitVo.getStolen();
 
-                    //添加野兽灾害灾难记录
-                    comPlayerDisasterLogService.addDisasterEnable(comPlayerLandAndPlantVo.getUserId(),-1L,3,_protectedDate);
+                        //添加野兽灾害灾难记录
+                        comPlayerDisasterLogService.addDisasterEnable(comPlayerLandAndPlantVo.getUserId(),-1L,3,_protectedDate);
 
+                    }
                 }
+
+                redisLock.unlock(_disasterKey, String.valueOf(time));
             }
+        } catch (Exception e) {
+            log.error("触发_InitFirstDisasterProfit异:" + e.getMessage());
         }
+
     }
 }

+ 30 - 17
src/main/java/com/td/boss/game/complayerland/service/ComPlayerDisasterLogServiceImpl.java

@@ -67,7 +67,7 @@ public class ComPlayerDisasterLogServiceImpl extends CommonServiceImpl<ComPlayer
     /**
      * 伤害 会减产50%
      */
-    private int damage = 50;
+    private int damage = 40;
 
     /**
      * 防御 90%概率防御灾难
@@ -242,8 +242,13 @@ public class ComPlayerDisasterLogServiceImpl extends CommonServiceImpl<ComPlayer
                 //这里处理一次判断是否发生过第一次灾难
                 //todo 添加一个灾难损失,灾难损失的时间点是种植开始到成熟阶段的一个随机时间
                 // 加个锁判断,是否在其他地方触发了这次灾难计算(自解锁)
-                String _disasterKey = RedisData.getPlayerDisastersFirstKey() + _comPlayerLand.getPlantFlag();
-                if (redisLock.lock(_disasterKey, String.valueOf(time))) {
+                String _disasterKey = RedisData.getPlayerDisastersFirstKey() + _comPlayerLand.getConfigLandId() + _comPlayerLand.getUserId();
+                try {
+                    if (!redisLock.lock(_disasterKey, String.valueOf(time))) {
+                        log.info("锁住key:"+_disasterKey);
+                       continue;
+                    }
+
                     //灾难发生时间
                     Date endDate = com.td.boss.util.DateUtil.getOldDateAddDay(_comPlayerLand.getPlantStart(), _comPlayerLand.getPlantMature());
                     long randomDate = _comPlayerLand.getPlantStart().compareTo(endDate) == 0 ?
@@ -260,11 +265,15 @@ public class ComPlayerDisasterLogServiceImpl extends CommonServiceImpl<ComPlayer
                         ComPlayerProfit _profit = comPlayerProfits.get(j);
                         _allLossProfit = DoubleUtil.add(_allLossProfit, _profit.getStolen());
                         if (_profit.getLossType().equals(2)) {
-                            isNaturalProfit = true;
+                            if(DoubleUtil.compare(-1D, _profit.getDsasterId().doubleValue()).equals(0)){
+                                isNaturalProfit = true;
+                            }
                             //出现灾难的次数
                             _disasterCount++;
                         } else if (_profit.getLossType().equals(3)) {
-                            isBeastProfit = true;
+                            if(DoubleUtil.compare(-1D, _profit.getDsasterId().doubleValue()).equals(0)){
+                                isBeastProfit = true;
+                            }
                             //出现灾难的次数
                             _disasterCount++;
                         }
@@ -272,38 +281,40 @@ public class ComPlayerDisasterLogServiceImpl extends CommonServiceImpl<ComPlayer
                     log.info("用户编号:{},防护历史记录:{}", _comPlayerLand.getUserId(), JSONUtil.toJsonStr(protectList));
                     //获得对应灾难类型的防护记录    并得到这个 防护到期时间. 自然灾害类型
                     //如果没有防护或者防护到期。则直接发生灾难进行减产
-                    if (!isNaturalProfit && protectedDate != null && disasterDate.before(protectedDate)) {
+                    if (!isNaturalProfit && (protectedDate == null || disasterDate.after(protectedDate))) {
                         //灾难的随机时间比防护包时间后,说明防护包到期
                         //成熟的时候触发第一次自然灾难
                         ComPlayerProfitVo naturalProfitVo = comPlayerProfitService.addFirstDisasterAndLoss(CopyUtil.copy(_comPlayerLand, ComPlayerLand.class),
-                                comMallSeedVo, 2, _allLossProfit);
+                                comMallSeedVo, 2, _allLossProfit,-1);
                         //多次执行需要加上当前操作的利润
                         _allLossProfit += naturalProfitVo.getStolen();
 
                         //添加自然灾害灾难记录
-                        addDisasterEnable(_comPlayerLand.getUserId(),-1L,2,protectedDate);
+                        addDisasterEnable(_comPlayerLand.getUserId(), -1L, 2, protectedDate);
 
                     }
-                    if (!isBeastProfit && protectedDate != null && disasterDate.before(protectedDate)) {
+                    if (!isBeastProfit && (protectedDate == null || disasterDate.after(protectedDate))) {
                         //灾难的随机时间比防护包时间后,说明防护包到期
                         //成熟的时候触发第一次自然灾难
                         ComPlayerProfitVo beastProfitVo = comPlayerProfitService.addFirstDisasterAndLoss(CopyUtil.copy(_comPlayerLand, ComPlayerLand.class),
-                                comMallSeedVo, 3, _allLossProfit);
+                                comMallSeedVo, 3, _allLossProfit,-1);
                         //多次执行需要加上当前操作的利润
                         _allLossProfit += beastProfitVo.getStolen();
 
                         //添加野兽灾害灾难记录
-                        addDisasterEnable(_comPlayerLand.getUserId(),-1L,3,protectedDate);
+                        addDisasterEnable(_comPlayerLand.getUserId(), -1L, 3, protectedDate);
                     }
 
                     //todo 添加一条单独减产的数据 ,对应灾难
                     comPlayerProfitService.addOtherDisasterAndLoss(CopyUtil.copy(_comPlayerLand, ComPlayerLand.class),
-                            comMallSeedVo, disasterLog.getDsasterType(), _allLossProfit, _disasterCount);
-                }
+                            comMallSeedVo, disasterLog.getDsasterType(), _allLossProfit, _disasterCount,disasterLog.getDsasterId());
 
+                    redisLock.unlock(_disasterKey, String.valueOf(time));
+                } catch (Exception e) {
+                    redisLock.unlock(_disasterKey, String.valueOf(time));
+                    log.error("额外灾难加锁异常:" + e.getMessage());
+                }
             }
-
-
         } else {
             log.info("灾难结果:已防御");
         }
@@ -334,9 +345,9 @@ public class ComPlayerDisasterLogServiceImpl extends CommonServiceImpl<ComPlayer
 
 
     @Override
-    public ComPlayerDisasterLog addDisasterEnable(String userId, long disasterTableId,Integer disasterType, Date disasterDay) {
+    public ComPlayerDisasterLog addDisasterEnable(String userId, long disasterTableId, Integer disasterType, Date disasterDay) {
 
-        ComPlayerDisasterEnum disasterEnum = EnumUtil.getEnumAt(ComPlayerDisasterEnum.class,disasterType);
+        ComPlayerDisasterEnum disasterEnum = EnumUtil.likeValueOf(ComPlayerDisasterEnum.class, disasterType);
         ComPlayerDisasterLog disasterLog = new ComPlayerDisasterLog();
         disasterLog.setDsasterId(disasterTableId);
         disasterLog.setDsasterName(disasterEnum.getMsg());
@@ -348,6 +359,8 @@ public class ComPlayerDisasterLogServiceImpl extends CommonServiceImpl<ComPlayer
         disasterLog.setShow(false);
         disasterLog.setEnabled(true);
         disasterLog.setDisasterTime(disasterDay);
+
+        save(CopyUtil.copy(disasterLog, ComPlayerDisasterLogVo.class));
         return disasterLog;
     }
 }

+ 1 - 1
src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandServiceImpl.java

@@ -45,7 +45,7 @@ public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo,
     public List<ComPlayerLand> findAllByUserIdAndPlantAndMature(String userId) {
         String sql = "SELECT  a.* FROM com_player_land AS a \n" +
                 "WHERE a.user_id = "+userId+" AND a.is_lease = 1 AND a.is_plant = 1 AND DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) <= NOW() AND a.lease_time > NOW()";
-        Query nativeQuery = em.createNativeQuery(sql, ComPlayerLandAndCanSteal.class);
+        Query nativeQuery = em.createNativeQuery(sql, ComPlayerLand.class);
         List list = nativeQuery.getResultList();
         return list;
     }

+ 3 - 0
src/main/java/com/td/boss/game/complayerprofit/pojo/ComPlayerProfit.java

@@ -42,6 +42,9 @@ public class ComPlayerProfit implements Serializable {
 
     private Integer lossType;//损失的类型,默认是0:被偷取果实,1:自然灾难,2:野兽
 
+    private Long dsasterId;//遭受的攻击id,-1 代表必然灾害
+
+    private Double addedPart;//增值部分
 
     private Date createTime;//
 

+ 3 - 3
src/main/java/com/td/boss/game/complayerprofit/repository/ComPlayerProfitRepository.java

@@ -26,8 +26,8 @@ public interface ComPlayerProfitRepository extends CommonRepository<ComPlayerPro
 
     Optional<ComPlayerProfit> findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId, String targetId, Integer landId, String plantFlag);
 
-    Optional<ComPlayerProfit> findByPlantFlagAndLossType(String plantFlag,Integer lossType);
+    Optional<ComPlayerProfit> findByPlantFlagAndLossTypeAndDsasterId(String plantFlag,Integer lossType,long dsasterId);
 
-    @Query(value = "SELECT IFNULL(sum(u.stolen), 0.0) AS sum FROM  com_player_profit u  where u.target_id=:targetId and u.plant_flag = :plantFlag", nativeQuery = true)
-    Double getStolenSumByTargetIdAndPlantFlag(String targetId,String plantFlag);
+    @Query(value = "SELECT IFNULL(sum(u.stolen), 0.0) AS sum FROM  com_player_profit u  where u.target_id=:targetId and u.plant_flag = :plantFlag and u.loss_type = :lossType", nativeQuery = true)
+    Double getStolenSumByTargetIdAndPlantFlagAndLossType(String targetId,String plantFlag,Integer lossType);
 }

+ 4 - 4
src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitService.java

@@ -32,10 +32,10 @@ public interface ComPlayerProfitService extends CommonService<ComPlayerProfitVo,
      * @param lossType {2:自然灾难,3:野兽灾难}
      * @return
      */
-    ComPlayerProfit findByPlantFlagAndLossType(String plantFlag,Integer lossType);
+    ComPlayerProfit findByPlantFlagAndLossTypeAndDsasterId(String plantFlag,Integer lossType,long dsasterId);
 
 
-    Double getStolenSumByOtherUserIdAndPlantFlag(String otherUserId, String plantFlag);
+    Double getStolenSumByOtherUserIdAndPlantFlagAndLossType(String otherUserId, String plantFlag,Integer lossType);
 
     /**
      * 必然灾难减扣
@@ -45,8 +45,8 @@ public interface ComPlayerProfitService extends CommonService<ComPlayerProfitVo,
      * @param allLossProfit
      * @return
      */
-    ComPlayerProfitVo addFirstDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType,Double allLossProfit);
+    ComPlayerProfitVo addFirstDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType,Double allLossProfit,long _dsasterId);
 
-    ComPlayerProfitVo addOtherDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit,Integer disasterCount);
+    ComPlayerProfitVo addOtherDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit,Integer disasterCount,long _dsasterId);
 
 }

+ 49 - 20
src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java

@@ -5,6 +5,8 @@ import com.td.boss.common.service.*;
 import com.td.boss.game.commallseed.pojo.ComMallSeed;
 import com.td.boss.game.commallseed.vo.ComMallSeedVo;
 import com.td.boss.game.complayerland.pojo.ComPlayerLand;
+import com.td.boss.game.complayerland.service.ComPlayerLandService;
+import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
 import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
 import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
 import com.td.boss.game.complayerprofit.repository.ComPlayerProfitRepository;
@@ -31,6 +33,9 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
     @Autowired
     private ComPlayerProfitService comPlayerProfitService;
 
+    @Autowired
+    private ComPlayerLandService comPlayerLandService;
+
     @Override
     public List<ComPlayerProfit> findByUserIdAndPlantFlagAndLandId(String userId, String plantFlag, Integer landId) {
         return comPlayerProfitRepository.findByTargetIdAndPlantFlagAndLandId(userId, plantFlag, landId);
@@ -53,18 +58,18 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
     }
 
     @Override
-    public ComPlayerProfit findByPlantFlagAndLossType(String plantFlag, Integer lossType) {
-        return comPlayerProfitRepository.findByPlantFlagAndLossType(plantFlag, lossType).orElse(null);
+    public ComPlayerProfit findByPlantFlagAndLossTypeAndDsasterId(String plantFlag, Integer lossType,long dsaterId) {
+        return comPlayerProfitRepository.findByPlantFlagAndLossTypeAndDsasterId(plantFlag, lossType,dsaterId).orElse(null);
     }
 
     @Override
-    public Double getStolenSumByOtherUserIdAndPlantFlag(String otherUserId, String plantFlag) {
-        return comPlayerProfitRepository.getStolenSumByTargetIdAndPlantFlag(otherUserId, plantFlag);
+    public Double getStolenSumByOtherUserIdAndPlantFlagAndLossType(String otherUserId, String plantFlag,Integer lossType) {
+        return comPlayerProfitRepository.getStolenSumByTargetIdAndPlantFlagAndLossType(otherUserId, plantFlag,lossType);
     }
 
 
     @Override
-    public ComPlayerProfitVo addFirstDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit) {
+    public ComPlayerProfitVo addFirstDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit ,long _dsasterId) {
 
         //对应土地灾害损失
         ComPlayerProfit comPlayerProfit = new ComPlayerProfit();
@@ -86,12 +91,13 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
         //todo 计算减产,第一次灾难按利润的 50% 减产,两次就是减到 0 了。
 
         //必然发生的灾难,减产50%
-        Double _reduceProfit = DoubleUtil.mul(_profit, 0.5);
+        Double _firstRatio = 0.4d;
+        Double _reduceProfit = DoubleUtil.mul(_profit, _firstRatio);
         // 100 - 80 = 20
         Double _residualProfit = DoubleUtil.sub(_profit, allLossProfit);
         //剩余利润减去当前需要减产的利润值
         Double _tempProfit = DoubleUtil.sub(_residualProfit, _reduceProfit);
-        if (DoubleUtil.compare(_tempProfit, 0.0).equals(1)) {
+        if (!DoubleUtil.compare(_tempProfit, 0.0).equals(-1)) {
             //还有利润,
             _endReduceProfit = _reduceProfit;
         }
@@ -106,13 +112,17 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
         comPlayerProfit.setProfit(_profit);//todo 目标用户可偷的初始利润值
         comPlayerProfit.setStolen(_endReduceProfit);//todo 目标用户被灾害减产对应的数量
         comPlayerProfit.setFinalSteal(_endReduceProfit);//
-        comPlayerProfit.setProfitAfter(DoubleUtil.add(allLossProfit, _endReduceProfit)); //当前损失的利润加上当前扣减的
+        comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(allLossProfit, _endReduceProfit))); //可偷的减去被偷的(包括灾难)
 
-        //记录相关比例,损失利润的百分之50
-        comPlayerProfit.setProfitRatio(0.5);
-        comPlayerProfit.setStealRatio(0.5);
+        //记录相关比例,损失利润的百分之40
+        comPlayerProfit.setProfitRatio(_firstRatio);
+        comPlayerProfit.setStealRatio(_firstRatio);
         comPlayerProfit.setFinalRatio(1.0);
         comPlayerProfit.setLossType(lossType);
+
+        comPlayerProfit.setDsasterId(_dsasterId);
+        comPlayerProfit.setAddedPart(landLevelInCome);
+
         ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
         comPlayerProfitService.save(comPlayerProfitVo);
 
@@ -121,7 +131,7 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
 
 
     @Override
-    public ComPlayerProfitVo addOtherDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit, Integer disasterCount) {
+    public ComPlayerProfitVo addOtherDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit, Integer disasterCount,long _dsasterId) {
 
         //对应土地灾害损失
         ComPlayerProfit comPlayerProfit = new ComPlayerProfit();
@@ -140,22 +150,37 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
         Double landLevelInCome = getLandLevelInCome(comPlayerLand, comMallSeedVo.getPriceSnb());
         Integer _profitInt = _otherAmount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
         Double _profit =  DoubleUtil.add(_profitInt.doubleValue(),landLevelInCome);
-        //todo 计算减产,第一次灾难按利润的 50% 减产,两次就是减到 0 了
+        //todo 计算减产,第一次灾难按利润的 100 减产 50,两次就是 50 减到 25
 
         //额外发生的灾难,按照次数计算减产 50% 发生已经发生1次计算后当次等于 25%,
-        double _startRatio = 1.0;
+        double _startRatio = 1;
         for(int i = disasterCount;i>0;i--){
             _startRatio =  DoubleUtil.mul(_startRatio,0.5);
         }
         Double _reduceProfit = DoubleUtil.mul(_profit, _startRatio);
         // 100 - 80 = 20
         Double _residualProfit = DoubleUtil.sub(_profit, allLossProfit);
-        //剩余利润减去当前需要减产的利润值
-        Double _tempProfit = DoubleUtil.sub(_residualProfit, _reduceProfit);
-        if (DoubleUtil.compare(_tempProfit, 0.0).equals(1)) {
-            //还有利润,
-            _endReduceProfit = _reduceProfit;
+        //判断当前是否还存在可减去的利润
+        if(DoubleUtil.compare(_residualProfit,0.0).equals(1)){
+            //存在
+            //剩余利润减去当前需要减产的利润值
+            Double _tempProfit = DoubleUtil.sub(_residualProfit, _reduceProfit);
+            if (DoubleUtil.compare(_tempProfit, 0.0).equals(-1)) {
+                //负数说明全部被扣完
+                _endReduceProfit = _residualProfit;
+
+                //更新一下土地状态为不可偷窃状态
+                comPlayerLand.setPlantSteal(0);
+                comPlayerLandService.save(CopyUtil.copy(comPlayerLand, ComPlayerLandVo.class));
+
+            }else{
+                _endReduceProfit = _reduceProfit;
+            }
         }
+        //else{
+        //    //不存在则默认是0
+        //}
+
 
         comPlayerProfit.setUserId(comPlayerLand.getUserId()); //损失记录的用户id
         comPlayerProfit.setTargetId(comPlayerLand.getUserId()); //目标是自己
@@ -167,13 +192,17 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
         comPlayerProfit.setProfit(_profit);//todo 目标用户可偷的初始利润值
         comPlayerProfit.setStolen(_endReduceProfit);//todo 目标用户被灾害减产对应的数量
         comPlayerProfit.setFinalSteal(_endReduceProfit);//
-        comPlayerProfit.setProfitAfter(DoubleUtil.add(allLossProfit, _endReduceProfit)); //当前损失的利润加上当前扣减的
+        comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(allLossProfit, _endReduceProfit))); //可偷的减去被偷的(包括灾难)
 
         //记录相关比例,损失利润的 _startRatio 相关比例
         comPlayerProfit.setProfitRatio(_startRatio);
         comPlayerProfit.setStealRatio(_startRatio);
         comPlayerProfit.setFinalRatio(1.0);
         comPlayerProfit.setLossType(lossType);
+
+        comPlayerProfit.setDsasterId(_dsasterId);
+        comPlayerProfit.setAddedPart(landLevelInCome);
+
         ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
         comPlayerProfitService.save(comPlayerProfitVo);
 

+ 4 - 0
src/main/java/com/td/boss/game/complayerprofit/vo/ComPlayerProfitVo.java

@@ -40,6 +40,10 @@ public class ComPlayerProfitVo extends PageCondition implements Serializable {
 
     private Integer lossType;//损失的类型,默认是0:被偷取果实,1:自然灾难,2:野兽
 
+    private Long dsasterId;//遭受的攻击id,-1 代表必然灾害
+
+    private Double addedPart;//增值部分
+
     private Date createTime;//
 
     private Date updateTime;//

+ 114 - 28
src/main/java/com/td/boss/game/comsnbapply/controller/ComSnbApplyController.java

@@ -1,5 +1,7 @@
 package com.td.boss.game.comsnbapply.controller;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import com.td.boss.common.controller.*;
 import com.td.boss.common.pojo.PageInfo;
 import com.td.boss.common.pojo.Result;
@@ -11,12 +13,17 @@ import com.td.boss.game.comsnbapply.service.ComSnbApplyService;
 import com.td.boss.game.comusers.pojo.ComUsers;
 import com.td.boss.game.comusers.service.ComUsersService;
 import com.td.boss.game.comusers.vo.ComUsersVo;
+import com.td.boss.util.CopyUtil;
 import com.td.boss.util.DoubleUtil;
+import com.td.boss.util.RedisData;
+import com.td.boss.util.RedisLock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @RestController
 @RequestMapping("/game/comSnbApply/")
@@ -27,6 +34,9 @@ public class ComSnbApplyController extends CommonController<ComSnbApplyVo, ComSn
     @Autowired
     private ComUsersService comUsersService;
 
+    @Autowired
+    private RedisLock redisLock;
+
 
     @GetMapping("getPage")
     public Result<PageInfo<ComSnbApplyVo>> getPageFunction(@RequestParam(value = "userId") String userId,
@@ -38,42 +48,118 @@ public class ComSnbApplyController extends CommonController<ComSnbApplyVo, ComSn
         comSnbApplyVo.setIsState(isState);
         comSnbApplyVo.setPage(page + 1);
         comSnbApplyVo.setRows(limit);
+        comSnbApplyVo.setSidx("desc");
+        comSnbApplyVo.setSord("createTime");
         return comSnbApplyService.page(comSnbApplyVo);
     }
 
+
     @PostMapping("applySnbToCnt")
     public Result<ComSnbApplyVo> applySnbToCntFunction(@RequestParam(value = "userId") String userId,
                                                        @RequestParam(value = "applyAmount") Integer applyAmount) {
-        //判断输入数量,不能为负数
-        if (applyAmount <= 0) {
-            return Result.of(null, false, ResultEnum.APPLY_SNB_AMOUNT_ERROR.getMessage(), ResultEnum.APPLY_SNB_AMOUNT_ERROR.getCode());
-        }
-        // 判断当前是否累加超过当前用户的snb
-        List<ComSnbApply> comSnbApplies = comSnbApplyService.findAllByUserIdAndIsState(userId, 0);
-        for (int i = 0; i < comSnbApplies.size(); i++) {
-            if(applyAmount.equals(comSnbApplies.get(i).getSnb())){
-                return Result.of(null, false, ResultEnum.APPLY_SNB_HAS_APPLY.getMessage(), ResultEnum.APPLY_SNB_HAS_APPLY.getCode());
+        //加个锁
+        String _redisKey = "applySnbToCnt:" + userId;
+        //todo snb冻结加锁
+        long time = System.currentTimeMillis() + RedisData.getUserApplyTimeout();
+
+        try {
+            // 防止重复操作
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                return Result.of(null, false, ResultEnum.REDIS_IS_LOCK.getMessage(), ResultEnum.REDIS_IS_LOCK.getCode());
             }
-        }
-        Integer _applySnb = comSnbApplies.stream().mapToInt(ComSnbApply::getSnb).sum();
-        //加上当前的
-        _applySnb += applyAmount;
-
-        ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
-        double _allSnbDouble = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
-        if (DoubleUtil.compare(_allSnbDouble, _applySnb.doubleValue()).equals(-1)) {
-            return Result.of(null, false, ResultEnum.APPLY_SNB_TOO_MUCH.getMessage(), ResultEnum.APPLY_SNB_TOO_MUCH.getCode());
+
+            //判断输入数量,不能为负数
+            if (applyAmount <= 0) {
+                return Result.of(null, false, ResultEnum.APPLY_SNB_AMOUNT_ERROR.getMessage(), ResultEnum.APPLY_SNB_AMOUNT_ERROR.getCode());
+            }
+            // 判断当前是否累加超过当前用户的snb
+            List<ComSnbApply> comSnbApplies = comSnbApplyService.findAllByUserIdAndIsState(userId, 0);
+            List<ComSnbApply> comSnbApplies2 = comSnbApplyService.findAllByUserIdAndIsState(userId, 1);
+            comSnbApplies2.stream().sequential().collect(Collectors.toCollection(() -> comSnbApplies));
+            //记录一个当前申请的数据
+            List<ComSnbApply> todayComSnbApply = new ArrayList<>();
+            Date now = new Date();
+            DateTime begin = DateUtil.beginOfDay(now);
+            DateTime end = DateUtil.endOfDay(now);
+            for (int i = 0; i < comSnbApplies.size(); i++) {
+                if (applyAmount.equals(comSnbApplies.get(i).getSnb())) {
+                    return Result.of(null, false, ResultEnum.APPLY_SNB_HAS_APPLY.getMessage(), ResultEnum.APPLY_SNB_HAS_APPLY.getCode());
+                }
+                //如果日期在指定范围内
+                if (DateUtil.isIn(comSnbApplies.get(i).getCreateTime(), begin, end)) {
+                    todayComSnbApply.add(comSnbApplies.get(i));
+                }
+            }
+            Integer _applySnb = comSnbApplies.stream().mapToInt(ComSnbApply::getSnb).sum();
+            //加上当前的
+            _applySnb += applyAmount;
+
+            ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+            double _allSnbDouble = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
+            if (DoubleUtil.compare(_allSnbDouble, _applySnb.doubleValue()).equals(-1)) {
+                return Result.of(null, false, ResultEnum.APPLY_SNB_TOO_MUCH.getMessage(), ResultEnum.APPLY_SNB_TOO_MUCH.getCode());
+            }
+
+            ComSnbApplyVo comSnbApplyVo = new ComSnbApplyVo();
+            comSnbApplyVo.setUserId(userId);
+            comSnbApplyVo.setAddress(comUsersVo.getAddress());
+            comSnbApplyVo.setSnb(applyAmount);
+            comSnbApplyVo.setSnbDescribe("applySnbToCnt,发起兑换记录snb!");
+            comSnbApplyVo.setIsState(0);
+            comSnbApplyVo.setCount(todayComSnbApply.size() + 1); //当日申请的次数 + 1
+            comSnbApplyVo.setCreateTime(new Date());
+            comSnbApplyVo.setUpdateTime(new Date());
+
+
+            //保存成功之后,刷新列表
+            return comSnbApplyService.save(comSnbApplyVo);
+        } catch (Exception e) {
+            return Result.of(null, false, ResultEnum.REDIS_IS_LOCK_ERROR.getMessage(), ResultEnum.REDIS_IS_LOCK_ERROR.getCode());
+        } finally {
+            redisLock.unlock(_redisKey, String.valueOf(time));
         }
 
-        ComSnbApplyVo comSnbApplyVo = new ComSnbApplyVo();
-        comSnbApplyVo.setUserId(userId);
-        comSnbApplyVo.setAddress(comUsersVo.getAddress());
-        comSnbApplyVo.setSnb(applyAmount);
-        comSnbApplyVo.setSnbDescribe("applySnbToCnt,发起兑换记录snb!");
-        comSnbApplyVo.setIsState(0);
-        comSnbApplyVo.setCreateTime(new Date());
-        comSnbApplyVo.setUpdateTime(new Date());
-        //保存成功之后,刷新列表
-        return comSnbApplyService.save(comSnbApplyVo);
+
+    }
+
+
+    @PostMapping("checkApplySnbToCnt")
+    public Result<ComSnbApplySimpleVo> checkApplySnbToCntFunction(@RequestParam(value = "userId") String userId,
+                                                                  @RequestParam(value = "certificateId") String certificateId) {
+        //加个锁
+        String _redisKey = "checkApplySnbToCnt:" + userId;
+        //todo snb冻结加锁
+        long time = System.currentTimeMillis() + RedisData.getUserApplyTimeout();
+        try {
+            // 防止重复操作
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                return Result.of(null, false, ResultEnum.REDIS_IS_LOCK.getMessage(), ResultEnum.REDIS_IS_LOCK.getCode());
+            }
+
+            ComSnbApplyVo comSnbApplyVo = comSnbApplyService.get(certificateId).getData();
+            if (!comSnbApplyVo.getIsState().equals(1)) {
+                return Result.of(null, false, ResultEnum.APPLY_SNB_STATE_ERROR.getMessage(), ResultEnum.APPLY_SNB_STATE_ERROR.getCode());
+            }
+            //判断申请的snb
+            if (comSnbApplyVo.getSnb() <= 0) {
+                comSnbApplyVo.setIsState(2);
+                comSnbApplyService.save(comSnbApplyVo);
+                return Result.of(null, false, ResultEnum.APPLY_SNB_AMOUNT_ERROR.getMessage(), ResultEnum.APPLY_SNB_AMOUNT_ERROR.getCode());
+            }
+            ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+            double _allSnbDouble = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
+
+            if (DoubleUtil.compare(_allSnbDouble, 0.0).equals(1) && DoubleUtil.compare(_allSnbDouble, comSnbApplyVo.getSnb().doubleValue()).equals(-1)) {
+                //snb不足时候
+                comSnbApplyVo.setIsState(2);
+                comSnbApplyService.save(comSnbApplyVo);
+                return Result.of(null, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
+            }
+            return Result.of(CopyUtil.copy(comSnbApplyVo, ComSnbApplySimpleVo.class));
+        } catch (Exception e) {
+            return Result.of(null, false, ResultEnum.REDIS_IS_LOCK_ERROR.getMessage(), ResultEnum.REDIS_IS_LOCK_ERROR.getCode());
+        } finally {
+            redisLock.unlock(_redisKey, String.valueOf(time));
+        }
     }
 }

+ 2 - 0
src/main/java/com/td/boss/game/comsnbapply/pojo/ComSnbApply.java

@@ -22,6 +22,8 @@ public class ComSnbApply implements Serializable {
 
     private String snbDescribe;//
 
+    private Integer count;//当天兑换的count
+
     private Date createTime;//
 
     private Date updateTime;//

+ 5 - 3
src/main/java/com/td/boss/game/comsnbapply/scheduled/BackService.java

@@ -60,9 +60,11 @@ public class BackService {
         List<ComSnbApplyVo> comSnbApplyVos = comSnbApplyService.list(getComSnbApplyVo).getData();
         //log.info("审查任务数量:{}个", comSnbApplyVos.size());
         for (ComSnbApplyVo comSnbApplyVo : comSnbApplyVos) {
-            //snb 在[max,min]区间,才能过审
-            if (comSnbApplyVo.getSnb() <= SysSettingTaskUtil.getSysSettingTask().getConditionSnbMax() &&
-                    comSnbApplyVo.getSnb() >= SysSettingTaskUtil.getSysSettingTask().getConditionSnbMin() ) {
+            //1.snb 在[max,min]区间,才能过审 2.如果申请次数不超过限制次数,则过审
+            if (comSnbApplyVo.getSnb() <= SysSettingTaskUtil.getSysSettingTask().getConditionSnbMax()
+                    && comSnbApplyVo.getSnb() >= SysSettingTaskUtil.getSysSettingTask().getConditionSnbMin()
+                    && comSnbApplyVo.getCount() <= SysSettingTaskUtil.getSysSettingTask().getApplyCount()
+            ) {
                 //全部给通过
                 comSnbApplyVo.setIsState(1);
             }

+ 4 - 0
src/main/java/com/td/boss/game/comsnbapply/service/ComSnbApplyService.java

@@ -4,6 +4,7 @@ import com.td.boss.common.service.*;
 import com.td.boss.game.comsnbapply.pojo.ComSnbApply;
 import com.td.boss.game.comsnbapply.vo.ComSnbApplyVo;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 
@@ -19,4 +20,7 @@ public interface ComSnbApplyService extends CommonService<ComSnbApplyVo, ComSnbA
 
     List<ComSnbApply> saveAll(List<ComSnbApply> comSnbApplies);
 
+
+    List<ComSnbApply> getBetweenTimeList(Date begin, Date end);
+
 }

+ 19 - 0
src/main/java/com/td/boss/game/comsnbapply/service/ComSnbApplyServiceImpl.java

@@ -5,10 +5,17 @@ import com.td.boss.game.comsnbapply.pojo.ComSnbApply;
 import com.td.boss.game.comsnbapply.vo.ComSnbApplyVo;
 import com.td.boss.game.comsnbapply.repository.ComSnbApplyRepository;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 @Service
@@ -47,4 +54,16 @@ public class ComSnbApplyServiceImpl extends CommonServiceImpl<ComSnbApplyVo, Com
         return comSnbApplyRepository.saveAll(comSnbApplies);
     }
 
+    @Override
+    public List<ComSnbApply> getBetweenTimeList(Date begin, Date end) {
+        Specification specification = new Specification<ComSnbApply>() {
+            @Override
+            public Predicate toPredicate(Root<ComSnbApply> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
+                List<Predicate> predicates = new ArrayList<>();
+                predicates.add(criteriaBuilder.between(root.get("createTime"), begin, end));
+                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        };
+        return comSnbApplyRepository.findAll(specification);
+    }
 }

+ 16 - 0
src/main/java/com/td/boss/game/comsnbapply/vo/ComSnbApplyBetweenVo.java

@@ -0,0 +1,16 @@
+package com.td.boss.game.comsnbapply.vo;
+
+import com.td.boss.common.pojo.PageCondition;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComSnbApplyBetweenVo implements Serializable {
+
+    private Date beginTime;//
+
+    private Date endTime;//
+
+}

+ 2 - 2
src/main/java/com/td/boss/game/comsnbapply/vo/ComSnbApplySimpleVo.java

@@ -10,14 +10,14 @@ import java.util.Date;
 public class ComSnbApplySimpleVo implements Serializable {
     private String id;//
 
-    private String userId;//
-
     private Integer snb;//游戏的snb
 
     private Integer isState;//0:申请中,1:申请通过,2:申请驳回
 
     private String snbDescribe;//
 
+    private Integer count;//当天兑换的count
+
     private Date createTime;//
 
     private Date updateTime;//

+ 2 - 0
src/main/java/com/td/boss/game/comsnbapply/vo/ComSnbApplyVo.java

@@ -18,6 +18,8 @@ public class ComSnbApplyVo extends PageCondition implements Serializable {
 
     private String snbDescribe;//
 
+    private Integer count;//当天兑换的count
+
     private Date createTime;//
 
     private Date updateTime;//

+ 74 - 29
src/main/java/com/td/boss/game/comsnbfreeze/controller/ComSnbFreezeController.java

@@ -1,6 +1,7 @@
 package com.td.boss.game.comsnbfreeze.controller;
 
 import cn.hutool.core.date.DateField;
+import cn.hutool.json.JSONUtil;
 import com.td.boss.common.controller.*;
 import com.td.boss.common.pojo.Result;
 import com.td.boss.config.enums.ResultEnum;
@@ -19,6 +20,7 @@ import com.td.boss.game.complayergoods.pojo.ComPlayerGoods;
 import com.td.boss.game.complayergoods.service.ComPlayerGoodsService;
 import com.td.boss.game.complayergoods.vo.ComPlayerGoodsSimpleVo;
 import com.td.boss.game.complayergoods.vo.ComPlayerGoodsVo;
+import com.td.boss.game.complayerland.pojo.ComPlayerDisasterProtected;
 import com.td.boss.game.complayerland.pojo.ComPlayerLand;
 import com.td.boss.game.complayerland.service.ComPlayerDisasterProtectedService;
 import com.td.boss.game.complayerland.service.ComPlayerLandService;
@@ -37,10 +39,7 @@ import com.td.boss.game.comsnbtran.service.ComSnbTranService;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import com.td.boss.game.comusers.service.ComUsersService;
 import com.td.boss.game.comusers.vo.ComUsersVo;
-import com.td.boss.util.CopyUtil;
-import com.td.boss.util.DateUtil;
-import com.td.boss.util.RedisData;
-import com.td.boss.util.RedisLock;
+import com.td.boss.util.*;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -90,6 +89,8 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
 
     @Autowired
     private ComMallOtherService comMallOtherService;
+    @Autowired
+    private ComPlayerDisasterProtectedService disasterProtectedService;
 
 
     /**
@@ -134,13 +135,13 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
             //return Result.of(map, false, ResultEnum.WALLET_SNB_SIGN_ERROR.getMessage(), ResultEnum.WALLET_SNB_SIGN_ERROR.getCode());
             return Result.of(map);
         }
-        if(snbAmount <= 0){
+        if (snbAmount <= 0) {
             map.put("msg", "snb小于等于0,记录异常!");
             return Result.of(map);
         }
         //todo 新增一个判断当前交易是否存在对应snb通过审核的
-        ComSnbApply comSnbApply = comSnbApplyService.findByUserIdAndSnbAndIsState(id.toString(),snbAmount,1);
-        if(comSnbApply == null){
+        ComSnbApply comSnbApply = comSnbApplyService.findByUserIdAndSnbAndIsState(id.toString(), snbAmount, 1);
+        if (comSnbApply == null) {
             comSnbApply.setIsState(2);
             comSnbApplyService.save(CopyUtil.copy(comSnbApply, ComSnbApplyVo.class));
             map.put("msg", "此交易未通过审核,返回给用户账户待用户提交审核");
@@ -247,7 +248,7 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
         }
 
         ComSnbFreezeVo comSnbFreezeVo = comSnbFreezeService.findById(snbId);
-        if(comSnbFreezeVo.getSnb()<=0){
+        if (comSnbFreezeVo.getSnb() <= 0) {
             map.put("msg", "snb是小于0?");
             return Result.of(map);
         }
@@ -373,11 +374,11 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
             comCntOrderVo.setPayType(pay_type);
             comCntOrderVo.setTxHash(tx_hash);
 
-            if (Double.parseDouble(pay_amount) <= 0) {
+            if (DoubleUtil.compare(Double.parseDouble(pay_amount), 0d).equals(-1)) {
                 comCntOrderVo.setCntDescribe("非法操作pay_amount CNT:" + pay_amount);
                 comCntOrderService.save(comCntOrderVo);
                 result.put("msg", "非法操作!");
-                 return Result.of(result);
+                return Result.of(result);
             }
 
             if (comCntOrderVo.getPayType().equals(1) //3个月
@@ -495,13 +496,13 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
             } else if (comCntOrderVo.getPayType().equals(2)) {
                 //获取当前防护包价格,判断
                 ComMallOther comMallOther = comMallOtherService.findByOtherType(2);
-                if(comMallOther == null){
+                if (comMallOther == null) {
                     comCntOrderVo.setCntDescribe("非法操作 comMallOther is null");
                     comCntOrderService.save(comCntOrderVo);
                     result.put("msg", "商品不存在!");
                     return Result.of(result);
                 }
-                if(!comMallOther.getPriceCnt().equals(pay_amount)){
+                if (!comMallOther.getPriceCnt().equals(Integer.parseInt(pay_amount))) {
                     comCntOrderVo.setCntDescribe("非法操作 pay_amount !");
                     comCntOrderService.save(comCntOrderVo);
                     result.put("msg", "pay_amount error!");
@@ -509,24 +510,44 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
                 }
                 comCntOrderVo.setCntDescribe("自然灾害防护");
                 // todo 每购买一次防护,插入一条记录 ?
-                ComPlayerDisasterProtectedVo comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
-                comPlayerDisasterProtected.setCreateTime(new Date());
-                comPlayerDisasterProtected.setUserId(id.toString());
-                comPlayerDisasterProtected.setDsasterType(ComPlayerDisasterEnum.ziran.getCode());
-                comPlayerDisasterProtected.setDsasterName(ComPlayerDisasterEnum.ziran.getMsg());
-                comPlayerDisasterProtected.setProtectTime(cn.hutool.core.date.DateUtil.date(new Date()).offset(DateField.DAY_OF_WEEK, 30));
-                comPlayerDisasterProtectedService.save(comPlayerDisasterProtected);
+                List<ComPlayerDisasterProtected> protectList = disasterProtectedService.getComPlayerDisasterProtectedByUserIdOrderByProtectTimeDesc(id.toString());
+                log.info("用户编号:{},防护历史记录:{}", id.toString(), JSONUtil.toJsonStr(protectList));
+                //获得对应灾难类型的防护记录    并得到这个 防护到期时间
+                ComPlayerDisasterProtected _disasterProtected = protectList.stream()
+                        .filter(a -> a.getDsasterType().equals(2))
+                        .sorted(Comparator.comparing(ComPlayerDisasterProtected::getProtectTime).reversed())
+                        .findFirst().orElse(null);
+                Date now = new Date();
+                if(_disasterProtected == null || now.after(_disasterProtected.getProtectTime())){
+                    //如果不存在或者过期
+                    ComPlayerDisasterProtectedVo comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
+                    comPlayerDisasterProtected.setCreateTime(now);
+                    comPlayerDisasterProtected.setUserId(id.toString());
+                    comPlayerDisasterProtected.setDsasterType(ComPlayerDisasterEnum.ziran.getCode());
+                    comPlayerDisasterProtected.setDsasterName(ComPlayerDisasterEnum.ziran.getMsg());
+                    comPlayerDisasterProtected.setProtectTime(DateUtil.getOldDateAddDay(now,comMallOther.getEffectiveDay()));
+                    comPlayerDisasterProtectedService.save(comPlayerDisasterProtected);
+                } else {
+                    //存在还未过期,把时间叠加到新的数据上面去
+                    ComPlayerDisasterProtectedVo comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
+                    comPlayerDisasterProtected.setCreateTime(now);
+                    comPlayerDisasterProtected.setUserId(id.toString());
+                    comPlayerDisasterProtected.setDsasterType(ComPlayerDisasterEnum.ziran.getCode());
+                    comPlayerDisasterProtected.setDsasterName(ComPlayerDisasterEnum.ziran.getMsg());
+                    comPlayerDisasterProtected.setProtectTime(DateUtil.getOldDateAddDay(_disasterProtected.getProtectTime(),comMallOther.getEffectiveDay()));
+                    comPlayerDisasterProtectedService.save(comPlayerDisasterProtected);
+                }
 
             } else if (comCntOrderVo.getPayType().equals(3)) {
                 //获取当前防护包价格,判断
                 ComMallOther comMallOther = comMallOtherService.findByOtherType(3);
-                if(comMallOther == null){
+                if (comMallOther == null) {
                     comCntOrderVo.setCntDescribe("非法操作 comMallOther is null");
                     comCntOrderService.save(comCntOrderVo);
                     result.put("msg", "商品不存在!");
                     return Result.of(result);
                 }
-                if(!comMallOther.getPriceCnt().equals(pay_amount)){
+                if (!comMallOther.getPriceCnt().equals(Integer.parseInt(pay_amount))) {
                     comCntOrderVo.setCntDescribe("非法操作 pay_amount !");
                     comCntOrderService.save(comCntOrderVo);
                     result.put("msg", "pay_amount error!");
@@ -534,14 +555,38 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
                 }
                 comCntOrderVo.setCntDescribe("野兽防护");
                 // todo 每购买一次防护,插入一条记录 ?
-                ComPlayerDisasterProtectedVo comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
-                comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
-                comPlayerDisasterProtected.setCreateTime(new Date());
-                comPlayerDisasterProtected.setUserId(id.toString());
-                comPlayerDisasterProtected.setDsasterType(ComPlayerDisasterEnum.yeshou.getCode());
-                comPlayerDisasterProtected.setDsasterName(ComPlayerDisasterEnum.yeshou.getMsg());
-                comPlayerDisasterProtected.setProtectTime(cn.hutool.core.date.DateUtil.date(new Date()).offset(DateField.DAY_OF_WEEK, -30));
-                comPlayerDisasterProtectedService.save(comPlayerDisasterProtected);
+                List<ComPlayerDisasterProtected> protectList = disasterProtectedService.getComPlayerDisasterProtectedByUserIdOrderByProtectTimeDesc(id.toString());
+                log.info("用户编号:{},防护历史记录:{}", id.toString(), JSONUtil.toJsonStr(protectList));
+                //获得对应灾难类型的防护记录    并得到这个 防护到期时间
+                ComPlayerDisasterProtected _disasterProtected = protectList.stream()
+                        .filter(a -> a.getDsasterType().equals(3))
+                        .sorted(Comparator.comparing(ComPlayerDisasterProtected::getProtectTime).reversed())
+                        .findFirst().orElse(null);
+                Date now = new Date();
+                if(_disasterProtected == null || now.after(_disasterProtected.getProtectTime())){
+                    //如果不存在或者过期
+                    ComPlayerDisasterProtectedVo comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
+                    comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
+                    comPlayerDisasterProtected.setCreateTime(now);
+                    comPlayerDisasterProtected.setUserId(id.toString());
+                    comPlayerDisasterProtected.setDsasterType(ComPlayerDisasterEnum.yeshou.getCode());
+                    comPlayerDisasterProtected.setDsasterName(ComPlayerDisasterEnum.yeshou.getMsg());
+                    comPlayerDisasterProtected.setProtectTime(DateUtil.getOldDateAddDay(now,comMallOther.getEffectiveDay()));
+                    comPlayerDisasterProtectedService.save(comPlayerDisasterProtected);
+
+                } else {
+                    //存在还未过期,把时间叠加到新的数据上面去
+                    ComPlayerDisasterProtectedVo comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
+                    comPlayerDisasterProtected = new ComPlayerDisasterProtectedVo();
+                    comPlayerDisasterProtected.setCreateTime(now);
+                    comPlayerDisasterProtected.setUserId(id.toString());
+                    comPlayerDisasterProtected.setDsasterType(ComPlayerDisasterEnum.yeshou.getCode());
+                    comPlayerDisasterProtected.setDsasterName(ComPlayerDisasterEnum.yeshou.getMsg());
+                    comPlayerDisasterProtected.setProtectTime(DateUtil.getOldDateAddDay(_disasterProtected.getProtectTime(),comMallOther.getEffectiveDay()));
+                    comPlayerDisasterProtectedService.save(comPlayerDisasterProtected);
+
+                }
+
             } else if (comCntOrderVo.getPayType().equals(4)) {
 
                 // 验证种子价格是否和服务器一样,不一样判定非法操作

+ 6 - 2
src/main/java/com/td/boss/game/comsnbtran/repository/ComSnbTranRepository.java

@@ -2,6 +2,7 @@ package com.td.boss.game.comsnbtran.repository;
 
 import com.td.boss.common.repository.*;
 import com.td.boss.game.comsnbtran.pojo.ComSnbTran;
+import com.td.boss.game.comsnbtran.vo.ComSnbTranAbnormalVo;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
@@ -21,15 +22,18 @@ public interface ComSnbTranRepository extends CommonRepository<ComSnbTran, Strin
      * 返回一个降序的pay_type 统计
      * @return
      */
-    @Query(value = "SELECT new com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo(u.tranType,sum(u.tranSnb)) from ComSnbTran u GROUP BY u.tranType ORDER BY sum(u.tranSnb) desc", nativeQuery = false)
+    @Query(value = "SELECT new com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo(u.tranType,sum(u.tranSnb+u.tranSnbPart)) from ComSnbTran u GROUP BY u.tranType ORDER BY sum(u.tranSnb + u.tranSnbPart) desc", nativeQuery = false)
     List<ComSnbTranTranTypeSumVo> findSnbSumByTranType();
 
+
+    @Query(value = "SELECT new com.td.boss.game.comsnbtran.vo.ComSnbTranAbnormalVo(u.userId,max(u.tranPrice),u.createTime) from ComSnbTran  as u WHERE u.tranPrice <0 GROUP BY u.tranPrice", nativeQuery = false)
+    List<ComSnbTranAbnormalVo> findSnbAbnormalData();
     /**
      * 根据开始结束时间获取payType 统计数据
      * @param startTime
      * @param endTime
      * @return
      */
-    @Query(value = "SELECT new com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo(u.tranType,sum(u.tranSnb)) FROM  ComSnbTran u  where u.createTime >= :startTime and u.createTime<= :endTime GROUP BY u.tranType ORDER BY sum(u.tranSnb) desc")
+    @Query(value = "SELECT new com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo(u.tranType,sum(u.tranSnb+u.tranSnbPart)) FROM  ComSnbTran u  where u.createTime >= :startTime and u.createTime<= :endTime GROUP BY u.tranType ORDER BY sum(u.tranSnb+u.tranSnbPart) desc")
     List<ComSnbTranTranTypeSumVo> findCNTSumByPayTypeFromDate(Date startTime, Date endTime);
 }

+ 2 - 0
src/main/java/com/td/boss/game/comsnbtran/service/ComSnbTranService.java

@@ -3,6 +3,7 @@ package com.td.boss.game.comsnbtran.service;
 import com.td.boss.common.service.*;
 import com.td.boss.game.comcntorder.vo.ComCntOrderPayTypeSumVo;
 import com.td.boss.game.comsnbtran.pojo.ComSnbTran;
+import com.td.boss.game.comsnbtran.vo.ComSnbTranAbnormalVo;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import org.springframework.data.domain.Page;
@@ -17,6 +18,7 @@ public interface ComSnbTranService extends CommonService<ComSnbTranVo, ComSnbTra
 
     List<ComSnbTranTranTypeSumVo> findAllSNBSumGroupByPayType();
 
+    List<ComSnbTranAbnormalVo> findAllComSnbTranAbnormal();
 
     //按日期返回一个snb消费记录
     List<ComSnbTranTranTypeSumVo> findAllSNBSumGroupByPayTypeFromDate(Date startTime, Date endTime);

+ 6 - 0
src/main/java/com/td/boss/game/comsnbtran/service/ComSnbTranServiceImpl.java

@@ -3,6 +3,7 @@ package com.td.boss.game.comsnbtran.service;
 import com.td.boss.common.service.*;
 import com.td.boss.game.comcntorder.vo.ComCntOrderPayTypeSumVo;
 import com.td.boss.game.comsnbtran.pojo.ComSnbTran;
+import com.td.boss.game.comsnbtran.vo.ComSnbTranAbnormalVo;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import com.td.boss.game.comsnbtran.repository.ComSnbTranRepository;
@@ -37,6 +38,11 @@ public class ComSnbTranServiceImpl extends CommonServiceImpl<ComSnbTranVo, ComSn
         return comSnbTranRepository.findSnbSumByTranType();
     }
 
+    @Override
+    public List<ComSnbTranAbnormalVo> findAllComSnbTranAbnormal() {
+        return comSnbTranRepository.findSnbAbnormalData();
+    }
+
     @Override
     public List<ComSnbTranTranTypeSumVo> findAllSNBSumGroupByPayTypeFromDate(Date startTime, Date endTime) {
         return comSnbTranRepository.findCNTSumByPayTypeFromDate(startTime, endTime);

+ 27 - 0
src/main/java/com/td/boss/game/comsnbtran/vo/ComSnbTranAbnormalVo.java

@@ -0,0 +1,27 @@
+package com.td.boss.game.comsnbtran.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2022/1/25
+ */
+@Getter
+@Setter
+@ToString
+public class ComSnbTranAbnormalVo {
+    private String userId;
+    private Integer tranPrice;
+    private Date createTime;
+    //user_id, max(tran_price),create_time
+    public ComSnbTranAbnormalVo(String userId, Integer tranPrice,Date createTime) {
+        this.userId = userId;
+        this.tranPrice = tranPrice;
+        this.createTime = createTime;
+    }
+
+}

+ 2 - 2
src/main/java/com/td/boss/game/comsnbtran/vo/ComSnbTranTranTypeSumVo.java

@@ -13,9 +13,9 @@ import lombok.ToString;
 @ToString
 public class ComSnbTranTranTypeSumVo {
     private Integer tranType;
-    private Long snbSum;
+    private Double snbSum;
 
-    public ComSnbTranTranTypeSumVo(Integer tranType, Long snbSum) {
+    public ComSnbTranTranTypeSumVo(Integer tranType, Double snbSum) {
         this.tranType = tranType;
         this.snbSum = snbSum;
     }

+ 66 - 5
src/main/java/com/td/boss/sys/sysGame/controller/sysGamePropertyController.java

@@ -3,12 +3,16 @@ package com.td.boss.sys.sysGame.controller;
 import com.td.boss.annotation.Decrypt;
 import com.td.boss.annotation.Encrypt;
 import com.td.boss.common.controller.CommonController;
+import com.td.boss.common.pojo.PageCondition;
 import com.td.boss.common.pojo.PageInfo;
 import com.td.boss.common.pojo.Result;
 import com.td.boss.game.comcntorder.service.ComCntOrderService;
 import com.td.boss.game.comcntorder.vo.ComCntOrderDateVo;
 import com.td.boss.game.comcntorder.vo.ComCntOrderPayTypeSumVo;
 import com.td.boss.game.comcntorder.vo.ComCntOrderVo;
+import com.td.boss.game.comcnttosnb.pojo.ComCntToSnb;
+import com.td.boss.game.comcnttosnb.service.ComCntToSnbService;
+import com.td.boss.game.comcnttosnb.vo.ComCntToSnbVo;
 import com.td.boss.game.comconfigland.pojo.ComConfigLand;
 import com.td.boss.game.comconfigland.service.ComConfigLandService;
 import com.td.boss.game.comconfigland.vo.ComConfigLandVo;
@@ -22,8 +26,10 @@ import com.td.boss.game.complayergoods.service.ComPlayerGoodsService;
 import com.td.boss.game.complayergoods.vo.ComPlayerGoodsTypeSumVo;
 import com.td.boss.game.comsnbapply.pojo.ComSnbApply;
 import com.td.boss.game.comsnbapply.service.ComSnbApplyService;
+import com.td.boss.game.comsnbapply.vo.ComSnbApplyBetweenVo;
 import com.td.boss.game.comsnbapply.vo.ComSnbApplyVo;
 import com.td.boss.game.comsnbtran.service.ComSnbTranService;
+import com.td.boss.game.comsnbtran.vo.ComSnbTranAbnormalVo;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranDateVo;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranTranTypeSumVo;
 import com.td.boss.game.comusers.pojo.ComUsers;
@@ -39,6 +45,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.servlet.ModelAndView;
 
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 
 @Slf4j
@@ -70,6 +77,9 @@ public class sysGamePropertyController extends CommonController<ComUsersVo, ComU
     @Autowired
     private ComSnbApplyService comSnbApplyService;
 
+    @Autowired
+    private ComCntToSnbService comCntToSnbService;
+
 
     @GetMapping("CNTAndSNB")
     public ModelAndView CNTAndSNB() {
@@ -122,6 +132,21 @@ public class sysGamePropertyController extends CommonController<ComUsersVo, ComU
         return Result.of(pageInfo);
     }
 
+
+    @PostMapping("findAllSNBErrorInfo")
+    @Decrypt
+    @Encrypt
+    public Result<PageInfo<ComSnbTranAbnormalVo>> findAllSNBErrorInfo(ComCntOrderVo comCntOrderVo) {
+        List<ComSnbTranAbnormalVo> comSnbTranTranTypeSumVoList = comSnbTranService.findAllComSnbTranAbnormal();
+        PageInfo<ComSnbTranAbnormalVo> pageInfo = new PageInfo<>();
+        pageInfo.setPage(1);//页码
+        pageInfo.setPageSize(5);//页面大小
+        pageInfo.setRows(comSnbTranTranTypeSumVoList);//分页结果
+        pageInfo.setRecords(comSnbTranTranTypeSumVoList.size());//总记录数
+        pageInfo.setTotal(1);//总页数
+        return Result.of(pageInfo);
+    }
+
     @PostMapping("findAllSNBSumGroupByPayTypeFromDate")
     @Decrypt
     @Encrypt
@@ -240,12 +265,14 @@ public class sysGamePropertyController extends CommonController<ComUsersVo, ComU
         return comFruitService.save(comFruitVo);
     }
 
-
+    /**
+     * 审核SNB部分
+     */
     @GetMapping("applySnbToCntView")
     public ModelAndView usersApplySnbToCnt() {
         ModelAndView modelAndView = new ModelAndView("sys/aComApplySNBToCNT/applySNBToCNT", "sysSettingTask",
                 SysSettingTaskUtil.getSysSettingTask());
-        modelAndView.getModelMap().addAttribute("applyState",0);
+        modelAndView.getModelMap().addAttribute("applyState", 0);
         return modelAndView;
     }
 
@@ -262,6 +289,7 @@ public class sysGamePropertyController extends CommonController<ComUsersVo, ComU
     @Decrypt
     @Encrypt
     public Result<ComSnbApplyVo> updateApplySnbToCntData(ComSnbApplyVo comSnbApplyVo) {
+        comSnbApplyVo.setUpdateTime(new Date());
         return comSnbApplyService.save(comSnbApplyVo);
     }
 
@@ -272,11 +300,44 @@ public class sysGamePropertyController extends CommonController<ComUsersVo, ComU
         //再保存新的
         List<ComSnbApply> comSnbApplies = comSnbApplyService.findAllByIn(Arrays.asList(sysApplySNBToCNTVo.getApplyIdList().split(",")));
         for (ComSnbApply comSnbApply : comSnbApplies) {
-           if(!comSnbApply.getIsState().equals(3)){
-               comSnbApply.setIsState(sysApplySNBToCNTVo.getIsState());
-           }
+            if (!comSnbApply.getIsState().equals(3)) {
+                comSnbApply.setIsState(sysApplySNBToCNTVo.getIsState());
+                comSnbApply.setUpdateTime(new Date());
+            }
         }
         comSnbApplyService.saveAll(comSnbApplies);
         return Result.of("success");
     }
+
+    @PostMapping("findBetweenApplySnbToCntDataPage")
+    @Decrypt
+    @Encrypt
+    public Result<List<ComSnbApplyVo>> findBetweenApplySnbToCntDataPage(ComSnbApplyBetweenVo comSnbApplyBetweenVo) {
+        List<ComSnbApplyVo> comSnbApplyVoList = CopyUtil.copyList(comSnbApplyService.getBetweenTimeList(comSnbApplyBetweenVo.getBeginTime(), comSnbApplyBetweenVo.getEndTime()), ComSnbApplyVo.class);
+        return Result.of(comSnbApplyVoList);
+    }
+
+
+    //领取snb页面
+    @GetMapping("comCntToSnbView")
+    public ModelAndView comCntToSnbView() {
+        ModelAndView modelAndView = new ModelAndView("sys/aComCntToSnb/aComCntToSnb");
+        return modelAndView;
+    }
+
+    @PostMapping("findComCntToSnbPage")
+    @Decrypt
+    @Encrypt
+    public Result<PageInfo<ComCntToSnbVo>> findComCntToSnbPage(ComCntToSnbVo comCntToSnbVo) {
+        return comCntToSnbService.page(comCntToSnbVo);
+    }
+
+    @PostMapping("findBetweenComCntToSnbPage")
+    @Decrypt
+    @Encrypt
+    public Result<List<ComCntToSnb>> findBetweenComCntToSnbPage(
+            @RequestParam(value = "beginTime") Date beginTime,
+            @RequestParam(value = "endTime") Date endTime) {
+        return Result.of(comCntToSnbService.getBetweenTimeList(beginTime, endTime));
+    }
 }

+ 2 - 0
src/main/java/com/td/boss/sys/syssettingtask/pojo/SysSettingTask.java

@@ -18,6 +18,8 @@ public class SysSettingTask implements Serializable {
 
     private Integer conditionSnbMin;//自动过审时候限制snb条件,最小值
 
+    private Integer applyCount;//当天的提现次数
+
     private Date createTime;//创建时间
 
     private Date updateTime;//修改时间

+ 2 - 0
src/main/java/com/td/boss/sys/syssettingtask/vo/SysSettingTaskVo.java

@@ -14,6 +14,8 @@ public class SysSettingTaskVo extends PageCondition implements Serializable {
 
     private Integer conditionSnbMin;//自动过审时候限制snb条件,最小值
 
+    private Integer applyCount;//当天的提现次数
+
     private Date createTime;//创建时间
 
     private Date updateTime;//修改时间

+ 10 - 2
src/main/java/com/td/boss/util/RedisData.java

@@ -32,9 +32,9 @@ public class RedisData {
     }
 
     /**
-     * 60s 第一次触发灾难锁
+     * 10s 第一次触发灾难锁
      */
-    private static final int PLAYER_DISASTERS_FIRST_TIMEOUT = 60 * 1000; //超时时间 60s
+    private static final int PLAYER_DISASTERS_FIRST_TIMEOUT = 10 * 1000; //超时时间 10s
     public static int getPlayerDisastersFirstTimeout() {
         return PLAYER_DISASTERS_FIRST_TIMEOUT;
     }
@@ -83,4 +83,12 @@ public class RedisData {
     public static int getAutoApplyTimeout () {
         return AUTO_APPLY_TIMEOUT;
     }
+
+    /**
+     * 20s 用户申请锁
+     */
+    private static final int USER_APPLY_TIMEOUT = 1000 * 20;
+    public static int getUserApplyTimeout () {
+        return USER_APPLY_TIMEOUT;
+    }
 }

+ 1 - 1
src/main/resources/application.yml

@@ -77,7 +77,7 @@ captcha:
   enable: false
 
 apply:
-  ip: 192.168.0.109
+  ip:  "" #183.52.205.93
 
 ---
 ##### dev 配置 #######

+ 47 - 2
src/main/resources/static/sys/aComApplySNBToCNT/js/applySNBToCNT.js

@@ -22,7 +22,7 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
             , limitName: 'rows' //每页数据量的参数名,默认:limit
         }
         , where: {
-            isState: applyState
+            isState: applyState, sidx: "desc", sord: "createTime"
         }
         , response: {
             statusName: 'flag' //规定数据状态的字段名称,默认:code
@@ -68,6 +68,7 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
                 , {field: 'address', title: '用户address'}
                 , {field: 'snb', title: '申请的Snb', sort: true}
                 , {field: 'snbDescribe', title: '描述'}
+                , {field: 'count',title:'申请下标'}
                 , {field: 'createTime', title: '创建时间', sort: true}
                 , {field: 'updateTime', title: '更新时间', sort: true}
                 , {fixed: 'right', title: '操作', toolbar: '#barDemo', width: 150}
@@ -76,6 +77,7 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
         , page: true
         , height: height
         , cellMinWidth: 80
+        , autoSort: false
     });
 
 
@@ -227,9 +229,34 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
                 }
             });
 
+        },
+
+        exports: function () {
+            $.post(ctx + "/sys/sysProperty/findBetweenApplySnbToCntDataPage", {
+                beginTime: commonUtil.parseTime(startDate),
+                endTime: commonUtil.parseTime(endDate)
+            }, function (res) {
+                // console.log(res);
+                table.exportFile(tableApplySNBToCNT.config.id,res.data,'xls');
+            });
         }
     };
 
+    laydate.render({
+        elem: '#cntDate'
+        , type: 'datetime'
+        , value: commonUtil.parseTime(startDate) + ' - ' + commonUtil.parseTime(endDate)
+        , isInitValue: true
+        , range: true
+        , done: function (_value, _date, _endDate) {
+            // console.log(_value, _date, _endDate)
+            let _array = _value.split(' - ');
+            startDate = _array[0];
+            endDate = _array[1];
+            // console.log(startDate, endDate)
+        }
+    });
+
     $('.addressTable .layui-btn').on('click', function () {
         let type = $(this).data('type');
         active[type] ? active[type].call(this) : '';
@@ -250,6 +277,23 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
             , url: ctx + "/sys/sysProperty/findApplySnbToCntPage"
             , where: {
                 isState: data.index
+            } , done: function (res, curr, count) {
+                console.log(applyState)
+
+                // if(0 === applyState){
+                //     $('.layuibtn1').css("display","inline-block");
+                //     $('.layuibtn2').css("display","inline-block");
+                //     $('.layuibtn3').css("display","inline-block");
+                //     $('.layuibtn4').css("display","inline-block");
+                //     $('.layuibtn5').css("display","inline-block");
+                // }else{
+                //
+                //     $('.layuibtn1').css("display","inline-block");
+                //     $('.layuibtn2').css("display","none");
+                //     $('.layuibtn3').css("display","none");
+                //     $('.layuibtn4').css("display","none");
+                //     $('.layuibtn5').css("display","none");
+                // }
             }
         });
     });
@@ -284,4 +328,5 @@ function sysSettingTaskFormSave() {
         $("#sysSettingTaskForm").form(data.data);
         $("#applyAutoExamine").val(data.data.applyAutoExamine)
     });
-}
+}
+

+ 101 - 10
src/main/resources/static/sys/aComCNTAndSNB/js/CNTAndSNB.js

@@ -2,6 +2,7 @@ let tableSumCNT;
 let tableDateSumCNT;
 let tableSumSNB;
 let tableDateSumSNB;
+let tableErrorSNB;
 let tree;
 let startDate = new Date(new Date(new Date().toLocaleDateString()).getTime()),
     endDate = new Date(new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1);
@@ -51,6 +52,10 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
                         return '<span style="color: red">土地租赁</span>';
                     } else if (d.payType == 4) {
                         return '<span style="color: red">购买种子</span>';
+                    } else if (d.payType == 2) {
+                        return '<span style="color: red">自然灾害防护</span>';
+                    } else if (d.payType == 3) {
+                        return '<span style="color: red">野兽灾害防护</span>';
                     } else {
                         return '待添加:' + d.payType;
                     }
@@ -105,6 +110,10 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
                         return '<span style="color: red">土地租赁</span>';
                     } else if (d.payType == 4) {
                         return '<span style="color: red">购买种子</span>';
+                    } else if (d.payType == 2) {
+                        return '<span style="color: red">自然灾害防护</span>';
+                    } else if (d.payType == 3) {
+                        return '<span style="color: red">野兽灾害防护</span>';
                     } else {
                         return '待添加:' + d.payType;
                     }
@@ -152,16 +161,29 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
         , cols: [[
             {
                 field: 'tranType', title: '交易类型', templet: function (d) {
-                    if (d.tranType == 3) {  // 自定义内容
-                        return '<span style="color: red">购买种子</span>';
-                    } else if (d.tranType == 0) {
-                        return '<span style="color: green">出售水果</span>';
+
+                    if (d.tranType == 0) {  // 自定义内容
+                        return '<span style="color: green">出售果实</span>';
                     } else if (d.tranType == 1) {
                         return '<span style="color: red">SNB兑换CNT冻结</span>';
                     } else if (d.tranType == 2) {
                         return '<span style="color: green">SNB兑换CNT解冻</span>';
+                    } else if (d.tranType == 3) {
+                        return '<span style="color: red">购买种子</span>';
+                    } else if (d.tranType == 4) {
+                        return '<span style="color: red">偷取果实</span>';
+                    } else if (d.tranType == 5) {
+                        return '<span style="color: red">购买装备</span>';
+                    } else if (d.tranType == 6) {
+                        return '<span style="color: red">购买装备</span>';
+                    } else if (d.tranType == 7) {
+                        return '<span style="color: red">购买狗粮</span>';
+                    } else if (d.tranType == 8) {
+                        return '<span style="color: red">释放SNB</span>';
+                    } else if (d.tranType == 9) {
+                        return '<span style="color: red">幸运值</span>';
                     } else {
-                        return '待添加:' + d.payType;
+                        return '<span style="color: red">待添加:</span>' + d.tranType;
                     }
                 }
             }
@@ -210,16 +232,28 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
         , cols: [
             [{
                 field: 'tranType', title: '交易类型', templet: function (d) {
-                    if (d.tranType == 3) {  // 自定义内容
-                        return '<span style="color: red">购买种子</span>';
-                    } else if (d.tranType == 0) {
-                        return '<span style="color: green">出售水果</span>';
+                    if (d.tranType == 0) {  // 自定义内容
+                        return '<span style="color: green">出售果实</span>';
                     } else if (d.tranType == 1) {
                         return '<span style="color: red">SNB兑换CNT冻结</span>';
                     } else if (d.tranType == 2) {
                         return '<span style="color: green">SNB兑换CNT解冻</span>';
+                    } else if (d.tranType == 3) {
+                        return '<span style="color: red">购买种子</span>';
+                    } else if (d.tranType == 4) {
+                        return '<span style="color: red">偷取果实</span>';
+                    } else if (d.tranType == 5) {
+                        return '<span style="color: red">购买装备</span>';
+                    } else if (d.tranType == 6) {
+                        return '<span style="color: red">购买装备</span>';
+                    } else if (d.tranType == 7) {
+                        return '<span style="color: red">购买狗粮</span>';
+                    } else if (d.tranType == 8) {
+                        return '<span style="color: red">释放SNB</span>';
+                    } else if (d.tranType == 9) {
+                        return '<span style="color: red">幸运值</span>';
                     } else {
-                        return '待添加:' + d.payType;
+                        return '<span style="color: red">待添加:</span>' + d.tranType;
                     }
                 }
             }
@@ -231,6 +265,46 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
         , cellMinWidth: 80
     });
 
+    tableErrorSNB = table.render({
+        elem: '#snbErrorTable'
+        , url: ctx + "/sys/sysProperty/findAllSNBErrorInfo"
+        , method: 'POST'
+        //请求前参数处理
+        , request: {
+            pageName: 'page' //页码的参数名称,默认:page
+            , limitName: 'rows' //每页数据量的参数名,默认:limit
+        }
+        , response: {
+            statusName: 'flag' //规定数据状态的字段名称,默认:code
+            , statusCode: true //规定成功的状态码,默认:0
+            , msgName: 'msg' //规定状态信息的字段名称,默认:msg
+            , countName: 'records' //规定数据总数的字段名称,默认:count
+            , dataName: 'rows' //规定数据列表的字段名称,默认:data
+        }
+        //响应后数据处理
+        , parseData: function (res) { //res 即为原始返回的数据
+            var data = res.data;
+            // console.log("返回的地址数据:", data);
+            //这里应该是反回一个用户,后台做成了页面数据。但是只带一条数据
+            return {
+                "flag": res.flag, //解析接口状态
+                "msg": res.msg, //解析提示文本
+                "records": data.records, //解析数据长度
+                "rows": data.rows //解析数据列表
+            };
+        }
+        , toolbar: '#snbErrorTableToolbarDemo'
+        , title: 'SNB异常消费统计'
+        , cols: [[
+            {field: 'userId', title: '用户id'}
+            , {field: 'tranPrice', title: '交易金额'}
+            , {field: 'createTime', title: '交易时间'}
+        ]]
+        , defaultToolbar: ['', 'exports', 'print']
+        , page: false
+        , height: height
+        , cellMinWidth: 80
+    });
 
     //头工具栏事件
     table.on('toolbar(test)', function (obj) {
@@ -238,6 +312,9 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
             case 'snbReload':
                 sumSnbReload();
                 break;
+            case 'snbErrorReload':
+                sumErrorSnbReload();
+                break;
             case 'cntReload':
                 sumCntReload();
                 break;
@@ -297,6 +374,20 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
 
 function sumSnbReload() {
     tableSumSNB.reload({
+        page: false
+        , method: 'POST'
+        , url: ctx + "/sys/sysProperty/findAllSNBErrorInfo"
+        , done: function (res, curr, count) {
+            // console.log(res, curr, count);
+            //this.where={};
+            //不清空,有问题:搜索条件会保留
+            //清空,  有问题:分页的时候没有搜索条件了,分页会受到影响
+        }
+    });
+}
+
+function  sumErrorSnbReload() {
+    tableErrorSNB.reload({
         page: false
         , method: 'POST'
         , url: ctx + "/sys/sysProperty/findAllSNBGroupByPayType"

+ 22 - 0
src/main/resources/static/sys/aComCntToSnb/aComCntToSnb.css

@@ -0,0 +1,22 @@
+body {
+    padding: 20px;
+    background-color: #F2F2F2;
+}
+
+.layui-form-label {
+    width: 120px !important;
+}
+
+.layui-input-block {
+    display: -webkit-box !important;
+}
+
+.layui-table-tool-temp {
+    padding-right: 0;
+}
+
+#queryByLoginName {
+    display: unset;
+    width: 100px;
+    margin-left: 10px;
+}

+ 132 - 0
src/main/resources/static/sys/aComCntToSnb/aComCntToSnb.js

@@ -0,0 +1,132 @@
+let tableCTB;
+let tree;
+let startDate = new Date(new Date(new Date().toLocaleDateString()).getTime()),
+    endDate = new Date(new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1);
+let snbStartDate = startDate, snbEndDate = endDate;
+let applyState = 0;
+layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], function () {
+    let table = layui.table;
+    let form = layui.form;//select、单选、复选等依赖form
+    let element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块
+    let laydate = layui.laydate;
+    tree = layui.tree;
+    let height = document.documentElement.clientHeight;
+
+    tableCTB = table.render({
+        elem: '#ctbTable'
+        , url: ctx + "/sys/sysProperty/findComCntToSnbPage"
+        , method: 'POST'
+        //请求前参数处理
+        , request: {
+            pageName: 'page' //页码的参数名称,默认:page
+            , limitName: 'rows' //每页数据量的参数名,默认:limit
+        }
+        , where: {
+            isState: applyState
+        }
+        , response: {
+            statusName: 'flag' //规定数据状态的字段名称,默认:code
+            , statusCode: true //规定成功的状态码,默认:0
+            , msgName: 'msg' //规定状态信息的字段名称,默认:msg
+            , countName: 'records' //规定数据总数的字段名称,默认:count
+            , dataName: 'rows' //规定数据列表的字段名称,默认:data
+        }
+        //响应后数据处理
+        , parseData: function (res) { //res 即为原始返回的数据
+            var data = res.data;
+            // console.log("返回的地址数据:", data);
+            //这里应该是反回一个用户,后台做成了页面数据。但是只带一条数据
+            return {
+                "flag": res.flag, //解析接口状态
+                "msg": res.msg, //解析提示文本
+                "records": data.records, //解析数据长度
+                "rows": data.rows //解析数据列表
+            };
+        }
+        , toolbar: '#ctbTableToolbarDemo'
+        , title: 'SNB释放列表'
+        , cols: [
+            [
+
+                {field: 'id', title: 'ID'}
+                , {field: 'address', title: '用户address'}
+                , {field: 'totalQuantity', title: '返还的总数', sort: true}
+                , {field: 'receivedQuantity', title: '已领取数量', sort: true}
+                , {field: 'totalDay', title: '领取总天数', sort: true}
+                , {field: 'receivedDay', title: '已领取天数', sort: true}
+                , {field: 'beginTime', title: '开始时间', sort: true},
+                {
+                    field: 'status', title: '状态', sort: true, templet: function (d) {
+                        if (d.status == 0) {
+                            return '<span style="color: red ">不可领取</span>';
+                        } else if (d.status == 1) {
+                            return '<span style="color: green">可以领取</span>';
+                        }  else {
+                            return '待添加:' + d.status;
+                        }
+                    }
+                }
+            ]]
+        , defaultToolbar: ['', 'exports', 'print']
+        , page: true
+        , limit: 20
+        , height: height
+        , cellMinWidth: 80
+    });
+
+
+    //头工具栏事件
+    table.on('toolbar(test)', function (obj) {
+        let data = obj.data;
+        switch (obj.event) {
+            case 'ctbReload':
+                ctbReloadFunction();
+                break;
+        }
+    });
+
+    let $ = layui.$, active = {
+        reload: function () {
+            let addressReload = $('#addressReload');
+            // console.log("reload");
+            tableCTB.reload({
+                page: {
+                    curr: 1 //重新从第 1 页开始
+                }
+                , method: 'POST'
+                , url: ctx + "/sys/sysProperty/findComCntToSnbPage"
+                , where: {
+                    address: addressReload.val().length != 0 ? addressReload.val() : null,
+                    isState: applyState
+                }
+                , done: function (res, curr, count) {
+                    // console.log(res, curr, count);
+                    // this.where={};
+                    //不清空,有问题:搜索条件会保留
+                    //清空,  有问题:分页的时候没有搜索条件了,分页会受到影响
+                }
+            });
+
+        }
+    };
+
+    $('.addressTable .layui-btn').on('click', function () {
+        let type = $(this).data('type');
+        active[type] ? active[type].call(this) : '';
+    });
+
+});
+
+function ctbReloadFunction() {
+    tableCTB.reload({
+        page: true
+        , method: 'POST'
+        , url: ctx + "/sys/sysProperty/findComCntToSnbPage"
+        , done: function (res, curr, count) {
+            // console.log(res, curr, count);
+            // this.where={};
+            //不清空,有问题:搜索条件会保留
+            //清空,  有问题:分页的时候没有搜索条件了,分页会受到影响
+        }
+    });
+}

+ 24 - 4
src/main/resources/static/sys/aComUser/js/user.js

@@ -260,12 +260,26 @@ function initSNBTable(table, data) {
                         return '<span style="color: green">转CNT解冻</span>';
                     } else if (d.tranType == 3) {
                         return '<span style="color: red">购买种子</span>';
+                    } else if (d.tranType == 4) {
+                        return '<span style="color: red">偷取果实</span>';
+                    } else if (d.tranType == 5) {
+                        return '<span style="color: red">购买装备</span>';
+                    } else if (d.tranType == 6) {
+                        return '<span style="color: red">购买装备</span>';
+                    } else if (d.tranType == 7) {
+                        return '<span style="color: red">购买狗粮</span>';
+                    } else if (d.tranType == 8) {
+                        return '<span style="color: red">释放SNB</span>';
+                    } else if (d.tranType == 9) {
+                        return '<span style="color: red">幸运值</span>';
                     } else {
                         return '<span style="color: red">待添加:</span>' + d.tranType;
                     }
                 }
             }
-            , {field: 'tranAmount', title: '交易数量'}
+            , {field: 'tranAmount', title: '交易数量',templet: function (d) {
+                    return (d.tranAmount + d.tranAmountPart).toFixed(5);
+                }}
             , {field: 'tranPrice', title: '交易价格'}
             , {field: 'tranDescribe', title: '交易描述'}
             , {
@@ -277,9 +291,15 @@ function initSNBTable(table, data) {
                     }
                 }
             }
-            , {field: 'beforeSnb', title: '交易之前的snb'}
-            , {field: 'tranSnb', title: '交易的snb'}
-            , {field: 'afterSnb', title: '交易完成后的snb'}
+            , {field: 'beforeSnb', title: '交易之前的snb',templet: function (d) {
+                    return (d.beforeSnb + d.beforeSnbPart).toFixed(5);
+                }}
+            , {field: 'tranSnb', title: '交易的snb', templet: function (d) {
+                    return (d.tranSnb + d.tranSnbPart).toFixed(5);
+                }}
+            , {field: 'afterSnb', title: '交易完成后的snb',templet: function (d) {
+                    return (d.afterSnb + d.afterSnbPart).toFixed(5);
+                }}
             , {field: 'createTime', title: '创建时间'}
             , {field: 'updateTime', title: '更新时间', hide: true}
         ]]

+ 1 - 1
src/main/resources/static/sys/aComUser/js/userPlayerGoods.js

@@ -80,7 +80,7 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
             , {field: 'name', title: '物品名称'}
             , {field: 'amount', title: '数量'}
             , {field: 'amountPart', title: '小数部分数量'}
-            , {fixed: 'right', title: '操作', toolbar: '#userPlayerGoodsTableBarDemo'}
+            , {fixed: 'right', title: '操作', toolbar: '#userPlayerGoodsTableBarDemo' ,hide:true}
         ]]
         , defaultToolbar: ['', 'exports', 'print']
         , page: true

+ 51 - 16
src/main/resources/view/sys/aComApplySNBToCNT/applySNBToCNT.html

@@ -18,7 +18,8 @@
                         <div class="layui-inline">
                             <label class="layui-form-label">自动审查</label>
                             <div class="layui-input-block">
-                                <input id="applyAutoExamine" th:value="${sysSettingTask.applyAutoExamine}"  hidden="hidden"/>
+                                <input id="applyAutoExamine" th:value="${sysSettingTask.applyAutoExamine}"
+                                       hidden="hidden"/>
                                 <input type="radio" name="applyAutoExamine" value="Y" title="是">
                                 <input type="radio" name="applyAutoExamine" value="N" title="否">
                             </div>
@@ -26,18 +27,31 @@
                         <div class="layui-inline">
                             <label class="layui-form-label">snb筛选范围</label>
                             <div class="layui-input-inline" style="width: 100px;">
-                                <input type="text" name="conditionSnbMin" placeholder="min"  th:value="${sysSettingTask.conditionSnbMin}" autocomplete="off" class="layui-input">
+                                <input type="text" name="conditionSnbMin" placeholder="min"
+                                       th:value="${sysSettingTask.conditionSnbMin}" autocomplete="off"
+                                       class="layui-input">
                             </div>
                             <div class="layui-form-mid">-</div>
                             <div class="layui-input-inline" style="width: 100px;">
-                                <input type="text" name="conditionSnbMax" placeholder="max"  th:value="${sysSettingTask.conditionSnbMax}" autocomplete="off" class="layui-input">
+                                <input type="text" name="conditionSnbMax" placeholder="max"
+                                       th:value="${sysSettingTask.conditionSnbMax}" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-inline">
+                            <label class="layui-form-label">当天下标限制的次数</label>
+                            <div class="layui-input-inline" style="width: 100px;">
+                                <input type="text" name="applyCount" placeholder="下标次数"
+                                       th:value="${sysSettingTask.applyCount}" autocomplete="off" class="layui-input">
                             </div>
                         </div>
 
                         <div class="layui-inline">
                             <label class="layui-form-label">更新时间</label>
                             <div class="layui-input-block">
-                                <input type="text" name="updateTime" th:value="${#dates.format(sysSettingTask.updateTime, 'yyyy-MM-dd HH:mm:ss')}" autocomplete="off"
+                                <input type="text" name="updateTime"
+                                       th:value="${#dates.format(sysSettingTask.updateTime, 'yyyy-MM-dd HH:mm:ss')}"
+                                       autocomplete="off"
                                        placeholder="更新时间"
                                        class="layui-input" readonly="readonly" disabled="disabled">
                             </div>
@@ -49,18 +63,31 @@
                     </div>
 
                     <!-- 隐藏域 -->
-                    <input type="text" name="id"  th:value="${sysSettingTask.id}" hidden="hidden"/>
-                    <input type="text" name="createTime"  th:value="${#dates.format(sysSettingTask.createTime, 'yyyy-MM-dd HH:mm:ss')}" hidden="hidden"/>
+                    <input type="text" name="id" th:value="${sysSettingTask.id}" hidden="hidden"/>
+                    <input type="text" name="createTime"
+                           th:value="${#dates.format(sysSettingTask.createTime, 'yyyy-MM-dd HH:mm:ss')}"
+                           hidden="hidden"/>
                 </form>
             </div>
             <div class="layui-card-body">
-                <div class="addressTable" style="margin-bottom: 20px;">
-                    钱包地址:
+                <div class="layui-inline addressTable" style="margin-bottom: 20px;">
+                    <div class="layui-inline">
+                        钱包地址:
+                        <div class="layui-inline">
+                            <input class="layui-input" name="id" id="addressReload" autocomplete="off">
+                        </div>
+                        <button class="layui-btn" data-type="reload">搜索</button>
+                    </div>
                     <div class="layui-inline">
-                        <input class="layui-input" name="id" id="addressReload" autocomplete="off">
+                        <label class="layui-form-label" style="margin-left: 20px;">日期范围的数据:</label>
+                        <div class="layui-input-inline" style="width: 300px;">
+                            <input type="text" class="layui-input" id="cntDate" placeholder=" - ">
+                        </div>
+                        <button class="layui-btn" data-type="exports">导出</button>
                     </div>
-                    <button class="layui-btn" data-type="reload">搜索</button>
                 </div>
+
+
                 <div class="layui-tab" lay-filter="test">
                     <ul class="layui-tab-title">
                         <li class="layui-this" lay-id="0">申请中</li>
@@ -77,17 +104,25 @@
                 <script type="text/html" id="applySnbTableToolbarDemo">
 
                     <div class="layui-btn-container">
-                        <button class="layui-btn" lay-event="applySnbTableReload">刷新</button>
-                        <button class="layui-btn" lay-event="batchApproval">批量同意</button>
-                        <button class="layui-btn" lay-event="batchRejection">批量驳回</button>
-                        <button class="layui-btn" lay-event="getCheckLength">获取选中数目</button>
-                        <button class="layui-btn" lay-event="isAll">验证是否全选</button>
+                        <button class="layui-btn layuibtn1" lay-event="applySnbTableReload">刷新</button>
+                        {{# if(applyState == 0 || applyState == 2){ }}
+                        <button class="layui-btn layuibtn2" lay-event="batchApproval">批量同意</button>
+                        {{# } }}
+                        {{# if(applyState == 1){ }}
+                        <button class="layui-btn layuibtn3" lay-event="batchRejection">批量驳回</button>
+                        {{# } }}
+                        <button class="layui-btn layuibtn4" lay-event="getCheckLength">获取选中数目</button>
+                        <button class="layui-btn layuibtn5" lay-event="isAll">验证是否全选</button>
                     </div>
+
+
                 </script>
 
                 <script type="text/html" id="barDemo">
-                    {{# if(d.isState == 0){ }}
+                    {{# if(d.isState == 0 || d.isState == 2){ }}
                     <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="agree">同意</a>
+                    {{# } }}
+                    {{# if(d.isState == 1){ }}
                     <a class="layui-btn layui-btn-xs" lay-event="reject">驳回</a>
                     {{# } }}
                 </script>

+ 17 - 0
src/main/resources/view/sys/aComCNTAnbSNB/CNTAndSNB.html

@@ -85,6 +85,23 @@
             </div>
         </div>
     </div>
+
+    <div class="layui-col-md6">
+        <div class="layui-card">
+            <div class="layui-card-header">SNB异常统计</div>
+            <div class="layui-card-body">
+                <!-- 表格主体 -->
+                <table class="layui-hide" id="snbErrorTable" lay-filter="test"></table>
+                <!-- 模板 -->
+                <script type="text/html" id="snbErrorTableToolbarDemo">
+                    <div class="layui-btn-container">
+                        <button class="layui-btn layui-btn-sm" lay-event="snbErrorReload">刷新</button>
+                    </div>
+                </script>
+            </div>
+        </div>
+
+    </div>
 </div>
 </body>
 <!-- js -->

+ 42 - 0
src/main/resources/view/sys/aComCntToSnb/aComCntToSnb.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--解决idea thymeleaf 表达式模板报红波浪线-->
+<!--suppress ALL -->
+<html xmlns:th="http://www.thymeleaf.org">
+<head>
+    <!-- 引入公用部分 -->
+    <script th:replace="common/head::static"></script>
+    <!-- 游戏数据用户相关样式 -->
+    <link th:href="@{/sys/aComCntToSnb/aComCntToSnb.css}" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div class="layui-row layui-col-space15">
+    <div class="layui-col-md12">
+        <div class="layui-card">
+            <div class="layui-card-body">
+                <div class="addressTable" style="margin-bottom: 20px;">
+                    钱包地址:
+                    <div class="layui-inline">
+                        <input class="layui-input" name="id" id="addressReload" autocomplete="off">
+                    </div>
+                    <button class="layui-btn" data-type="reload">搜索</button>
+                </div>
+
+                <!-- 表格主体 -->
+                <table class="layui-hide" id="ctbTable" lay-filter="test"></table>
+
+                <!-- 模板 -->
+                <script type="text/html" id="ctbTableToolbarDemo">
+
+                    <div class="layui-btn-container">
+                        <button class="layui-btn" lay-event="ctbReload">刷新</button>
+                    </div>
+                </script>
+
+            </div>
+        </div>
+    </div>
+</div>
+</body>
+<!-- js -->
+<script th:src="@{/sys/aComCntToSnb/aComCntToSnb.js}"></script>
+</html>

+ 1 - 1
src/test/java/com/td/boss/ComPlayerDisasterLogTests.java

@@ -30,7 +30,7 @@ class ComPlayerDisasterLogTests {
     @Autowired
     private ComCntToSnbService comCntToSnbService;
 
-    private String userId = "1002";
+    private String userId = "4";
 
     /**
      * 防护灾难