Ver código fonte

Merge branch 'dev' into 2D展厅

# Conflicts:
#	src/main/java/com/izouma/nineth/security/WebSecurityConfig.java
#	src/main/java/com/izouma/nineth/service/AirDropService.java
#	src/test/java/com/izouma/nineth/service/UserServiceTest.java
licailing 3 anos atrás
pai
commit
49e12dbeb7
23 arquivos alterados com 302 adições e 172 exclusões
  1. 6 0
      pom.xml
  2. 6 0
      src/main/java/com/izouma/nineth/domain/AirDrop.java
  3. 12 1
      src/main/java/com/izouma/nineth/domain/TestClass.java
  4. 17 2
      src/main/java/com/izouma/nineth/domain/User.java
  5. 9 1
      src/main/java/com/izouma/nineth/exception/GlobalExceptionHandler.java
  6. 15 6
      src/main/java/com/izouma/nineth/listener/RegisterListener.java
  7. 3 2
      src/main/java/com/izouma/nineth/repo/TestClassRepo.java
  8. 0 4
      src/main/java/com/izouma/nineth/repo/UserRepo.java
  9. 2 0
      src/main/java/com/izouma/nineth/security/WebSecurityConfig.java
  10. 15 3
      src/main/java/com/izouma/nineth/service/AirDropService.java
  11. 64 23
      src/main/java/com/izouma/nineth/service/CollectionService.java
  12. 4 1
      src/main/java/com/izouma/nineth/service/IdentityAuthService.java
  13. 5 13
      src/main/java/com/izouma/nineth/service/UserService.java
  14. 4 10
      src/main/java/com/izouma/nineth/web/AuthenticationController.java
  15. 6 0
      src/main/java/com/izouma/nineth/web/StatisticController.java
  16. 9 15
      src/main/java/com/izouma/nineth/web/TestClassController.java
  17. 17 5
      src/main/resources/application.yaml
  18. 20 21
      src/main/resources/logback-spring.xml
  19. 27 4
      src/main/vue/src/views/AirDropEdit.vue
  20. 42 6
      src/main/vue/src/views/OrderUsedList.vue
  21. 1 7
      src/test/java/com/izouma/nineth/CommonTest.java
  22. 2 1
      src/test/java/com/izouma/nineth/service/CollectionServiceTest.java
  23. 16 47
      src/test/java/com/izouma/nineth/service/UserServiceTest.java

+ 6 - 0
pom.xml

@@ -430,6 +430,12 @@
             <artifactId>bucket4j-core</artifactId>
             <version>7.3.0</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.github.marschall</groupId>
+            <artifactId>hibernate-batch-sequence-generator</artifactId>
+            <version>1.2.0</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 6 - 0
src/main/java/com/izouma/nineth/domain/AirDrop.java

@@ -49,4 +49,10 @@ public class AirDrop extends BaseEntity {
 
     @Column(columnDefinition = "TEXT")
     private String result;
+
+    @ApiModelProperty("模拟订单")
+    private boolean simulateOrder = false;
+
+    @ApiModelProperty("忽略库存校验")
+    private boolean ignoreStockCheck = false;
 }

+ 12 - 1
src/main/java/com/izouma/nineth/domain/TestClass.java

@@ -6,12 +6,23 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
 
 @Data
 @Entity
 @AllArgsConstructor
 @NoArgsConstructor
 @Builder
-public class TestClass extends BaseEntity {
+public class TestClass {
+    public TestClass(String name) {
+        this.name = name;
+    }
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
     private String name;
 }

+ 17 - 2
src/main/java/com/izouma/nineth/domain/User.java

@@ -27,7 +27,7 @@ import java.util.Set;
 @Data
 @Entity
 @Table(indexes = {
-        @Index(columnList = "phone"),
+        @Index(columnList = "phone", unique = true, name = "user_index_phone"),
         @Index(columnList = "collectionId"),
         @Index(columnList = "collectionInvitor"),
         @Index(columnList = "admin"),
@@ -39,7 +39,22 @@ import java.util.Set;
 @NoArgsConstructor
 @Builder
 @ApiModel(value = "用户", description = "用户")
-public class User extends BaseEntity implements Serializable {
+public class User extends BaseEntityNoID implements Serializable {
+
+    @Id
+//    @GenericGenerator(
+//            name = "some_column_name_id_generator",
+//            strategy = "com.github.marschall.hibernate.batchsequencegenerator.BatchSequenceGenerator",
+//            parameters = {
+//                    @org.hibernate.annotations.Parameter(name = "sequence", value = "user_sequence"),
+//                    @org.hibernate.annotations.Parameter(name = "fetch_size", value = "50")
+//            })
+//    @GeneratedValue(generator = "user_id_generator")
+
+//    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
+//    @SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 200)
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
 
     //    @Pattern(regexp = Constants.Regex.USERNAME)
     @Size(min = 1, max = 50)

+ 9 - 1
src/main/java/com/izouma/nineth/exception/GlobalExceptionHandler.java

@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 @ControllerAdvice
@@ -86,8 +87,15 @@ public class GlobalExceptionHandler {
             modelAndView.addObject("trace", trace);
             return modelAndView;
         } else {
+            String message = e.getMessage();
+            if (Pattern.matches(".*SQL.*constraint.*user_index_phone.*", e.getMessage())) {
+                message = "手机号已注册";
+            }
+            if (Pattern.matches(".*SQL.*constraint.*username.*", e.getMessage())) {
+                message = "用户名已存在";
+            }
             Map<String, Object> map = new HashMap<>();
-            map.put("error", e.getMessage());
+            map.put("error", message);
             map.put("code", -1);
             return map;
         }

+ 15 - 6
src/main/java/com/izouma/nineth/listener/RegisterListener.java

@@ -2,7 +2,8 @@ package com.izouma.nineth.listener;
 
 import com.izouma.nineth.domain.User;
 import com.izouma.nineth.event.RegisterEvent;
-import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.security.JwtTokenUtil;
+import com.izouma.nineth.security.JwtUserFactory;
 import com.izouma.nineth.service.UserService;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -14,6 +15,8 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
 import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
 
 @Service
 @Slf4j
@@ -24,19 +27,25 @@ import java.time.Duration;
         consumeMode = ConsumeMode.ORDERLY)
 @ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
 public class RegisterListener implements RocketMQListener<RegisterEvent> {
-    private UserService                   userService;
-    private RedisTemplate<String, Object> redisTemplate;
+    private       UserService                   userService;
+    private       RedisTemplate<String, Object> redisTemplate;
+    private final JwtTokenUtil                  jwtTokenUtil;
 
     @Override
     public void onMessage(RegisterEvent registerEvent) {
+        Map<String, Object> map = new HashMap<>();
         try {
             User user = userService.phoneRegister(registerEvent.getPhone(), registerEvent.getCode(),
                     registerEvent.getPassword(), registerEvent.getInviteCode(),
                     registerEvent.getInvitor(), registerEvent.getCollectionId());
-            redisTemplate.opsForValue().set("register::" + registerEvent.getPhone(), user, Duration.ofSeconds(600));
+            map.put("status", "success");
+            map.put("data", user);
+            map.put("token", jwtTokenUtil.generateToken(JwtUserFactory.create(user)));
+            redisTemplate.opsForValue().set("register::" + registerEvent.getPhone(), map, Duration.ofSeconds(600));
         } catch (Exception e) {
-            redisTemplate.opsForValue()
-                    .set("register::" + registerEvent.getPhone(), new BusinessException(e.getMessage()), Duration.ofSeconds(600));
+            map.put("status", "fail");
+            map.put("data", e.getMessage());
+            redisTemplate.opsForValue().set("register::" + registerEvent.getPhone(), map, Duration.ofSeconds(600));
         }
     }
 }

+ 3 - 2
src/main/java/com/izouma/nineth/repo/TestClassRepo.java

@@ -9,8 +9,9 @@ import org.springframework.data.jpa.repository.Query;
 import javax.transaction.Transactional;
 
 public interface TestClassRepo extends JpaRepository<TestClass, Long>, JpaSpecificationExecutor<TestClass> {
-    @Query("update TestClass t set t.del = true where t.id = ?1")
+
     @Modifying
     @Transactional
-    void softDelete(Long id);
+    @Query(value = "insert into test_class (name) values (?1)", nativeQuery = true)
+    public void nativeSave(String name);
 }

+ 0 - 4
src/main/java/com/izouma/nineth/repo/UserRepo.java

@@ -23,10 +23,6 @@ public interface UserRepo extends JpaRepository<User, Long>, JpaSpecificationExe
     @Query("update User u set u.del = true where u.id = ?1")
     void softDelete(Long id);
 
-    @NonNull
-    @CachePut(value = "userInfo", key = "#user.id")
-    User save(@NonNull User user);
-
     @Cacheable("user")
     User findByUsernameAndDelFalse(String username);
 

+ 2 - 0
src/main/java/com/izouma/nineth/security/WebSecurityConfig.java

@@ -96,6 +96,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/blindBoxItem/all").permitAll()
                 .antMatchers("/collection/recommend").permitAll()
                 .antMatchers("/order/**/status").permitAll()
+                .antMatchers("/order/checkLimit").permitAll()
                 .antMatchers("/mintOrder/**/status").permitAll()
                 .antMatchers("/activity/all").permitAll()
                 .antMatchers("/activity/get/*").permitAll()
@@ -112,6 +113,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/statistic/weekTop").permitAll()
                 .antMatchers("/showroom/all").permitAll()
                 .antMatchers("/showroom/get/**").permitAll()
+                .antMatchers("/testClass/**").permitAll()
                 // all other requests need to be authenticated
                 .anyRequest().authenticated().and()
                 // make sure we use stateless session; session won't be used to

+ 15 - 3
src/main/java/com/izouma/nineth/service/AirDropService.java

@@ -50,7 +50,7 @@ public class AirDropService {
             if (collection.isSalable()) {
                 throw new BusinessException("请先设置藏品为不可购买");
             }
-            if (collection.getStock() < record.getUserIds().size()) {
+            if (!record.isIgnoreStockCheck() && collection.getStock() < record.getUserIds().size()) {
                 throw new BusinessException("藏品库存不足");
             }
             List<User> users = userRepo.findByIdInAndDelFalse(record.getUserIds());
@@ -58,9 +58,21 @@ public class AirDropService {
                 try {
                     if (collection.getType() == CollectionType.BLIND_BOX) {
                         BlindBoxItem winItem = collectionService.draw(collection.getId());
-                        assetService.createAsset(winItem, user, null, null, "空投",
-                                collectionService.getNextNumber(winItem.getCollectionId()), collection.getHoldDays());
+                        if (record.isSimulateOrder()) {
+                            assetService.createAsset(winItem, user, 0L, collection.getPrice(), "出售",
+                                    winItem.getTotal() > 1 ? collectionService.getNextNumber(winItem.getCollectionId()) : null,
+                                    collection.getHoldDays());
+                        } else {
+                            assetService.createAsset(winItem, user, null, null, "空投",
+                                    collectionService.getNextNumber(winItem.getCollectionId()), collection.getHoldDays());
+                        }
                     } else {
+                        if (record.isSimulateOrder()) {
+                            assetService.createAsset(collection, user, 0L, collection.getPrice(), "出售",
+                                    collection.getTotal() > 1 ? collectionService.getNextNumber(collection.getId()) : null);
+                        } else {
+                            assetService.createAsset(collection, user, null, null, "空投", collectionService.getNextNumber(collection.getId()));
+                        }
                         Asset asset = assetService.createAsset(collection, user, null, null, "空投", collectionService.getNextNumber(collection.getId()));
                         if (collection.getType() == CollectionType.SHOWROOM) {
                             showroomService.save(asset);

+ 64 - 23
src/main/java/com/izouma/nineth/service/CollectionService.java

@@ -1,9 +1,11 @@
 package com.izouma.nineth.service;
 
 import com.alibaba.fastjson.JSON;
+import com.izouma.nineth.TokenHistory;
 import com.izouma.nineth.annotations.Debounce;
 import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.config.RedisKeys;
+import com.izouma.nineth.converter.LongArrayConverter;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.*;
@@ -40,8 +42,10 @@ import org.springframework.web.bind.annotation.RequestParam;
 import javax.annotation.PostConstruct;
 import javax.persistence.criteria.Predicate;
 import javax.transaction.Transactional;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
@@ -79,14 +83,6 @@ public class CollectionService {
         for (Collection collection : collections) {
             onShelfTask(collection);
         }
-        for (CollectionStockAndSale collection : collectionRepo.getStockAndSale()) {
-            if (redisTemplate.opsForValue().get(RedisKeys.COLLECTION_STOCK + collection.getId()) == null) {
-                redisTemplate.opsForValue().set(RedisKeys.COLLECTION_STOCK + collection.getId(), collection.getStock());
-            }
-            if (redisTemplate.opsForValue().get(RedisKeys.COLLECTION_SALE + collection.getId()) == null) {
-                redisTemplate.opsForValue().set(RedisKeys.COLLECTION_SALE + collection.getId(), collection.getSale());
-            }
-        }
     }
 
     @Cacheable(value = "collectionList", key = "#pageQuery.hashCode()")
@@ -477,10 +473,10 @@ public class CollectionService {
     }
 
 
-    public List<PointDTO> savePoint(Long collectionId) {
+    public List<PointDTO> savePoint(Long collectionId, LocalDateTime time) {
         Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("无藏品"));
         //库存
-        int stock = collection.getStock();
+//        int stock = collection.getStock();
         //是否开启白名单
         int assignment = collection.getAssignment();
         if (assignment <= 0) {
@@ -493,30 +489,76 @@ public class CollectionService {
                 .collect(Collectors.groupingBy(User::getCollectionInvitor));
 
         AtomicInteger sum = new AtomicInteger();
+        AtomicInteger sum1 = new AtomicInteger();
         List<PointDTO> dtos = new ArrayList<>();
+
+        Map<Long, BigDecimal> historyMap = tokenHistoryRepo.userBuy(userMap.keySet())
+                .stream()
+                .collect(Collectors.groupingBy(TokenHistory::getToUserId, Collectors.reducing(BigDecimal.ZERO,
+                        TokenHistory::getPrice,
+                        BigDecimal::add)));
+
+        DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         userMap.forEach((key, value) -> {
             //邀请达到数量
             if (value.size() >= collection.getAssignment()) {
                 value.sort(Comparator.comparing(User::getCreatedAt));
+                BigDecimal buy = historyMap.get(key);
                 //满足条件的时间
                 User user = value.get(collection.getAssignment() - 1);
-                //实名数量
-                long identitySum = value.stream().filter(u -> AuthStatus.SUCCESS.equals(u.getAuthStatus())).count();
-                dtos.add(new PointDTO(key, user.getCreatedAt(), value.size(), (int) identitySum, tokenHistoryRepo.userBuy(key)));
-                sum.getAndIncrement();
+                //作弊得已屏蔽
+                if ((ObjectUtils.isEmpty(buy) || buy.compareTo(BigDecimal.valueOf(500)) < 0) && user.getCreatedAt()
+                        .isBefore(time)) {
+                    sum1.getAndIncrement();
+                    System.out.println(key + "," + dft.format(user.getCreatedAt()) + "," + buy);
+                } else {
+                    //实名数量
+                    long identitySum = value.stream().filter(u -> AuthStatus.SUCCESS.equals(u.getAuthStatus())).count();
+                    dtos.add(new PointDTO(key, user.getCreatedAt(), value.size(), (int) identitySum, buy));
+                    sum.getAndIncrement();
+                }
             }
         });
         log.info("完成任务人数:{}", sum);
+        log.info("作弊任务人数:{}", sum1);
 
-        //只留库存数量
-        List<PointDTO> result = dtos.stream()
-                .sorted(Comparator.comparing(PointDTO::getCreatedAt))
-                .limit(stock)
+        LongArrayConverter longArrayConverter = new LongArrayConverter();
+
+        List<Long> collect = dtos.stream()
+                .filter(dto -> time.isBefore(dto.getCreatedAt()))
+                .map(PointDTO::getId)
                 .collect(Collectors.toList());
-        List<Long> userIds = result.stream().map(PointDTO::getId).collect(Collectors.toList());
-        Map<Long, User> resultMap = userRepo.findAllById(userIds)
-                .stream()
-                .collect(Collectors.toMap(User::getId, user -> user));
+        log.info(dft.format(time) + "前完成任务人数:{}", collect.size());
+        log.info("sql: update user set vip_point = 1 where id in ({})", longArrayConverter.convertToDatabaseColumn(collect));
+
+        List<PointDTO> collect1 = dtos.stream().filter(dto -> time.isAfter(dto.getCreatedAt())).collect(Collectors.toList());
+        log.info(dft.format(time) + "后完成任务人数:{}", collect1.size());
+
+        List<Long> collect2 = dtos.stream().filter(dto -> dto.getIdentitySum() > 0).map(PointDTO::getId).collect(Collectors.toList());
+        log.info("邀请实名认证人量:{}", collect2.size());
+        log.info("sql: update user set vip_point = 1 where id in ({})", longArrayConverter.convertToDatabaseColumn(collect2));
+
+        //只留库存数量
+//        List<PointDTO> result = dtos.stream()
+//                .sorted(Comparator.comparing(PointDTO::getCreatedAt))
+//                .collect(Collectors.toList());
+//        List<Long> userIds = result.stream().map(PointDTO::getId).collect(Collectors.toList());
+//        Map<Long, User> resultMap = userRepo.findAllById(userIds)
+//                .stream()
+//                .collect(Collectors.toMap(User::getId, user -> user));
+//
+//        List<PointDTO> result2 = new ArrayList<>();
+//        List<PointDTO> result3 = new ArrayList<>();
+//        result.forEach(dto -> {
+//            if (dto.getIdentitySum() > 0) {
+//                result2.add(dto);
+//            } else {
+//                result3.add(dto);
+//            }
+//        });
+//
+//        result2.addAll(result3);
+
 
         //加积分,存记录
 //        result.forEach(pointDTO -> {
@@ -524,7 +566,6 @@ public class CollectionService {
 //            if (user.getVipPoint() <= 0) {
 //                user.setVipPoint(1);
 //                userRepo.save(user);
-////                userRepo.updateVipPoint(pointDTO.getId(), 1);
 //                pointRecordRepo.save(PointRecord.builder()
 //                        .collectionId(collectionId)
 //                        .userId(pointDTO.getId())

+ 4 - 1
src/main/java/com/izouma/nineth/service/IdentityAuthService.java

@@ -1,6 +1,8 @@
 package com.izouma.nineth.service;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.github.kevinsawicki.http.HttpRequest;
 import com.izouma.nineth.annotations.RedisLock;
 import com.izouma.nineth.domain.IdentityAuth;
@@ -129,6 +131,7 @@ public class IdentityAuthService {
                 .form("realName", name)
                 .body();
         JSONObject jsonObject = JSONObject.parseObject(body);
+        log.info("validate {} {} \n{}", name, idno, JSON.toJSONString(jsonObject, SerializerFeature.PrettyFormat));
         if (jsonObject.getInteger("error_code") != 0) {
             String msg = jsonObject.getString("reason");
             throw new BusinessException(msg);
@@ -150,7 +153,7 @@ public class IdentityAuthService {
         while (hasMore) {
             Page<Long> page = identityAuthRepo.listUserId(PageRequest.of(pageNum, 100));
             List<Long> userIds = page.getContent();
-            userIds.parallelStream().forEach(userId -> {
+            userIds.forEach(userId -> {
                 userRepo.findById(userId).ifPresent(user -> {
                     log.info("removeDuplicated {}/{} ", count.incrementAndGet(), page.getTotalElements());
                     List<IdentityAuth> list = identityAuthRepo.findByUserId(userId);

+ 5 - 13
src/main/java/com/izouma/nineth/service/UserService.java

@@ -145,10 +145,6 @@ public class UserService {
     }
 
     public User create(UserRegister userRegister) {
-        if (StringUtils.isNoneEmpty(userRegister.getPhone()) && userRepo.findByPhoneAndDelFalse(userRegister.getPhone())
-                .orElse(null) != null) {
-            throw new BusinessException("该手机号已注册");
-        }
         User user = new User();
         BeanUtils.copyProperties(userRegister, user);
         user.setShareRatio(sysConfigService.getBigDecimal("share_ratio"));
@@ -156,11 +152,7 @@ public class UserService {
         if (StringUtils.isNotBlank(userRegister.getPassword())) {
             user.setPassword(new BCryptPasswordEncoder().encode(userRegister.getPassword()));
         }
-        user = userRepo.save(user);
-        if (Arrays.asList(env.getActiveProfiles()).contains("prod")) {
-            nftService.createAccount(user.getId());
-        }
-        return user;
+        return userRepo.save(user);
     }
 
     @EventListener
@@ -196,7 +188,6 @@ public class UserService {
             }
         }
         User user = create(UserRegister.builder()
-                .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER)))
                 .username(name)
                 .nickname(name)
                 .password(password)
@@ -254,8 +245,10 @@ public class UserService {
         return redisTemplate.opsForValue().get("register::" + phone);
     }
 
-    public User testPhoneRegister() {
-        String phone = "19" + RandomStringUtils.randomNumeric(11);
+    public User testPhoneRegister(String phone) {
+        if (phone == null) {
+            phone = "19" + RandomStringUtils.randomNumeric(11);
+        }
         String password = "123456";
         String inviteCode = null;
         Long invitor = null;
@@ -281,7 +274,6 @@ public class UserService {
             }
         }
         User user = create(UserRegister.builder()
-                .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER)))
                 .username(name)
                 .nickname(name)
                 .password(password)

+ 4 - 10
src/main/java/com/izouma/nineth/web/AuthenticationController.java

@@ -94,24 +94,18 @@ public class AuthenticationController {
     public Object registerResult(String phone) {
         Object res = userService.getRegisterResult(phone);
         Map<String, Object> map = new HashMap<>();
-        if (res instanceof User) {
-            map.put("status", "success");
-            map.put("token", jwtTokenUtil.generateToken(JwtUserFactory.create((User) res)));
-            return map;
-        } else if (res == null) {
+        if (res == null) {
             map.put("status", "pending");
             return map;
         } else {
-            map.put("status", "fail");
-            map.put("error", res);
-            return map;
+            return res;
         }
     }
 
     @PostMapping("/testphoneRegister")
     @ApiOperation(value = "手机号密码注册")
-    public String phonePwdLogin() {
-        User user = userService.testPhoneRegister();
+    public String phonePwdLogin(String phone) {
+        User user = userService.testPhoneRegister(phone);
         return jwtTokenUtil.generateToken(JwtUserFactory.create(user));
     }
 

+ 6 - 0
src/main/java/com/izouma/nineth/web/StatisticController.java

@@ -76,4 +76,10 @@ public class StatisticController {
     public void clearWeekTop(){
         cacheService.clearWeekTop();
     }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/clearUser")
+    public void clearUser(){
+        cacheService.clearUser();
+    }
 }

+ 9 - 15
src/main/java/com/izouma/nineth/web/TestClassController.java

@@ -1,10 +1,10 @@
 package com.izouma.nineth.web;
+
 import com.izouma.nineth.domain.TestClass;
-import com.izouma.nineth.service.TestClassService;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.TestClassRepo;
-import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.service.TestClassService;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import lombok.AllArgsConstructor;
 import org.springframework.data.domain.Page;
@@ -19,19 +19,18 @@ import java.util.List;
 @AllArgsConstructor
 public class TestClassController extends BaseController {
     private TestClassService testClassService;
-    private TestClassRepo testClassRepo;
+    private TestClassRepo    testClassRepo;
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
-    public TestClass save(@RequestBody TestClass record) {
-        if (record.getId() != null) {
-            TestClass orig = testClassRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
-            ObjUtils.merge(orig, record);
-            return testClassRepo.save(orig);
-        }
-        return testClassRepo.save(record);
+    public TestClass save() {
+        return testClassRepo.save(new TestClass("aaa"));
     }
 
+    @PostMapping("/save1")
+    public void save1() {
+        testClassRepo.nativeSave("aaa");
+    }
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
@@ -44,11 +43,6 @@ public class TestClassController extends BaseController {
         return testClassRepo.findById(id).orElseThrow(new BusinessException("无记录"));
     }
 
-    @PostMapping("/del/{id}")
-    public void del(@PathVariable Long id) {
-        testClassRepo.softDelete(id);
-    }
-
     @GetMapping("/excel")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {

+ 17 - 5
src/main/resources/application.yaml

@@ -39,13 +39,15 @@ spring:
     druid:
       # 连接池的配置信息
       # 初始化大小,最小,最大
-      initial-size: 10
-      min-idle: 10
-      maxActive: 5000
+      initial-size: 5
+      min-idle: 20
+      maxActive: 3000
       # 配置获取连接等待超时的时间
-      maxWait: 10000
+      maxWait: 60000
+      # 使用不公平锁提高并发
+      use-unfair-lock: true
       # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-      timeBetweenEvictionRunsMillis: 60000
+      timeBetweenEvictionRunsMillis: 30000
       # 配置一个连接在池中最小生存的时间,单位是毫秒
       minEvictableIdleTimeMillis: 300000
       validationQuery: SELECT 1
@@ -63,6 +65,10 @@ spring:
       remove-abandoned: true
       remove-abandoned-timeout: 1800
       log-abandoned: true
+      # 保持连接
+      keep-alive: true
+      # 超过多长时间
+      keep-alive-between-time-millis: 60000
       # 配置DruidStatFilter
       web-stat-filter:
         enabled: true
@@ -81,6 +87,7 @@ spring:
             condition-and-alway-false-allow: true
             condition-and-alway-true-allow: true
             select-where-alway-true-check: false
+
   jpa:
     database: MySQL
     database_platform: org.hibernate.dialect.MySQL5InnoDBDialect
@@ -89,6 +96,11 @@ spring:
     properties:
       hibernate:
         enable_lazy_load_no_trans: true
+        jdbc:
+          batch_size: 100
+          order_inserts: true
+          order_updates: true
+          fetch_size: 400
     open-in-view: true
   servlet:
     multipart:

+ 20 - 21
src/main/resources/logback-spring.xml

@@ -16,22 +16,21 @@
         <logger name="io.swagger.models.parameters.AbstractSerializableParameter" level="ERROR"/>
         <logger name="org.freemarker" level="DEBUG"/>
 
-        <!-- dingding log -->
-        <appender name="HTTP_INVOKE_LOGGER_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
-            <param name="append" value="true"/>
-            <param name="encoding" value="UTF-8"/>
-            <param name="threshold" value="INFO"/>
-            <encoder>
-                <pattern>${CONSOLE_LOG_PATTERN}</pattern>
-            </encoder>
-        </appender>
+<!--        <logger name="druid.sql.Statement" level="debug">-->
+<!--        </logger>-->
+<!--        <logger name="druid.sql.DataSource" level="debug">-->
+<!--        </logger>-->
+<!--        <logger name="druid.sql.Connection" level="debug">-->
+<!--        </logger>-->
+<!--        <logger name="druid.sql.ResultSet" level="debug">-->
+<!--        </logger>-->
 
-<!--        <logger name="org.hibernate.SQL" level="DEBUG"/>-->
-<!--        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>-->
-<!--        <logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>-->
-<!--        <logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="TRACE"/>-->
-<!--        <logger name="cn.binarywang.wx.miniapp" level="DEBUG"/>-->
-<!--        <logger name="io.swagger.models.parameters.AbstractSerializableParameter" level="ERROR"/>-->
+        <!--        <logger name="org.hibernate.SQL" level="DEBUG"/>-->
+        <!--        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>-->
+        <!--        <logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>-->
+        <!--        <logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="TRACE"/>-->
+        <!--        <logger name="cn.binarywang.wx.miniapp" level="DEBUG"/>-->
+        <!--        <logger name="io.swagger.models.parameters.AbstractSerializableParameter" level="ERROR"/>-->
     </springProfile>
 
     <springProfile name="local">
@@ -81,12 +80,12 @@
         <root level="INFO">
             <appender-ref ref="FILE"/>
         </root>
-<!--        <logger name="org.hibernate.SQL" level="DEBUG"/>-->
-<!--        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>-->
-<!--        <logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>-->
-<!--        <logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="TRACE"/>-->
-<!--        <logger name="cn.binarywang.wx.miniapp" level="DEBUG"/>-->
-<!--        <logger name="io.swagger.models.parameters.AbstractSerializableParameter" level="ERROR"/>-->
+        <!--        <logger name="org.hibernate.SQL" level="DEBUG"/>-->
+        <!--        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>-->
+        <!--        <logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>-->
+        <!--        <logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="TRACE"/>-->
+        <!--        <logger name="cn.binarywang.wx.miniapp" level="DEBUG"/>-->
+        <!--        <logger name="io.swagger.models.parameters.AbstractSerializableParameter" level="ERROR"/>-->
     </springProfile>
 
     <springProfile name="test1">

+ 27 - 4
src/main/vue/src/views/AirDropEdit.vue

@@ -11,7 +11,7 @@
                     :model="formData"
                     :rules="rules"
                     ref="form"
-                    label-width="94px"
+                    label-width="120px"
                     label-position="right"
                     size="small"
                     style="max-width: 500px"
@@ -56,6 +56,13 @@
                             </el-table-column>
                         </el-table>
                         <el-button @click="addUser" size="mini">添加</el-button>
+                        <div class="tip">一次最多空投300个</div>
+                    </el-form-item>
+                    <el-form-item prop="simulateOrder" label="模拟订单" v-if="advanceMode">
+                        <el-switch v-model="formData.simulateOrder"></el-switch>
+                    </el-form-item>
+                    <el-form-item prop="ignoreStockCheck" label="忽略库存校验" v-if="advanceMode">
+                        <el-switch v-model="formData.ignoreStockCheck"></el-switch>
                     </el-form-item>
                     <el-form-item class="form-submit">
                         <el-button @click="onSave" :loading="saving" type="primary"> 保存 </el-button>
@@ -112,12 +119,18 @@ export default {
             .then(res => {
                 this.coupons = res.content;
             });
+        if (this.$route.query.advanceMode + '' === 'true') {
+            this.advanceMode = true;
+        }
     },
     data() {
         return {
             saving: false,
             formData: {
-                couponLimited: false
+                couponLimited: false,
+                simulateOrder: false,
+                ignoreStockCheck: false,
+                userIds: []
             },
             rules: {
                 name: [
@@ -170,7 +183,8 @@ export default {
             showPhoneDialog: false,
             searchingPhone: false,
             users: [],
-            coupons: []
+            coupons: [],
+            advanceMode: false
         };
     },
     methods: {
@@ -184,6 +198,9 @@ export default {
             });
         },
         submit() {
+            if (this.formData.userIds.length > 300) {
+                this.$message.error('一次最多空投300个');
+            }
             let data = { ...this.formData };
 
             this.saving = true;
@@ -265,4 +282,10 @@ export default {
     }
 };
 </script>
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+.tip {
+    font-size: 12px;
+    color: @text3;
+    margin-top: 5px;
+}
+</style>

+ 42 - 6
src/main/vue/src/views/OrderUsedList.vue

@@ -21,6 +21,15 @@
             </el-button>
         </page-title>
         <div class="filters-container">
+            <el-input
+                placeholder="搜索交易ID"
+                v-model="search"
+                clearable
+                class="filter-item search"
+                @keyup.enter.native="getData"
+            >
+                <el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
+            </el-input>
             <el-select v-model="status" placeholder="筛选状态" clearable @change="getData" class="filter-item">
                 <el-option
                     v-for="item in statusOptions"
@@ -29,16 +38,31 @@
                     :label="item.label"
                 ></el-option>
             </el-select>
-            <created-at-picker v-model="createdAt" @input="getData" name="下单" class="filter-item"></created-at-picker>
+             <el-input
+                placeholder="搜索藏品ID"
+                v-model="collectionId"
+                clearable
+                class="filter-item"
+                @keyup.enter.native="getData"
+            >
+            </el-input>
             <el-input
-                placeholder="搜索..."
-                v-model="search"
+                placeholder="搜索藏品名称"
+                v-model="name"
                 clearable
-                class="filter-item search"
+                class="filter-item"
+                @keyup.enter.native="getData"
+            >
+            </el-input>
+            <el-input
+                placeholder="搜索用户ID"
+                v-model="userId"
+                clearable
+                class="filter-item"
                 @keyup.enter.native="getData"
             >
-                <el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
             </el-input>
+            <created-at-picker v-model="createdAt" @input="getData" name="下单" class="filter-item"></created-at-picker>
         </div>
         <el-table
             :data="tableData"
@@ -134,7 +158,10 @@ export default {
                 { label: '支付宝', value: 'ALIPAY' }
             ],
             status: null,
-            createdAt: []
+            createdAt: [],
+            collectionId: '',
+            name: '',
+            userId: ''
         };
     },
     computed: {
@@ -174,6 +201,15 @@ export default {
             if (this.status) {
                 data.query.status = this.status;
             }
+            if (this.collectionId) {
+                data.query.collectionId = this.collectionId;
+            }
+            if (this.name) {
+                data.query.name = this.name;
+            }
+            if (this.userId) {
+                data.query.userId = this.userId;
+            }
             return data;
         },
         beforeGetData() {

+ 1 - 7
src/test/java/com/izouma/nineth/CommonTest.java

@@ -455,12 +455,6 @@ public class CommonTest {
 
     @Test
     public void aasdf() {
-        String body = HttpRequest.post("https://zid.market.alicloudapi.com/idcheck/Post")
-                .header("Authorization", "APPCODE b48bc8f6759345a79ae20a951f03dabe")
-                .contentType(HttpRequest.CONTENT_TYPE_FORM)
-                .form("cardNo", "352228198905220012")
-                .form("realName", "吴承培")
-                .body();
-        System.out.println(JSON.toJSONString(JSON.parseObject(body), SerializerFeature.PrettyFormat));
+        System.out.println(new BCryptPasswordEncoder().matches("123456","$2a$10$hYKQk3SKDqpK2QPDFqGdLekKWFcHs8rvou0hV4TxFy.ylL8PTBo5a"));
     }
 }

+ 2 - 1
src/test/java/com/izouma/nineth/service/CollectionServiceTest.java

@@ -140,7 +140,8 @@ class CollectionServiceTest extends ApplicationTests {
 
     @Test
     public void savePoint() {
-        collectionService.savePoint(196332L).forEach(System.out::println);
+//        collectionRepo.findById(206985L).orElseThrow(new BusinessException("无藏品"));
+        collectionService.savePoint(3749128L, LocalDateTime.of(2022, 3, 23, 15, 0, 0));
     }
 
 }

+ 16 - 47
src/test/java/com/izouma/nineth/service/UserServiceTest.java

@@ -1,35 +1,18 @@
 package com.izouma.nineth.service;
 
-import com.github.kevinsawicki.http.HttpRequest;
-import com.huifu.adapay.core.exception.BaseAdaPayException;
 import com.izouma.nineth.ApplicationTests;
 import com.izouma.nineth.config.Constants;
-import com.izouma.nineth.domain.IdentityAuth;
 import com.izouma.nineth.domain.User;
-import com.izouma.nineth.dto.BankValidate;
-import com.izouma.nineth.dto.PageQuery;
-import com.izouma.nineth.dto.UserBankCard;
 import com.izouma.nineth.dto.UserRegister;
-import com.izouma.nineth.enums.AuthStatus;
-import com.izouma.nineth.enums.AuthorityName;
-import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.IdentityAuthRepo;
 import com.izouma.nineth.repo.UserBankCardRepo;
 import com.izouma.nineth.repo.UserRepo;
-import com.izouma.nineth.security.Authority;
 import com.izouma.nineth.service.storage.StorageService;
-import com.izouma.nineth.utils.BankUtils;
-import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.regex.Pattern;
 
 public class UserServiceTest extends ApplicationTests {
 
@@ -58,38 +41,24 @@ public class UserServiceTest extends ApplicationTests {
     }
 
     @Test
-    public void sss9() throws IOException {
-        for (User user : userRepo.findAll()) {
-            if (user.getAvatar().startsWith("https://cdn")) {
-                HttpRequest request = HttpRequest.get(user.getAvatar());
-                File file = File.createTempFile("gw1", "1sadga");
-                request.receive(file);
-                user.setAvatar(storageService.uploadFromInputStream(new FileInputStream(file), "image/" + RandomStringUtils.randomAlphabetic(12) + ".jpg"));
-                userRepo.save(user);
-            }
-        }
-    }
-
-    @Test
-    public void a() {
-        for (String s : ("13816681152\n" +
-                "15564456867\n" +
-                "13363659367\n" +
-                "18963550881\n" +
-                "13931604318\n" +
-                "13705395943\n" +
-                "13162078752\n" +
-                "13589360751\n")
-                .split("\n")) {
-            String name = "9th_" + RandomStringUtils.randomAlphabetic(8);
+    public void register() throws IOException {
+        try {
             User user = userService.create(UserRegister.builder()
-                    .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER)))
-                    .username(name)
-                    .nickname(name)
-                    .password("123456")
+                    .username("1111fff1g1rertuiohejldknhgurphoj")
+                    .nickname("1111fff1g1rertuiohejldknhgurphoj")
                     .avatar(Constants.DEFAULT_AVATAR)
-                    .phone(s)
+                    .phone("15077886171")
                     .build());
+            System.out.println(user.getId());
+        } catch (Exception e) {
+            if (Pattern.matches(".*SQL.*constraint.*phone.*", e.getMessage())) {
+                System.out.println("手机号已注册");
+            }
+            if (Pattern.matches(".*SQL.*constraint.*username.*", e.getMessage())) {
+                System.out.println("用户名已存在");
+            }
+            e.printStackTrace();
+        }
         }
     }