Преглед изворни кода

Merge branch 'dev' of http://git.izouma.com/xiongzhu/raex_back into dev

 Conflicts:
	src/main/java/com/izouma/nineth/repo/CollectionRepo.java
wangqifan пре 3 година
родитељ
комит
85f66f455a
52 измењених фајлова са 655 додато и 185 уклоњено
  1. 11 5
      pom.xml
  2. 1 1
      src/main/java/com/izouma/nineth/config/RedisKeys.java
  3. 20 1
      src/main/java/com/izouma/nineth/domain/Collection.java
  4. 4 2
      src/main/java/com/izouma/nineth/domain/User.java
  5. 18 0
      src/main/java/com/izouma/nineth/dto/MarketSettlement.java
  6. 6 3
      src/main/java/com/izouma/nineth/dto/RecommendDTO.java
  7. 68 7
      src/main/java/com/izouma/nineth/dto/UserDTO.java
  8. 9 1
      src/main/java/com/izouma/nineth/listener/RegisterListener.java
  9. 12 7
      src/main/java/com/izouma/nineth/listener/UpdateSaleListener.java
  10. 27 2
      src/main/java/com/izouma/nineth/listener/UpdateStockListener.java
  11. 1 0
      src/main/java/com/izouma/nineth/repo/CollectionRepo.java
  12. 4 0
      src/main/java/com/izouma/nineth/repo/IdentityAuthRepo.java
  13. 3 0
      src/main/java/com/izouma/nineth/repo/OrderRepo.java
  14. 2 0
      src/main/java/com/izouma/nineth/repo/UserBankCardRepo.java
  15. 2 2
      src/main/java/com/izouma/nineth/repo/UserRepo.java
  16. 1 0
      src/main/java/com/izouma/nineth/security/WebSecurityConfig.java
  17. 16 5
      src/main/java/com/izouma/nineth/service/CaptchaService.java
  18. 26 26
      src/main/java/com/izouma/nineth/service/CollectionService.java
  19. 4 1
      src/main/java/com/izouma/nineth/service/IdentityAuthService.java
  20. 31 26
      src/main/java/com/izouma/nineth/service/MintOrderService.java
  21. 53 12
      src/main/java/com/izouma/nineth/service/OrderService.java
  22. 46 0
      src/main/java/com/izouma/nineth/service/SandPayService.java
  23. 2 4
      src/main/java/com/izouma/nineth/service/StatisticService.java
  24. 27 1
      src/main/java/com/izouma/nineth/service/UserService.java
  25. 2 0
      src/main/java/com/izouma/nineth/web/AssetController.java
  26. 5 3
      src/main/java/com/izouma/nineth/web/CollectionController.java
  27. 2 1
      src/main/java/com/izouma/nineth/web/DevelopController.java
  28. 2 0
      src/main/java/com/izouma/nineth/web/GenCodeController.java
  29. 8 1
      src/main/java/com/izouma/nineth/web/IdentityAuthController.java
  30. 23 0
      src/main/java/com/izouma/nineth/web/OrderController.java
  31. 5 3
      src/main/java/com/izouma/nineth/web/OrderPayController.java
  32. 4 0
      src/main/java/com/izouma/nineth/web/SandPayController.java
  33. 3 1
      src/main/java/com/izouma/nineth/web/SettingController.java
  34. 2 0
      src/main/java/com/izouma/nineth/web/ShowroomController.java
  35. 13 1
      src/main/java/com/izouma/nineth/web/SmsController.java
  36. 7 2
      src/main/java/com/izouma/nineth/web/StatisticController.java
  37. 22 4
      src/main/java/com/izouma/nineth/web/UserController.java
  38. 9 7
      src/main/resources/application.yaml
  39. 2 2
      src/main/resources/logback-spring.xml
  40. 2 0
      src/main/resources/templates/Privacy.ftlh
  41. 2 0
      src/main/resources/templates/Service.ftlh
  42. 2 2
      src/main/vue/src/components/CollectionCoupon.vue
  43. 2 2
      src/main/vue/src/components/CollectionSearch.vue
  44. 1 1
      src/main/vue/src/views/AdminList.vue
  45. 48 33
      src/main/vue/src/views/BlindBoxEdit.vue
  46. 7 1
      src/main/vue/src/views/CollectionList.vue
  47. 5 1
      src/main/vue/src/views/OrderList.vue
  48. 1 1
      src/main/vue/src/views/OrderUsedList.vue
  49. 1 1
      src/main/vue/src/views/UserEdit.vue
  50. 4 2
      src/main/vue/src/views/UserList.vue
  51. 73 10
      src/test/java/com/izouma/nineth/service/CollectionServiceTest.java
  52. 4 0
      src/test/java/com/izouma/nineth/service/OrderServiceTest.java

+ 11 - 5
pom.xml

@@ -287,11 +287,11 @@
         </dependency>
         <!-- 钉钉 -->
 
-        <dependency>
-            <groupId>com.github.whvcse</groupId>
-            <artifactId>easy-captcha</artifactId>
-            <version>1.6.2</version>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.github.whvcse</groupId>-->
+<!--            <artifactId>easy-captcha</artifactId>-->
+<!--            <version>1.6.2</version>-->
+<!--        </dependency>-->
 
         <dependency>
             <groupId>org.libjpegturbo</groupId>
@@ -420,6 +420,12 @@
             <version>2.0.1</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.pig4cloud.plugin</groupId>
+            <artifactId>captcha-spring-boot-starter</artifactId>
+            <version>2.2.2</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 1 - 1
src/main/java/com/izouma/nineth/config/RedisKeys.java

@@ -23,7 +23,7 @@ public class RedisKeys {
 
     public static final String UPDATE_SALE = "updateSale";
 
-    public static final String UPDATE_STOCK = "updateSale";
+    public static final String UPDATE_STOCK = "updateStock";
 
     public static final String LIMIT_REQ = "limitReq::";
 

+ 20 - 1
src/main/java/com/izouma/nineth/domain/Collection.java

@@ -32,7 +32,17 @@ import java.util.List;
         @Index(columnList = "assetId"),
         @Index(columnList = "salable"),
         @Index(columnList = "del"),
-        @Index(columnList = "name")
+        @Index(columnList = "name"),
+        @Index(columnList = "createdAt"),
+        @Index(columnList = "sale"),
+        @Index(columnList = "sort"),
+        @Index(columnList = "del"),
+        @Index(columnList = "price"),
+        @Index(columnList = "likes"),
+        @Index(columnList = "onShelf,del"),
+        @Index(columnList = "onShelf,del,source"),
+        @Index(columnList = "onShelf,del,source,salable"),
+        @Index(columnList = "onShelf,del,source,salable,price"),
 })
 @AllArgsConstructor
 @NoArgsConstructor
@@ -79,6 +89,7 @@ public class Collection extends BaseEntity {
 
     @ApiModelProperty("类型")
     @Enumerated(EnumType.STRING)
+    @Column(length = 20)
     private CollectionType type;
 
     @Column(columnDefinition = "TEXT")
@@ -95,6 +106,7 @@ public class Collection extends BaseEntity {
     private Integer number;
 
     @ApiModelProperty("是否可转售")
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean canResale;
 
     @ApiModelProperty("版税比例")
@@ -108,6 +120,7 @@ public class Collection extends BaseEntity {
 
     @ApiModelProperty("来源")
     @Enumerated(EnumType.STRING)
+    @Column(length = 20)
     private CollectionSource source;
 
     @ApiModelProperty("已售")
@@ -123,9 +136,11 @@ public class Collection extends BaseEntity {
     private int likes;
 
     @ApiModelProperty("上架")
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean onShelf;
 
     @ApiModelProperty("可售")
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean salable;
 
     @ApiModelProperty("价格")
@@ -135,6 +150,7 @@ public class Collection extends BaseEntity {
     @ApiModelProperty("盲盒开售时间")
     private LocalDateTime startTime;
 
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean scheduleSale;
 
     private int sort;
@@ -154,6 +170,7 @@ public class Collection extends BaseEntity {
     @ApiModelProperty("限购识别码")
     private String countId;
 
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean scanCode;
 
     /*
@@ -161,12 +178,14 @@ public class Collection extends BaseEntity {
     false: 已售罄
      */
     @ApiModelProperty("手动售罄")
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean noSoldOut;
 
     @ApiModelProperty("拉新任务指标")
     private int assignment;
 
     @ApiModelProperty("优惠券支付")
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean couponPayment;
 
     @ApiModelProperty("分享背景")

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

@@ -122,6 +122,7 @@ public class User extends BaseEntityNoID implements Serializable {
     @JsonIgnore
     private String tradeCode;
 
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean admin;
 
     @ApiModelProperty("分成比例")
@@ -150,10 +151,11 @@ public class User extends BaseEntityNoID implements Serializable {
     @ApiModelProperty("优先购买")
     private int vipPurchase;
 
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean minter;
 
-    @Column(columnDefinition = "bit default false")
     @ApiModelProperty("使用藏品图片")
+    @Column(columnDefinition = "tinyint unsigned")
     private boolean useCollectionPic;
 
     @Column(columnDefinition = "int(11) default 0")
@@ -163,6 +165,6 @@ public class User extends BaseEntityNoID implements Serializable {
     @ApiModelProperty(value = "风险提示")
     private Boolean riskWarning;
 
-    @Column(columnDefinition = "int(11) default 0")
+    @Column(columnDefinition = "tinyint unsigned default 0")
     private boolean canSale = false;
 }

+ 18 - 0
src/main/java/com/izouma/nineth/dto/MarketSettlement.java

@@ -0,0 +1,18 @@
+package com.izouma.nineth.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+@AllArgsConstructor
+public class MarketSettlement {
+    private Long userId;
+
+    private String name;
+
+    private String bankNo;
+
+    private BigDecimal amount;
+}

+ 6 - 3
src/main/java/com/izouma/nineth/dto/RecommendDTO.java

@@ -4,11 +4,14 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.time.LocalDateTime;
+
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
 public class RecommendDTO {
-    private Integer sort;
-    private Object obj;
-    private String type;
+    private Integer       sort;
+    private Object        obj;
+    private String        type;
+    private LocalDateTime createdAt;
 }

+ 68 - 7
src/main/java/com/izouma/nineth/dto/UserDTO.java

@@ -1,23 +1,84 @@
 package com.izouma.nineth.dto;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.izouma.nineth.domain.User;
+import com.izouma.nineth.enums.AuthStatus;
+import com.izouma.nineth.security.Authority;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Set;
+
 @Data
 public class UserDTO extends User {
 
-    private String password;
+    @ApiModelProperty("是否关注")
+    private boolean follow;
+
+    @Override
+    public String getPhone() {
+        return null;
+    }
 
-    private String nftAccount;
+    @Override
+    public String getPassword() {
+        return null;
+    }
 
-    private String kmsId;
+    @Override
+    public AuthStatus getAuthStatus() {
+        return null;
+    }
 
-    private String publicKey;
+    @Override
+    public Set<Authority> getAuthorities() {
+        return null;
+    }
 
-    private String tradeCode;
+    @Override
+    public LocalDateTime getCreatedAt() {
+        return null;
+    }
 
-    @ApiModelProperty("是否关注")
-    private boolean follow;
+    @Override
+    public String getNftAccount() {
+        return null;
+    }
+
+    @Override
+    public String getPublicKey() {
+        return null;
+    }
+
+    @Override
+    public String getTradeCode() {
+        return null;
+    }
+
+    @Override
+    public String getKmsId() {
+        return null;
+    }
+
+    @Override
+    public String getMemberId() {
+        return null;
+    }
+
+    @Override
+    public Long getAuthId() {
+        return null;
+    }
+
+    @Override
+    public BigDecimal getShareRatio() {
+        return null;
+    }
 
+    @Override
+    public String getSettleAccountId() {
+        return null;
+    }
 }

+ 9 - 1
src/main/java/com/izouma/nineth/listener/RegisterListener.java

@@ -17,6 +17,7 @@ import org.springframework.stereotype.Service;
 import java.time.Duration;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.regex.Pattern;
 
 @Service
 @Slf4j
@@ -44,7 +45,14 @@ public class RegisterListener implements RocketMQListener<RegisterEvent> {
             redisTemplate.opsForValue().set("register::" + registerEvent.getPhone(), map, Duration.ofSeconds(600));
         } catch (Exception e) {
             map.put("status", "fail");
-            map.put("data", e.getMessage());
+            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.put("data", message);
             redisTemplate.opsForValue().set("register::" + registerEvent.getPhone(), map, Duration.ofSeconds(600));
         }
     }

+ 12 - 7
src/main/java/com/izouma/nineth/listener/UpdateSaleListener.java

@@ -13,6 +13,8 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
+import java.util.Set;
+
 @Service
 @Slf4j
 @AllArgsConstructor
@@ -35,14 +37,17 @@ public class UpdateSaleListener implements RocketMQListener<Long> {
     @Scheduled(fixedRate = 10000)
     public void updateSale() {
         BoundHashOperations<String, String, Integer> ops = redisTemplate.boundHashOps(RedisKeys.UPDATE_SALE);
-        for (String id : ops.keys()) {
-            Long val = ops.increment(id, -1);
-            if (val <= 0) {
-                ops.delete(id);
-            } else if (val > 1) {
-                ops.put(id, 1);
+        Set<String> keys = ops.keys();
+        if (keys != null) {
+            for (String id : keys) {
+                Long val = ops.increment(id, -1);
+                if (val <= 0) {
+                    ops.delete(id);
+                } else if (val > 1) {
+                    ops.put(id, 1);
+                }
+                collectionService.syncSale(Long.parseLong(id));
             }
-            collectionService.syncSale(Long.parseLong(id));
         }
     }
 }

+ 27 - 2
src/main/java/com/izouma/nineth/listener/UpdateStockListener.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.listener;
 
+import com.izouma.nineth.config.RedisKeys;
 import com.izouma.nineth.service.CollectionService;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -7,8 +8,13 @@ import org.apache.rocketmq.spring.annotation.ConsumeMode;
 import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.redis.core.BoundHashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
+import java.util.Set;
+
 @Service
 @Slf4j
 @AllArgsConstructor
@@ -19,10 +25,29 @@ import org.springframework.stereotype.Service;
 @ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
 public class UpdateStockListener implements RocketMQListener<Long> {
 
-    private CollectionService collectionService;
+    private CollectionService             collectionService;
+    private RedisTemplate<String, Object> redisTemplate;
 
     @Override
     public void onMessage(Long id) {
-        collectionService.syncStock(id);
+        BoundHashOperations<String, String, Integer> ops = redisTemplate.boundHashOps(RedisKeys.UPDATE_STOCK);
+        ops.increment(id.toString(), 1);
+    }
+
+    @Scheduled(fixedRate = 10000)
+    public void updateSale() {
+        BoundHashOperations<String, String, Integer> ops = redisTemplate.boundHashOps(RedisKeys.UPDATE_STOCK);
+        Set<String> keys = ops.keys();
+        if (keys != null) {
+            for (String id : keys) {
+                Long val = ops.increment(id, -1);
+                if (val <= 0) {
+                    ops.delete(id);
+                } else if (val > 1) {
+                    ops.put(id, 1);
+                }
+                collectionService.syncStock(Long.parseLong(id));
+            }
+        }
     }
 }

+ 1 - 0
src/main/java/com/izouma/nineth/repo/CollectionRepo.java

@@ -153,4 +153,5 @@ public interface CollectionRepo extends JpaRepository<Collection, Long>, JpaSpec
     @Query("select c.assetId from Collection  c where c.price >= ?1 and c.source = ?2 and c.startTime <= ?3 and c.salable = ?4")
     Set<Long> findResaleCollectionPriceOver20K(BigDecimal price, CollectionSource source, LocalDateTime startTime, boolean salable);
 
+    List<Collection> findAllByNameLike(String name);
 }

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

@@ -45,4 +45,8 @@ public interface IdentityAuthRepo extends JpaRepository<IdentityAuth, Long>, Jpa
     @Modifying
     @Transactional
     int deleteDuplicated(Long userId, Long id);
+
+    List<IdentityAuth> findByUserIdInAndStatus(Iterable<Long> userId, AuthStatus status);
+
+    IdentityAuth findFirstByUserId(Long userId);
 }

+ 3 - 0
src/main/java/com/izouma/nineth/repo/OrderRepo.java

@@ -1,6 +1,7 @@
 package com.izouma.nineth.repo;
 
 import com.izouma.nineth.domain.Order;
+import com.izouma.nineth.enums.CollectionSource;
 import com.izouma.nineth.enums.OrderStatus;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -52,4 +53,6 @@ public interface OrderRepo extends JpaRepository<Order, Long>, JpaSpecificationE
             "where (status = 'FINISH' or status = 'PROCESSING') " +
             "group by user_id order by sum(price) desc limit 50")
     List<Object[]> sumPrice();
+
+    List<Order> findByCreatedAtBetweenAndSourceAndStatusIn(LocalDateTime start, LocalDateTime end, CollectionSource source, Collection<OrderStatus> statuses);
 }

+ 2 - 0
src/main/java/com/izouma/nineth/repo/UserBankCardRepo.java

@@ -11,6 +11,8 @@ import java.util.List;
 public interface UserBankCardRepo extends JpaRepository<UserBankCard, Long>, JpaSpecificationExecutor<UserBankCard> {
     List<UserBankCard> findByUserId(Long userId);
 
+    List<UserBankCard> findByUserIdIn(Iterable<Long> userId);
+
     @Transactional
     @Modifying
     int deleteByUserId(Long userId);

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

@@ -168,9 +168,9 @@ public interface UserRepo extends JpaRepository<User, Long>, JpaSpecificationExe
 
     int countAllByCollectionIdAndCollectionInvitor(Long collectionId, Long collectionInvitor);
 
-    long countAllByAuthoritiesContainsAndDelFalse(Authority authority);
+    long countAllByDelFalse();
 
-    List<User> findAllByCreatedAtIsAfterAndAuthoritiesContains(LocalDateTime createdAt, Authority authorities);
+    List<User> findAllByCreatedAtIsAfterAndAdminFalse(LocalDateTime createdAt);
 
     List<User> findBySettleAccountIdIsNotNull();
 

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

@@ -118,6 +118,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/testClass/**").permitAll()
                 .antMatchers("/appVersion/**").permitAll()
                 .antMatchers("/sandpay/**").permitAll()
+                .antMatchers("/order/calcSettle").permitAll()
                 // all other requests need to be authenticated
                 .anyRequest().authenticated().and()
                 // make sure we use stateless session; session won't be used to

+ 16 - 5
src/main/java/com/izouma/nineth/service/CaptchaService.java

@@ -1,7 +1,7 @@
 package com.izouma.nineth.service;
 
 import com.izouma.nineth.dto.Captcha;
-import com.wf.captcha.SpecCaptcha;
+import com.pig4cloud.captcha.ArithmeticCaptcha;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 import org.ehcache.UserManagedCache;
@@ -24,10 +24,21 @@ public class CaptchaService {
 
     public Captcha gen() throws IOException, FontFormatException {
         String key = UUID.randomUUID().toString();
-        SpecCaptcha specCaptcha = new SpecCaptcha(90 * 2, 32 * 2, 5);
-        specCaptcha.setFont(com.wf.captcha.base.Captcha.FONT_7, 24 * 2);
-        String code = specCaptcha.text().toLowerCase();
-        String image = specCaptcha.toBase64();
+//        SpecCaptcha specCaptcha = new SpecCaptcha(90 * 2, 32 * 2, 5);
+//        specCaptcha.setFont(com.wf.captcha.base.Captcha.FONT_7, 24 * 2);
+//        String code = specCaptcha.text().toLowerCase();
+//        String image = specCaptcha.toBase64();
+//        captchaCache.put(key, code);
+
+        // 算术类型
+        ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 48);
+        captcha.setFont(com.pig4cloud.captcha.base.Captcha.FONT_7, 24 * 2);
+        captcha.setLen(2);  // 几位数运算,默认是两位
+        captcha.getArithmeticString();  // 获取运算的公式:3+2=?
+        captcha.supportAlgorithmSign(2); // 可设置支持的算法:2 表示只生成带加减法的公式
+        captcha.setDifficulty(99); // 设置计算难度,参与计算的每一个整数的最大值
+        String code = captcha.text();  // 获取运算的结果:5
+        String image = captcha.toBase64();  // 输出验证码
         captchaCache.put(key, code);
         return new Captcha(key, image);
     }

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

@@ -87,34 +87,34 @@ public class CollectionService {
     @Cacheable(value = "collectionList", key = "#pageQuery.hashCode()")
     public PageWrapper<Collection> all(PageQuery pageQuery) {
         pageQuery.getQuery().put("del", false);
-        String type = MapUtils.getString(pageQuery.getQuery(), "type", "DEFAULT");
-        pageQuery.getQuery().remove("type");
+//        String type = MapUtils.getString(pageQuery.getQuery(), "type", "DEFAULT");
+//        pageQuery.getQuery().remove("type");
 
         Specification<Collection> specification = JpaUtils.toSpecification(pageQuery, Collection.class);
         PageRequest pageRequest = JpaUtils.toPageRequest(pageQuery);
-        if (pageRequest.getSort().stream().noneMatch(order -> order.getProperty().equals("createdAt"))) {
-            pageRequest = PageRequest.of(pageRequest.getPageNumber(), pageQuery.getSize(),
-                    pageRequest.getSort().and(Sort.by("createdAt").descending()));
-        }
-
-        specification = specification.and((Specification<Collection>) (root, criteriaQuery, criteriaBuilder) -> {
-            List<Predicate> and = new ArrayList<>();
-
-            if (StringUtils.isNotEmpty(type) && !"all".equalsIgnoreCase(type)) {
-                try {
-                    if (type.contains(",")) {
-                        and.add(root.get("type")
-                                .in(Arrays.stream(type.split(",")).map(s -> Enum.valueOf(CollectionType.class, s))
-                                        .collect(Collectors.toList())));
-                    } else {
-                        and.add(criteriaBuilder.equal(root.get("type"), Enum.valueOf(CollectionType.class, type)));
-                    }
-                } catch (Exception e) {
-
-                }
-            }
-            return criteriaBuilder.and(and.toArray(new Predicate[0]));
-        });
+//        if (pageRequest.getSort().stream().noneMatch(order -> order.getProperty().equals("createdAt"))) {
+//            pageRequest = PageRequest.of(pageRequest.getPageNumber(), pageQuery.getSize(),
+//                    pageRequest.getSort().and(Sort.by("createdAt").descending()));
+//        }
+
+//        specification = specification.and((Specification<Collection>) (root, criteriaQuery, criteriaBuilder) -> {
+//            List<Predicate> and = new ArrayList<>();
+//
+//            if (StringUtils.isNotEmpty(type) && !"all".equalsIgnoreCase(type)) {
+//                try {
+//                    if (type.contains(",")) {
+//                        and.add(root.get("type")
+//                                .in(Arrays.stream(type.split(",")).map(s -> Enum.valueOf(CollectionType.class, s))
+//                                        .collect(Collectors.toList())));
+//                    } else {
+//                        and.add(criteriaBuilder.equal(root.get("type"), Enum.valueOf(CollectionType.class, type)));
+//                    }
+//                } catch (Exception e) {
+//
+//                }
+//            }
+//            return criteriaBuilder.and(and.toArray(new Predicate[0]));
+//        });
         Page<Collection> page = collectionRepo.findAll(specification, pageRequest);
         return new PageWrapper<>(page.getContent(), page.getPageable().getPageNumber(),
                 page.getPageable().getPageSize(), page.getTotalElements());
@@ -416,7 +416,7 @@ public class CollectionService {
         return increaseSale(id, -number);
     }
 
-    @Debounce(key = "#id", delay = 500)
+//    @Debounce(key = "#id", delay = 500)
     public void syncStock(Long id) {
         Integer stock = (Integer) redisTemplate.opsForValue().get(RedisKeys.COLLECTION_STOCK + id);
         if (stock != null) {

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

@@ -5,6 +5,7 @@ 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.config.GeneralProperties;
 import com.izouma.nineth.domain.IdentityAuth;
 import com.izouma.nineth.domain.User;
 import com.izouma.nineth.dto.PageQuery;
@@ -44,6 +45,7 @@ public class IdentityAuthService {
     private Environment                   env;
     private SysConfigService              sysConfigService;
     private CacheService                  cacheService;
+    private GeneralProperties             generalProperties;
 
     public Page<IdentityAuth> all(PageQuery pageQuery) {
         return identityAuthRepo.findAll(JpaUtils.toSpecification(pageQuery, IdentityAuth.class), JpaUtils.toPageRequest(pageQuery));
@@ -202,6 +204,7 @@ public class IdentityAuthService {
     @Scheduled(fixedRate = 60000)
     @RedisLock(value = "autoValidate", expire = 30, unit = TimeUnit.MINUTES)
     public void autoValidate() {
+        if (generalProperties.isNotifyServer()) return;
         if (!sysConfigService.getBoolean("auto_validate")) return;
         log.info("autoValidate");
         if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
@@ -242,7 +245,7 @@ public class IdentityAuthService {
                 int count = identityAuthRepo.countByIdNoAndStatus(identityAuth.getIdNo(), AuthStatus.SUCCESS);
 
                 if (count >= 3) {
-                    result.put("status", AuthStatus.PENDING);
+                    result.put("status", AuthStatus.FAIL);
                     result.put("reason", "同一身份证注册超过3个");
                 } else {
                     try {

+ 31 - 26
src/main/java/com/izouma/nineth/service/MintOrderService.java

@@ -102,7 +102,6 @@ public class MintOrderService {
         MintOrder order = mintOrderRepo.save(MintOrder.builder()
                 .userId(userId)
                 .phone(user.getPhone())
-//                .material(materials)
                 .consume(true)
                 .status(MintOrderStatus.AIR_DROP)
                 .build());
@@ -158,21 +157,25 @@ public class MintOrderService {
      */
 //    @Transactional
     public MintOrder create(User user, List<Long> assetId, Long mintActivityId, Long addressId) {
-        try {
-
-            // 参加的活动
-            MintActivity mintActivity = mintActivityRepo.findByIdAndDelFalse(mintActivityId)
-                    .orElseThrow(new BusinessException("无此铸造活动"));
+        // 参加的活动
+        MintActivity mintActivity = mintActivityRepo.findByIdAndDelFalse(mintActivityId)
+                .orElseThrow(new BusinessException("无此铸造活动"));
 
-            if (mintActivity.isScheduleSale()) {
-                if (mintActivity.getStartTime().isAfter(LocalDateTime.now())) {
-                    throw new BusinessException("当前还未开售");
-                }
-            }
-            if (!mintActivity.isOnShelf()) {
-                throw new BusinessException("活动已下架");
+        if (mintActivity.isScheduleSale()) {
+            if (mintActivity.getStartTime().isAfter(LocalDateTime.now())) {
+                throw new BusinessException("当前还未开售");
             }
+        }
+        if (!mintActivity.isOnShelf()) {
+            throw new BusinessException("活动已下架");
+        }
 
+        UserAddress userAddress = null;
+        if (addressId != null) {
+            userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
+        }
+
+        try {
             int stock = Optional.ofNullable(mintActivityService.decreaseStock(mintActivityId, 1))
                     .map(Math::toIntExact)
                     .orElseThrow(new BusinessException("很遗憾,铸造活动已无库存"));
@@ -235,13 +238,16 @@ public class MintOrderService {
                     assetRepo.save(asset);
                 });
             } else {
+                // 转让的用户
+                userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
+
                 // 消耗改为转赠
                 assets.forEach(asset -> {
+                    if (!asset.getUserId().equals(user.getId())) {
+                        throw new BusinessException("此藏品不属于你");
+                    }
                     // 取消公开展示
                     if (asset.isPublicShow()) {
-                        if (!asset.getUserId().equals(user.getId())) {
-                            throw new BusinessException("此藏品不属于你");
-                        }
                         if (asset.isConsignment()) {
                             if (asset.getPublicCollectionId() != null) {
                                 List<Order> orders = orderRepo.findByCollectionId(asset.getPublicCollectionId());
@@ -256,21 +262,21 @@ public class MintOrderService {
                         collectionRepo.delete(collection);
                         // 如果展厅有此藏品
                         showCollectionRepo.deleteAllByCollectionId(asset.getPublicCollectionId());
+                    }
 
+                });
+
+                // 统一处理
+                assets.forEach(asset -> {
+                    if (asset.isPublicShow()) {
                         asset.setPublicShow(false);
                         asset.setPublicCollectionId(null);
                     }
                     asset.setStatus(AssetStatus.MINTING);
                     assetRepo.save(asset);
                 });
-                // 转让的用户
-                userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
             }
 
-            UserAddress userAddress = null;
-            if (addressId != null) {
-                userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
-            }
 
             // 铸造订单
             MintOrder mintOrder = mintOrderRepo.save(MintOrder.builder()
@@ -304,9 +310,9 @@ public class MintOrderService {
 
             mintMaterialRepo.saveAll(materials);
 
-            //销量
-//        mintActivityService.increaseSale(mintActivityId, 1);
-
+            if (mintOrder.getGasPrice().compareTo(BigDecimal.ZERO) == 0) {
+                this.mintNotify(mintOrder.getId(), PayMethod.WEIXIN, null);
+            }
             return mintOrder;
         } catch (Exception e) {
             // 错了加库存
@@ -541,7 +547,6 @@ public class MintOrderService {
 
             // 加库存
             mintActivityService.increaseStock(order.getMintActivityId(), 1);
-//        mintActivityService.decreaseSale(order.getMintActivityId(), 1);
 
             rocketMQTemplate.syncSend(generalProperties.getUpdateStockTopic(), order.getMintActivityId(), 10000);
             log.info("取消订单{}", order.getId());

+ 53 - 12
src/main/java/com/izouma/nineth/service/OrderService.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.service;
 
+import com.alibaba.excel.EasyExcel;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.serializer.SerializerFeature;
@@ -20,7 +21,9 @@ import com.huifu.adapay.model.Refund;
 import com.izouma.nineth.config.*;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.domain.*;
+import com.izouma.nineth.dto.MarketSettlement;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.UserBankCard;
 import com.izouma.nineth.enums.*;
 import com.izouma.nineth.event.CreateAssetEvent;
 import com.izouma.nineth.event.CreateOrderEvent;
@@ -34,6 +37,7 @@ import com.izouma.nineth.utils.AESEncryptUtil;
 import com.izouma.nineth.utils.JpaUtils;
 import com.izouma.nineth.utils.SecurityUtils;
 import com.izouma.nineth.utils.SnowflakeIdWorker;
+import com.izouma.nineth.utils.excel.ExcelUtils;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.EncoderException;
@@ -54,6 +58,8 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.ui.Model;
 
+import java.io.File;
+import java.io.OutputStream;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.Duration;
@@ -63,6 +69,7 @@ import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
@@ -94,6 +101,8 @@ public class OrderService {
     private ShowCollectionRepo            showCollectionRepo;
     private ShowroomService               showroomService;
     private CollectionPrivilegeRepo       collectionPrivilegeRepo;
+    private UserBankCardRepo              userBankCardRepo;
+    private IdentityAuthRepo              identityAuthRepo;
 
     public Page<Order> all(PageQuery pageQuery) {
         return orderRepo.findAll(JpaUtils.toSpecification(pageQuery, Order.class), JpaUtils.toPageRequest(pageQuery));
@@ -112,18 +121,18 @@ public class OrderService {
             throw new BusinessException("签名已过期");
         }
 
-//        if (redisTemplate.opsForValue().get(RedisKeys.BLACK_LIST + userId) != null) {
-//            throw new BusinessException("频繁操作,请稍后再试");
-//        }
-//        BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.LIMIT_USER + userId);
-//        ops.setIfAbsent(0, Duration.ofSeconds(10));
-//        long val = Optional.ofNullable(ops.increment()).orElse(0L);
-//        if (val > 5) {
-//            if (val > 10) {
-//                redisTemplate.opsForValue().set(RedisKeys.BLACK_LIST + userId, 1, Duration.ofSeconds(60 * 10));
-//            }
-//            throw new BusinessException("频繁操作,请稍后再试");
-//        }
+        if (redisTemplate.opsForValue().get(RedisKeys.BLACK_LIST + userId) != null) {
+            throw new BusinessException("频繁操作,请稍后再试");
+        }
+        BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.LIMIT_USER + userId);
+        ops.setIfAbsent(0, Duration.ofSeconds(10));
+        long val = Optional.ofNullable(ops.increment()).orElse(0L);
+        if (val > 5) {
+            if (val > 10) {
+                redisTemplate.opsForValue().set(RedisKeys.BLACK_LIST + userId, 1, Duration.ofSeconds(60 * 10));
+            }
+            throw new BusinessException("频繁操作,请稍后再试");
+        }
 
         limitReq(collectionId);
 
@@ -911,4 +920,36 @@ public class OrderService {
     public void releaseOrderLock(Long orderId) {
         redisTemplate.delete(RedisKeys.ORDER_LOCK + orderId);
     }
+
+    public void calcSettle(LocalDateTime start, LocalDateTime end, OutputStream outputStream) {
+        List<Order> orders = orderRepo.findByCreatedAtBetweenAndSourceAndStatusIn(start, end, CollectionSource.TRANSFER, Arrays.asList(OrderStatus.PROCESSING, OrderStatus.FINISH));
+        List<Asset> assets = assetRepo.findAllById(orders.stream().map(Order::getAssetId).collect(Collectors.toSet()));
+        List<UserBankCard> bankCards = userBankCardRepo.findByUserIdIn(assets.stream().map(Asset::getUserId).collect(Collectors.toSet()));
+        List<MarketSettlement> settlements = new ArrayList<>();
+        for (Order order : orders) {
+            BigDecimal amount = order.getTotalPrice()
+                    .subtract(order.getGasPrice())
+                    .multiply(new BigDecimal("100")
+                            .subtract(BigDecimal.valueOf(order.getServiceCharge()))
+                            .subtract(BigDecimal.valueOf(order.getRoyalties()))
+                            .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP))
+                    .setScale(2, RoundingMode.HALF_UP);
+            Long userId = assets.stream().filter(a -> a.getId().equals(order.getAssetId())).map(Asset::getUserId).findAny().orElse(null);
+            if (userId != null) {
+                UserBankCard userBankCard = bankCards.stream().filter(b -> b.getUserId().equals(userId)).findAny().orElse(null);
+                MarketSettlement marketSettlement = settlements.stream().filter(s -> s.getUserId().equals(userId)).findAny().orElse(null);
+                if (marketSettlement == null) {
+                    marketSettlement = new MarketSettlement(userId,
+                            Optional.ofNullable(userBankCard).map(UserBankCard::getRealName).orElse(null),
+                            Optional.ofNullable(userBankCard).map(UserBankCard::getBankNo).orElse(null),
+                            amount);
+                    settlements.add(marketSettlement);
+                } else {
+                    marketSettlement.setAmount(marketSettlement.getAmount()
+                            .add(amount));
+                }
+            }
+        }
+        EasyExcel.write(outputStream, MarketSettlement.class).sheet("sheet").doWrite(settlements);
+    }
 }

+ 46 - 0
src/main/java/com/izouma/nineth/service/SandPayService.java

@@ -4,10 +4,13 @@ import cn.com.sandpay.cashier.sdk.*;
 import com.alibaba.fastjson.JSONObject;
 import com.izouma.nineth.config.SandPayProperties;
 import com.izouma.nineth.domain.GiftOrder;
+import com.izouma.nineth.domain.MintOrder;
 import com.izouma.nineth.domain.Order;
+import com.izouma.nineth.enums.MintOrderStatus;
 import com.izouma.nineth.enums.OrderStatus;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.GiftOrderRepo;
+import com.izouma.nineth.repo.MintOrderRepo;
 import com.izouma.nineth.repo.OrderRepo;
 import com.izouma.nineth.utils.DateTimeUtils;
 import lombok.AllArgsConstructor;
@@ -37,6 +40,7 @@ public class SandPayService {
     private final OrderRepo         orderRepo;
     private final GiftOrderRepo     giftOrderRepo;
     private final SandPayProperties sandPayProperties;
+    private final MintOrderRepo     mintOrderRepo;
 
     public JSONObject requestServer(JSONObject header, JSONObject body, String reqAddr) {
 
@@ -165,6 +169,14 @@ public class SandPayService {
         if (res == null)
             throw new BusinessException("下单失败,请稍后再试");
 
+        if (!"000000".equals(res.getJSONObject("head").getString("respCode"))) {
+            String msg = res.getJSONObject("head").getString("respMsg");
+            if (msg.contains("超限")) {
+                throw new BusinessException("超过商户单日额度");
+            }
+            throw new BusinessException(msg);
+        }
+
         return res.getJSONObject("body").getString("qrCode");
     }
 
@@ -183,6 +195,40 @@ public class SandPayService {
         if (res == null)
             throw new BusinessException("下单失败,请稍后再试");
 
+        if (!"000000".equals(res.getJSONObject("head").getString("respCode"))) {
+            String msg = res.getJSONObject("head").getString("respMsg");
+            if (msg.contains("超限")) {
+                throw new BusinessException("超过商户单日额度");
+            }
+            throw new BusinessException(msg);
+        }
+
+        return res.getJSONObject("body").getString("qrCode");
+    }
+
+    @Cacheable(value = "sandPay", key = "#orderId")
+    public String payMintOrder(Long orderId) {
+        MintOrder order = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
+        if (order.getStatus() != MintOrderStatus.NOT_PAID) {
+            throw new BusinessException("订单状态错误");
+        }
+        JSONObject extend = new JSONObject();
+        extend.put("type", "mintOrder");
+        extend.put("id", orderId);
+
+        JSONObject res = requestAlipay(orderId.toString(), order.getGasPrice(), "铸造活动:" + order.getMintActivityId(),
+                "铸造活动:" + order.getMintActivityId(), order.getCreatedAt().plusMinutes(3), extend.toJSONString());
+        if (res == null)
+            throw new BusinessException("下单失败,请稍后再试");
+
+        if (!"000000".equals(res.getJSONObject("head").getString("respCode"))) {
+            String msg = res.getJSONObject("head").getString("respMsg");
+            if (msg.contains("超限")) {
+                throw new BusinessException("超过商户单日额度");
+            }
+            throw new BusinessException(msg);
+        }
+
         return res.getJSONObject("body").getString("qrCode");
     }
 }

+ 2 - 4
src/main/java/com/izouma/nineth/service/StatisticService.java

@@ -4,13 +4,11 @@ import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.izouma.nineth.domain.Order;
 import com.izouma.nineth.domain.User;
-import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.enums.CollectionSource;
 import com.izouma.nineth.enums.OrderStatus;
 import com.izouma.nineth.repo.OrderRepo;
 import com.izouma.nineth.repo.TokenHistoryRepo;
 import com.izouma.nineth.repo.UserRepo;
-import com.izouma.nineth.security.Authority;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 
@@ -35,7 +33,7 @@ public class StatisticService {
     public Map<String, Object> total() {
         Map<String, Object> total = new HashMap<>();
 
-        long user = userRepo.countAllByAuthoritiesContainsAndDelFalse(Authority.get(AuthorityName.ROLE_USER));
+        long user = userRepo.countAllByDelFalse();
         total.put("userNum", user);
 
         List<Order> orders = orderRepo.findAllByStatus(OrderStatus.FINISH);
@@ -63,7 +61,7 @@ public class StatisticService {
     public Map<String, Long> userTrend(int day) {
         LocalDateTime date = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
         LocalDateTime start = date.minusDays(day);
-        List<User> users = userRepo.findAllByCreatedAtIsAfterAndAuthoritiesContains(start, Authority.get(AuthorityName.ROLE_USER));
+        List<User> users = userRepo.findAllByCreatedAtIsAfterAndAdminFalse(start);
         return users.stream().collect(Collectors.groupingBy(
                 item -> DateTimeFormatter.ofPattern("yyyy-MM-dd").format(item.getCreatedAt()), Collectors.counting()));
     }

+ 27 - 1
src/main/java/com/izouma/nineth/service/UserService.java

@@ -99,7 +99,6 @@ public class UserService {
         userRepo.updateHistoryToUser(orig.getId());
         userRepo.updateShowroomToUser(orig.getId());
         cacheService.clearCollection();
-        cacheService.clearUserMy(user.getId());
         return orig;
     }
 
@@ -110,6 +109,33 @@ public class UserService {
         return userRepo.save(user);
     }
 
+    public User update(Long userId, String nickname, String avatar, String sex, String bg, String intro,
+                       Boolean useCollectionPic, Boolean riskWarning, Integer level) {
+        User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在"));
+        if (StringUtils.isNotBlank(nickname)) {
+            user.setNickname(nickname);
+        }
+        if (StringUtils.isNotBlank(avatar)) {
+            user.setAvatar(avatar);
+        }
+        if (StringUtils.isNotBlank(sex)) {
+            user.setSex(sex);
+        }
+        if (StringUtils.isNotBlank(bg)) {
+            user.setBg(bg);
+        }
+        if (StringUtils.isNotBlank(intro)) {
+            user.setIntro(intro);
+        }
+        if (useCollectionPic != null) {
+            user.setUseCollectionPic(useCollectionPic);
+        }
+        if (riskWarning != null) {
+            user.setRiskWarning(riskWarning);
+        }
+        return save(user);
+    }
+
     @Cacheable(value = "userList", key = "#pageQuery.hashCode()")
     public PageWrapper<User> all(PageQuery pageQuery) {
         Specification<User> specification = JpaUtils.toSpecification(pageQuery, User.class);

+ 2 - 0
src/main/java/com/izouma/nineth/web/AssetController.java

@@ -50,6 +50,7 @@ public class AssetController extends BaseController {
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<Asset> all(@RequestBody PageQuery pageQuery) {
+        pageQuery.getQuery().put("userId",SecurityUtils.getAuthenticatedUser().getId());
         return assetService.all(pageQuery);
     }
 
@@ -65,6 +66,7 @@ public class AssetController extends BaseController {
 //        assetRepo.softDelete(id);
 //    }
 
+    @PreAuthorize("hasRole('ADMIN')")
     @GetMapping("/excel")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {

+ 5 - 3
src/main/java/com/izouma/nineth/web/CollectionController.java

@@ -64,7 +64,7 @@ public class CollectionController extends BaseController {
     @PostMapping("/create")
     public Collection create(@RequestBody CollectionInfoDTO record) {
         Collection collection = new Collection();
-        BeanUtils.copyProperties(record,collection);
+        BeanUtils.copyProperties(record, collection);
         collection = collectionService.create(collection);
         CollectionPrivilege collectionPrivilege = new CollectionPrivilege();
         BeanUtils.copyProperties(record, collectionPrivilege);
@@ -176,14 +176,16 @@ public class CollectionController extends BaseController {
             collectionDTO.setPrivileges(null);
             collectionDTO.setProperties(null);
 
-            return new RecommendDTO(rc.getRecommend().getSort(), collectionDTO, "collection");
+            return new RecommendDTO(rc.getRecommend().getSort(), collectionDTO, "collection", rc.getRecommend()
+                    .getCreatedAt());
         }).collect(Collectors.toList());
 
         List<RecommendDTO> news = newsRepo.recommend("LIST").stream().map(rn -> {
             if (StringUtils.isNotBlank(rn.getRecommend().getPic())) {
                 rn.getNews().setPic(rn.getRecommend().getPic());
             }
-            return new RecommendDTO(rn.getRecommend().getSort(), rn.getNews(), "news");
+            return new RecommendDTO(rn.getRecommend().getSort(), rn.getNews(), "news", rn.getRecommend()
+                    .getCreatedAt());
         }).collect(Collectors.toList());
 
         recommedDTOS.addAll(collectionDTOS);

+ 2 - 1
src/main/java/com/izouma/nineth/web/DevelopController.java

@@ -3,6 +3,7 @@ package com.izouma.nineth.web;
 import com.izouma.nineth.utils.ObjUtils;
 import org.reflections.Reflections;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.method.HandlerMethod;
 import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
@@ -17,7 +18,7 @@ import java.util.*;
 
 @RestController
 @RequestMapping("/dev")
-// @PreAuthorize("hasRole('ROLE_ADMIN') and hasRole('ROLE_DEV')")
+@PreAuthorize("hasRole('ADMIN')")
 public class DevelopController {
     @Autowired
     private RequestMappingHandlerMapping requestMappingHandlerMapping;

+ 2 - 0
src/main/java/com/izouma/nineth/web/GenCodeController.java

@@ -12,6 +12,7 @@ import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.text.CaseUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.*;
@@ -23,6 +24,7 @@ import java.util.regex.Pattern;
 
 @RestController
 @RequestMapping("/genCode")
+@PreAuthorize("hasRole('ADMIN')")
 public class GenCodeController {
     @Autowired
     private GenCodeService genCodeService;

+ 8 - 1
src/main/java/com/izouma/nineth/web/IdentityAuthController.java

@@ -27,7 +27,7 @@ public class IdentityAuthController extends BaseController {
     private IdentityAuthService identityAuthService;
     private IdentityAuthRepo    identityAuthRepo;
 
-    //    @PreAuthorize("hasAnyRole('ADMIN','OPERATOR')")
+    @PreAuthorize("hasAnyRole('ADMIN','OPERATOR')")
     @PostMapping("/all")
     public Page<IdentityAuth> all(@RequestBody PageQuery pageQuery) {
         return identityAuthService.all(pageQuery);
@@ -71,6 +71,7 @@ public class IdentityAuthController extends BaseController {
         identityAuthService.audit(id, AuthStatus.FAIL, reason);
     }
 
+    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
     @ApiOperation("查找重复身份证")
     @PostMapping("/repeat")
     public List<User> repeat(@RequestParam String idNo, @RequestParam Long userId) {
@@ -82,6 +83,7 @@ public class IdentityAuthController extends BaseController {
         identityAuthService.removeDuplicated();
     }
 
+    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
     @PostMapping("/autoAuth")
     public Object authAuth(@RequestParam Long id) {
         IdentityAuth identityAuth = identityAuthRepo.findById(id).orElseThrow(new BusinessException("无记录"));
@@ -89,5 +91,10 @@ public class IdentityAuthController extends BaseController {
         identityAuthService.audit(identityAuth.getId(), (AuthStatus) map.get("status"), (String) map.get("reason"));
         return map;
     }
+
+    @PostMapping("/my")
+    public IdentityAuth my(){
+        return identityAuthRepo.findFirstByUserId(SecurityUtils.getAuthenticatedUser().getId());
+    }
 }
 

+ 23 - 0
src/main/java/com/izouma/nineth/web/OrderController.java

@@ -4,6 +4,7 @@ import com.izouma.nineth.domain.Order;
 import com.izouma.nineth.domain.User;
 import com.izouma.nineth.dto.OrderDTO;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.enums.CollectionType;
 import com.izouma.nineth.enums.OrderStatus;
 import com.izouma.nineth.enums.PayMethod;
@@ -11,6 +12,7 @@ import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.OrderRepo;
 import com.izouma.nineth.repo.UserRepo;
 import com.izouma.nineth.service.OrderService;
+import com.izouma.nineth.utils.DateTimeUtils;
 import com.izouma.nineth.utils.SecurityUtils;
 import com.izouma.nineth.utils.SnowflakeIdWorker;
 import com.izouma.nineth.utils.excel.ExcelUtils;
@@ -22,6 +24,8 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -51,6 +55,9 @@ public class OrderController extends BaseController {
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<Order> all(@RequestBody PageQuery pageQuery) {
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN)) {
+            pageQuery.getQuery().put("userId", SecurityUtils.getAuthenticatedUser().getId());
+        }
         return orderService.all(pageQuery);
     }
 
@@ -164,5 +171,21 @@ public class OrderController extends BaseController {
     public void cancel(@RequestParam Long id) {
         orderService.cancel(id);
     }
+
+    @GetMapping(value = "/calcSettle")
+    public void calcSettle(LocalDateTime start, LocalDateTime end, HttpServletResponse response) {
+        if (start == null && end == null) {
+            start = LocalDate.now().minusDays(1).atStartOfDay();
+            end = LocalDate.now().minusDays(1).atTime(23, 59, 59, 99999);
+        }
+        try {
+            response.setContentType("application/vnd.ms-excel");
+            response.setCharacterEncoding("utf-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + DateTimeUtils.format(LocalDateTime.now(), "MMdd") + ".xlsx");
+            orderService.calcSettle(start, end, response.getOutputStream());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
 }
 

+ 5 - 3
src/main/java/com/izouma/nineth/web/OrderPayController.java

@@ -109,7 +109,7 @@ public class OrderPayController {
     @RequestMapping(value = "/gift/alipay_wx", method = RequestMethod.GET)
     public String payGiftOrderAlipayWx(Long id, Model model) throws BaseAdaPayException {
 //        String payUrl = (String) giftOrderService.payAdapay(id, "alipay_wap", null);
-        String payUrl = sandPayService.payGiftOrder(id);;
+        String payUrl = sandPayService.payGiftOrder(id);
         model.addAttribute("payUrl", payUrl);
         model.addAttribute("orderId", id);
         return "AlipayHtml";
@@ -152,12 +152,14 @@ public class OrderPayController {
     @RequestMapping(value = "/mint/alipay_h5", method = RequestMethod.GET)
     @ResponseBody
     public String payMintOrderAlipayH5(Long id, Model model) throws BaseAdaPayException {
-        return (String) mintOrderService.payAdapay(id, "alipay_wap", null);
+//        return (String) mintOrderService.payAdapay(id, "alipay_wap", null);
+        return sandPayService.payMintOrder(id);
     }
 
     @RequestMapping(value = "/mint/alipay_wx", method = RequestMethod.GET)
     public String payMintOrderAlipayWx(Long id, Model model) throws BaseAdaPayException {
-        String payUrl = (String) mintOrderService.payAdapay(id, "alipay_wap", null);
+//        String payUrl = (String) mintOrderService.payAdapay(id, "alipay_wap", null);
+        String payUrl = sandPayService.payMintOrder(id);
         model.addAttribute("payUrl", payUrl);
         model.addAttribute("orderId", id);
         return "AlipayHtml2";

+ 4 - 0
src/main/java/com/izouma/nineth/web/SandPayController.java

@@ -7,6 +7,7 @@ import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.enums.PayMethod;
 import com.izouma.nineth.event.OrderNotifyEvent;
 import com.izouma.nineth.service.GiftOrderService;
+import com.izouma.nineth.service.MintOrderService;
 import com.izouma.nineth.service.OrderService;
 import com.izouma.nineth.service.SandPayService;
 import com.izouma.nineth.utils.SnowflakeIdWorker;
@@ -36,6 +37,7 @@ public class SandPayController {
     private GeneralProperties generalProperties;
     private RocketMQTemplate  rocketMQTemplate;
     private GiftOrderService  giftOrderService;
+    private MintOrderService  mintOrderService;
 
     @GetMapping(value = "/testpay", produces = "text/html")
     private String testpay() {
@@ -83,6 +85,8 @@ public class SandPayController {
                             case "gift":
                                 giftOrderService.giftNotify(id, PayMethod.ALIPAY, payOrderCode);
                                 break;
+                            case "mintOrder":
+                                mintOrderService.mintNotify(id, PayMethod.ALIPAY, payOrderCode);
                         }
                     }
                     return "respCode=000000";

+ 3 - 1
src/main/java/com/izouma/nineth/web/SettingController.java

@@ -28,7 +28,7 @@ public class SettingController extends BaseController {
     private SettingRepo    settingRepo;
     private CacheService   cacheService;
 
-    //@PreAuthorize("hasRole('ADMIN')")
+    @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
     public Setting save(@RequestBody Setting record) {
         if (record.getId() != null) {
@@ -59,11 +59,13 @@ public class SettingController extends BaseController {
         return settingRepo.findById(id).orElseThrow(new BusinessException("无记录"));
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/del/{id}")
     public void del(@PathVariable Long id) {
         settingRepo.softDelete(id);
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
     @GetMapping("/excel")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {

+ 2 - 0
src/main/java/com/izouma/nineth/web/ShowroomController.java

@@ -17,6 +17,7 @@ import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.data.domain.Page;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
@@ -86,6 +87,7 @@ public class ShowroomController extends BaseController {
         return showroom;
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/del/{id}")
     public void del(@PathVariable Long id) {
         showCollectionRepo.deleteAllByShowroomId(id);

+ 13 - 1
src/main/java/com/izouma/nineth/web/SmsController.java

@@ -2,6 +2,7 @@ package com.izouma.nineth.web;
 
 import com.izouma.nineth.config.Constants;
 import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.service.CaptchaService;
 import com.izouma.nineth.service.sms.SmsService;
 import lombok.AllArgsConstructor;
 import org.springframework.data.redis.core.RedisTemplate;
@@ -16,16 +17,27 @@ import java.util.regex.Pattern;
 @RequestMapping("/sms")
 @AllArgsConstructor
 public class SmsController {
-    private SmsService                    smsService;
+    private SmsService     smsService;
+    private CaptchaService captchaService;
 
     @GetMapping("/sendVerify")
     public String sendVerify(@RequestParam String phone) {
+        //throw new BusinessException("此接口已停用,请重启APP或刷新网页");
         if (!Pattern.matches(Constants.Regex.PHONE, phone)) {
             throw new BusinessException("请输入正确的手机号");
         }
         return smsService.sendVerify(phone);
     }
 
+    @GetMapping("/sendSecureVerify")
+    public String sendVerify(@RequestParam String phone, @RequestParam String captcha, @RequestParam String captchaKey) {
+        if (!Pattern.matches(Constants.Regex.PHONE, phone)) {
+            throw new BusinessException("请输入正确的手机号");
+        }
+        captchaService.verify(captchaKey, captcha);
+        return smsService.sendVerify(phone);
+    }
+
     @GetMapping("/verify")
     public String verify(@RequestParam String phone, @RequestParam String code) throws SmsService.SmsVerifyException {
         return smsService.verify(phone, code);

+ 7 - 2
src/main/java/com/izouma/nineth/web/StatisticController.java

@@ -26,30 +26,35 @@ public class StatisticController {
 
     @GetMapping("/total")
     @Cacheable("total")
+    @PreAuthorize("hasRole('ADMIN')")
     public Map<String, Object> total() {
         return statisticService.total();
     }
 
     @GetMapping("/userTrend")
     @Cacheable("userTrend")
+    @PreAuthorize("hasRole('ADMIN')")
     public Map<String, Long> userTrend(int day) {
         return statisticService.userTrend(day);
     }
 
     @GetMapping("/orderNumTrend")
     @Cacheable("orderNumTrend")
+    @PreAuthorize("hasRole('ADMIN')")
     public Map<String, Map<String, Long>> orderNumTrend(int day) {
         return statisticService.orderNumTrend(day);
     }
 
     @GetMapping("/orderPriceTrend")
     @Cacheable("orderPriceTrend")
+    @PreAuthorize("hasRole('ADMIN')")
     public Map<String, Map<String, BigDecimal>> orderPriceTrend(int day) {
         return statisticService.orderPriceTrend(day);
     }
 
     @GetMapping("/top")
     @CachePut(value = "top", key = "#month")
+    @PreAuthorize("hasRole('ADMIN')")
     public String top(int year, int month) {
         LocalDateTime start = LocalDateTime.of(year, month, 1, 0, 0, 0);
         LocalDateTime end = start.plusMonths(1).minusSeconds(1);
@@ -73,13 +78,13 @@ public class StatisticController {
 
     @PreAuthorize("hasRole('ADMIN')")
     @GetMapping("/clearWeekTop")
-    public void clearWeekTop(){
+    public void clearWeekTop() {
         cacheService.clearWeekTop();
     }
 
     @PreAuthorize("hasRole('ADMIN')")
     @GetMapping("/clearUser")
-    public void clearUser(){
+    public void clearUser() {
         cacheService.clearUser();
     }
 }

+ 22 - 4
src/main/java/com/izouma/nineth/web/UserController.java

@@ -57,7 +57,7 @@ public class UserController extends BaseController {
         return userService.create(userRegister);
     }
 
-
+    @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
     public User save(@RequestBody User user) {
         if (user.getId() != null) {
@@ -66,6 +66,13 @@ public class UserController extends BaseController {
         return userService.save(user);
     }
 
+    @PostMapping("/update")
+    public User update(String nickname, String avatar, String sex, String bg, String intro,
+                       Boolean useCollectionPic, Boolean riskWarning, Integer level) {
+        return userService.update(SecurityUtils.getAuthenticatedUser().getId(),
+                nickname, avatar, sex, bg, intro, useCollectionPic, riskWarning, level);
+    }
+
     @GetMapping("/my")
     public User my() {
         return userService.my(SecurityUtils.getAuthenticatedUser().getId());
@@ -81,12 +88,17 @@ public class UserController extends BaseController {
     //    @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<UserDTO> all(@RequestBody PageQuery pageQuery) {
-        if (!(SecurityUtils.getAuthenticatedUser() != null && SecurityUtils.getAuthenticatedUser().isAdmin())) {
-            pageQuery.getQuery().put("minter", true);
-        }
+        pageQuery.getQuery().put("minter", true);
+        if (pageQuery.getSize() > 100) pageQuery.setSize(100);
         return userService.toDTO(userService.all(pageQuery).toPage());
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/adminAll")
+    public Page<User> adminAll(@RequestBody PageQuery pageQuery) {
+        return userService.all(pageQuery).toPage();
+    }
+
     @PostMapping("/minterList")
     public Page<Minter> toMinter(@RequestBody PageQuery pageQuery) {
         pageQuery.getQuery().put("minter", true);
@@ -99,6 +111,12 @@ public class UserController extends BaseController {
         return userService.toDTO(userRepo.findById(id).orElseThrow(new BusinessException("无记录")), true);
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/adminGet/{id}")
+    public User adminGet(@PathVariable Long id) {
+        return userRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
     @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/del/{id}")
     public void del(@PathVariable Long id) {

+ 9 - 7
src/main/resources/application.yaml

@@ -25,8 +25,10 @@ spring:
         max_idle: 50
         min_idle: 0
   datasource:
-    url: jdbc:mysql://rm-wz9sc79f5255780opqo.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
-    username: raex_server
+#    url: jdbc:mysql://rm-wz9sc79f5255780opqo.mysql.rds.aliyuncs.com/raex?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
+#    username: raex_server
+    url: jdbc:mysql://rm-wz9q65wzuf8c56647ro.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
+    username: raex_test
     password: tetQsjw!u4!c5$URduo7BH
     hikari:
       minimum-idle: 20
@@ -238,8 +240,8 @@ spring:
     activate:
       on-profile: test
   datasource:
-    url: jdbc:mysql://rm-wz9sc79f5255780op.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&useLocalSessionState=true
-    username: raex_server
+    url: jdbc:mysql://rm-wz9q65wzuf8c56647.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&useLocalSessionState=true
+    username: raex_test
     password: tetQsjw!u4!c5$URduo7BH
   redis:
     host: 127.0.0.1
@@ -438,8 +440,8 @@ spring:
     activate:
       on-profile: notifytest
   datasource:
-    url: jdbc:mysql://rm-wz9sc79f5255780opqo.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
-    username: raex_server
+    url: jdbc:mysql://rm-wz9q65wzuf8c56647.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
+    username: raex_test
     password: tetQsjw!u4!c5$URduo7BH
   redis:
     host: 172.31.215.239
@@ -479,7 +481,7 @@ spring:
     activate:
       on-profile: staging
   datasource:
-    url: jdbc:mysql://rm-wz9q65wzuf8c56647ro.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
+    url: jdbc:mysql://rm-wz9q65wzuf8c56647.mysql.rds.aliyuncs.com/raex_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
     username: raex_test
     password: tetQsjw!u4!c5$URduo7BH
   redis:

+ 2 - 2
src/main/resources/logback-spring.xml

@@ -16,8 +16,8 @@
         <logger name="io.swagger.models.parameters.AbstractSerializableParameter" level="ERROR"/>
         <logger name="org.freemarker" level="DEBUG"/>
 
-<!--        <logger name="druid.sql.Statement" level="debug">-->
-<!--        </logger>-->
+        <logger name="druid.sql.Statement" level="debug">
+        </logger>
 <!--        <logger name="druid.sql.DataSource" level="debug">-->
 <!--        </logger>-->
 <!--        <logger name="druid.sql.Connection" level="debug">-->

+ 2 - 0
src/main/resources/templates/Privacy.ftlh

@@ -15,6 +15,8 @@
 <body>
   <div class="page-container">
     <h1 class="align-center">${properties.name}隐私政策</h1>
+    <h4>生效时间【2022-04-11】</h4>
+    <h4>更新时间【2022-04-11】</h4>
     <p class="text-content">
       ${properties.org}(以下称“我们”或“公司”)深知个人信息安全的重要性,我们将按照法律法规要求,采用安全保护措施,保护您的个人信息及隐私安全。因此,我们制定《${properties.name}隐私政策》(以下简称“《隐私政策》”)并提醒您:在使用“${properties.name}”及相关服务(定义同《${properties.name}用户协议》)前,请务必仔细阅读并透彻理解本《隐私政策》,在确认充分理解并同意后,按照指引作出您的适当选择。
     </p>

+ 2 - 0
src/main/resources/templates/Service.ftlh

@@ -15,6 +15,8 @@
 <body>
   <div class="page-container">
     <h1 class="align-center">${properties.name}服务协议</h1>
+    <h4>生效时间【2022-04-11】</h4>
+    <h4>更新时间【2022-04-11】</h4>
     <p class="text-content">欢迎您使用${properties.name}数字商品服务!</p>
     <p class="text-content">为使用${properties.name}数字商品服务(简称“本服务”),您应当阅读并遵守《${properties.name}数字商品服务协议》(以下简称“本协议”)、
       <a href="privacy.html" target="_blank" rel="noopener noreferrer">《${properties.name}隐私政策》</a>

+ 2 - 2
src/main/vue/src/components/CollectionCoupon.vue

@@ -16,7 +16,7 @@ export default {
                 '/collection/all',
                 {
                     sort: 'sort,desc;createdAt,desc',
-                    query: { del: false, source: 'OFFICIAL', type: 'all', couponPayment: true }
+                    query: { del: false, source: 'OFFICIAL', couponPayment: true }
                 },
                 { body: 'json' }
             )
@@ -40,7 +40,7 @@ export default {
                     {
                         sort: 'sort,desc;createdAt,desc',
                         search: query,
-                        query: { del: false, source: 'OFFICIAL', type: 'all', couponPayment: true }
+                        query: { del: false, source: 'OFFICIAL', couponPayment: true }
                     },
                     { body: 'json' }
                 )

+ 2 - 2
src/main/vue/src/components/CollectionSearch.vue

@@ -16,7 +16,7 @@ export default {
                 '/collection/all',
                 {
                     sort: 'sort,desc;createdAt,desc',
-                    query: { del: false, source: 'OFFICIAL', type: 'all' }
+                    query: { del: false, source: 'OFFICIAL' }
                 },
                 { body: 'json' }
             )
@@ -40,7 +40,7 @@ export default {
                     {
                         sort: 'sort,desc;createdAt,desc',
                         search: query,
-                        query: { del: false, source: 'OFFICIAL', type: 'all' }
+                        query: { del: false, source: 'OFFICIAL' }
                     },
                     { body: 'json' }
                 )

+ 1 - 1
src/main/vue/src/views/AdminList.vue

@@ -71,7 +71,7 @@ export default {
         return {
             multipleMode: false,
             search: '',
-            url: '/user/all',
+            url: '/user/adminAll',
             downloading: false
         };
     },

+ 48 - 33
src/main/vue/src/views/BlindBoxEdit.vue

@@ -14,7 +14,7 @@
                     label-width="100px"
                     label-position="right"
                     size="small"
-                    style="max-width: 500px"
+                    style="max-width: 500px;"
                 >
                     <el-form-item prop="name" label="名称">
                         <el-input v-model="formData.name" :disabled="!canEdit"></el-input>
@@ -40,10 +40,10 @@
                             <el-option v-for="item in cateogories" :label="item" :value="item" :key="item"></el-option>
                         </el-select>
                     </el-form-item>
-                    <el-form-item prop="detail" label="详情" style="width: calc(100vw - 450px)">
+                    <el-form-item prop="detail" label="详情" style="width: calc(100vw - 450px);">
                         <rich-text v-model="formData.detail"></rich-text>
                     </el-form-item>
-                    <el-form-item prop="properties" label="特性" style="width: calc(100vw - 450px)" size="mini">
+                    <el-form-item prop="properties" label="特性" style="width: calc(100vw - 450px);" size="mini">
                         <el-table :data="formData.properties">
                             <el-table-column prop="name" label="名称">
                                 <template v-slot="{ row }">
@@ -56,7 +56,7 @@
                                 </template>
                             </el-table-column>
                             <el-table-column width="80" align="center">
-                                <template v-slot="{ row, $index }">
+                                <template v-slot="{ $index }">
                                     <el-button type="danger" plain size="mini" @click="delProperty($index)">
                                         删除
                                     </el-button>
@@ -67,7 +67,7 @@
                     <el-form-item>
                         <el-button size="mini" @click="addProperty"> 添加特性 </el-button>
                     </el-form-item>
-                    <el-form-item label="特权" prop="privileges" style="width: calc(100vw - 450px)">
+                    <el-form-item label="特权" prop="privileges" style="width: calc(100vw - 450px);">
                         <el-table :data="privilegeOptions">
                             <el-table-column prop="name" label="可选特权" width="150"></el-table-column>
                             <el-table-column prop="description"></el-table-column>
@@ -120,7 +120,10 @@
                     <el-form-item prop="total" label="发行数量">
                         <el-input-number v-model="formData.total" disabled></el-input-number>
                     </el-form-item>
-                    <el-form-item prop="items" label="包含作品" style="width: calc(100vw - 450px)">
+                    <el-form-item prop="items" label="包含作品" v-if="!canEdit">
+                        <el-button v-if="formData.id" type="primary" size="mini" @click="getBox">查看作品</el-button>
+                    </el-form-item>
+                    <el-form-item v-if="canEdit" label="包含作品" style="width: calc(100vw - 450px);">
                         <el-table :data="blindBoxItems" max-height="300px">
                             <el-table-column prop="collectionId" label="ID"></el-table-column>
                             <el-table-column prop="name" label="名称"></el-table-column>
@@ -131,7 +134,7 @@
                                 </template>
                             </el-table-column>
                             <el-table-column width="100">
-                                <template v-slot="{ row, $index }">
+                                <template v-slot="{ $index }">
                                     <el-button
                                         @click="removeItem($index)"
                                         type="danger"
@@ -144,8 +147,6 @@
                                 </template>
                             </el-table-column>
                         </el-table>
-                    </el-form-item>
-                    <el-form-item>
                         <el-button size="mini" @click="addItem" :disabled="!canEdit">添加作品</el-button>
                     </el-form-item>
                     <!-- <el-form-item prop="likes" label="点赞">
@@ -162,7 +163,7 @@
                     <el-form-item prop="startTime" label="定时发布">
                         <el-radio v-model="formData.scheduleSale" :label="true">是</el-radio>
                         <el-radio v-model="formData.scheduleSale" :label="false">否</el-radio>
-                        <div style="margin-top: 10px" v-if="formData.scheduleSale">
+                        <div style="margin-top: 10px;" v-if="formData.scheduleSale">
                             <el-date-picker
                                 v-model="formData.startTime"
                                 type="datetime"
@@ -197,13 +198,13 @@
                             :step="1"
                             :max="2147483647"
                             v-model="formData.holdDays"
-                            style="width: 180px"
+                            style="width: 180px;"
                         ></el-input-number>
                         <div class="tip">持有多少天可转赠/转让。为空时,按系统设置天数</div>
                     </el-form-item>
 
                     <el-form-item prop="minimumCharge" label="最低消费">
-                        <el-input-number type="number" :min="0" v-model="formData.minimumCharge" style="width: 180px">
+                        <el-input-number type="number" :min="0" v-model="formData.minimumCharge" style="width: 180px;">
                         </el-input-number>
                     </el-form-item>
 
@@ -252,7 +253,7 @@
                             prop="saleTime"
                             label="销售时间"
                             v-if="formData.assignment > 0 && formData.timeDelay"
-                            style="margin-left: 22px"
+                            style="margin-left: 22px;"
                         >
                             <el-date-picker
                                 v-model="formData.saleTime"
@@ -336,6 +337,26 @@
                 <el-button type="primary" @click="savePrivilege">保存</el-button>
             </div>
         </el-dialog>
+
+        <el-dialog title="包含作品" :visible.sync="showBox" width="800px" @close="showBox = false">
+            <el-table :data="blindBoxItems" max-height="300px">
+                <el-table-column prop="collectionId" label="ID"></el-table-column>
+                <el-table-column prop="name" label="名称"></el-table-column>
+                <el-table-column prop="total" label="数量" width="100"></el-table-column>
+                <el-table-column prop="rare" label="稀有" width="100">
+                    <template v-slot="{ row }">
+                        <el-tag :type="row.rare ? 'success' : 'info'">{{ row.rare ? '是' : '否' }}</el-tag>
+                    </template>
+                </el-table-column>
+                <el-table-column width="100">
+                    <template v-slot="{ $index }">
+                        <el-button @click="removeItem($index)" type="danger" plain size="mini" :disabled="!canEdit">
+                            移除
+                        </el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </el-dialog>
     </div>
 </template>
 <script>
@@ -403,26 +424,7 @@ export default {
                 .then(res => {
                     this.privilegeOptions = res.content;
                     return Promise.resolve();
-                }),
-            new Promise((resolve, reject) => {
-                if (this.$route.query.id) {
-                    this.$http
-                        .post(
-                            '/blindBoxItem/all',
-                            { query: { blindBoxId: this.$route.query.id }, size: 10000 },
-                            { body: 'json' }
-                        )
-                        .then(res => {
-                            this.blindBoxItems = res.content;
-                            resolve();
-                        })
-                        .catch(e => {
-                            resolve();
-                        });
-                } else {
-                    resolve();
-                }
-            })
+                })
         ]).then(() => {
             console.log(this.formData, this.privilegeOptions);
             this.formData.privileges.forEach(p => {
@@ -441,6 +443,7 @@ export default {
     data() {
         return {
             saving: false,
+            showBox: false,
             formData: {
                 onShelf: false,
                 salable: true,
@@ -692,6 +695,18 @@ export default {
         };
     },
     methods: {
+        getBox() {
+            this.$http
+                .post(
+                    '/blindBoxItem/all',
+                    { query: { blindBoxId: this.$route.query.id }, size: 10000 },
+                    { body: 'json' }
+                )
+                .then(res => {
+                    this.showBox = true;
+                    this.blindBoxItems = res.content;
+                });
+        },
         onSave() {
             this.$refs.form.validate(valid => {
                 if (valid) {

+ 7 - 1
src/main/vue/src/views/CollectionList.vue

@@ -135,6 +135,7 @@ import { mapState } from 'vuex';
 import pageableTable from '@/mixins/pageableTable';
 import SortableHeader from '../components/SortableHeader.vue';
 import MinterSelect from '../components/MinterSelect.vue';
+import { format, addDays } from 'date-fns';
 
 export default {
     components: { SortableHeader, MinterSelect },
@@ -185,7 +186,12 @@ export default {
         beforeGetData() {
             return {
                 search: this.search,
-                query: { del: false, source: 'OFFICIAL', createdAt: this.createdAt, minterId: this.minterId }
+                query: {
+                    del: false,
+                    source: 'OFFICIAL',
+                    createdAt: this.createdAt || ['1970-01-01 00:00:00', format(new Date(), 'yyyy-MM-dd HH:mm:ss')],
+                    minterId: this.minterId
+                }
             };
         },
         toggleMultipleMode(multipleMode) {

+ 5 - 1
src/main/vue/src/views/OrderList.vue

@@ -138,6 +138,7 @@
 import { mapState } from 'vuex';
 import pageableTable from '@/mixins/pageableTable';
 import CreatedAtPicker from '../components/CreatedAtPicker.vue';
+import { format, addDays } from 'date-fns';
 
 export default {
     components: { CreatedAtPicker },
@@ -200,6 +201,8 @@ export default {
             }
             if (this.createdAt) {
                 data.query.createdAt = this.createdAt;
+            } else {
+                data.query.createdAt = ['1970-01-01 00:00:00', format(new Date(), 'yyyy-MM-dd HH:mm:ss')];
             }
             if (this.status) {
                 data.query.status = this.status;
@@ -216,6 +219,7 @@ export default {
             if (this.userId) {
                 data.query.userId = this.userId;
             }
+            console.log('data::', data);
             return data;
         },
         beforeGetData() {
@@ -247,7 +251,7 @@ export default {
         download() {
             this.downloading = true;
             let params = this.getParams();
-            params.size = 10000;
+            params.size = 100000;
             this.$axios
                 .post('/order/excel', params, {
                     responseType: 'blob'

+ 1 - 1
src/main/vue/src/views/OrderUsedList.vue

@@ -241,7 +241,7 @@ export default {
         download() {
             this.downloading = true;
             let params = this.getParams();
-            params.size = 10000;
+            params.size = 100000;
             this.$axios
                 .post('/order/excel', params, {
                     responseType: 'blob'

+ 1 - 1
src/main/vue/src/views/UserEdit.vue

@@ -86,7 +86,7 @@ export default {
     created() {
         if (this.$route.query.id) {
             this.$http
-                .get(`/user/get/${this.$route.query.id}`)
+                .get(`/user/adminGet/${this.$route.query.id}`)
                 .then(res => {
                     this.formData = res;
                     this.vip = res.vipPurchase > 0;

+ 4 - 2
src/main/vue/src/views/UserList.vue

@@ -27,6 +27,7 @@
             header-cell-class-name="table-header-cell"
             row-class-name="table-row"
             cell-class-name="table-cell"
+            v-loading="fetchingData"
         >
             <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
             <el-table-column prop="id" label="ID" width="100">
@@ -86,10 +87,11 @@ export default {
         return {
             multipleMode: false,
             search: '',
-            url: '/user/all',
+            url: '/user/adminAll',
             downloading: false,
             createdAt: '',
-            vip: ''
+            vip: '',
+            sortStr: 'id,desc'
         };
     },
     computed: {

+ 73 - 10
src/test/java/com/izouma/nineth/service/CollectionServiceTest.java

@@ -12,20 +12,25 @@ import com.izouma.nineth.repo.CollectionRepo;
 import com.izouma.nineth.repo.PrivilegeOptionRepo;
 import com.izouma.nineth.repo.UserRepo;
 import com.izouma.nineth.service.storage.StorageService;
+import com.izouma.nineth.utils.ImageUtils;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.RandomStringUtils;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.Frame;
+import org.bytedeco.javacv.Java2DFrameConverter;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
 import java.nio.file.Files;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
@@ -52,23 +57,31 @@ class CollectionServiceTest extends ApplicationTests {
 
     @Test
     public void batchUpload() throws IOException {
-        AtomicInteger num = new AtomicInteger(2501);
+        AtomicInteger num = new AtomicInteger(1);
         List<BlindBoxItem> items = new ArrayList<>();
-        String jsonStr = FileUtils.readFileToString(new File("/Users/qiufangchao/Desktop/evo.json"), "UTF-8");
-        Arrays.stream(new File("/Users/qiufangchao/Desktop/evo3").listFiles())
-                .filter(f -> Pattern.matches("^BJ.*\\.png$", f.getName()))
+        String jsonStr = FileUtils.readFileToString(new File("/Users/qiufangchao/Desktop/OASISPUNK.json"), "UTF-8");
+        Arrays.stream(new File("/Users/qiufangchao/Desktop/avatar").listFiles())
+                .filter(f -> !f.getName().contains(".DS_Store"))
                 .parallel().forEach(file -> {
                     try {
+                        String name = file.getName();
+                        Pattern p = Pattern.compile("(\\d+)");
+                        Matcher matcher = p.matcher(name);
+                        matcher.find();
+                        String findname = matcher.group();
+
                         Collection collection = JSON.parseObject(jsonStr, Collection.class);
                         collection.setId(null);
-                        collection.setName(String.format("OASISPUNK.EVO #%04d", num.getAndIncrement()));
+                        collection.setName("OASISPUNK #" + findname);
                         collection.setStock(1);
                         collection.setTotal(1);
                         collection.setSale(0);
                         collection.setMinterId(7150L);
                         collection.setOnShelf(false);
                         collection.setSalable(false);
-                        collection.setPic(Collections.singletonList(new FileObject("", "https://raex-meta.oss-cn-shenzhen.aliyuncs.com/image/evos3/" + file.getName(), null, "png")));
+//                        String thumbPath = "https://cdn.raex.vip/thumb_image/mahjongman/" + file.getName()
+//                                .substring(0, file.getName().lastIndexOf(".")) + ".jpg";
+                        collection.setPic(Collections.singletonList(new FileObject("", "https://cdn.raex.vip/image/evo1/" + file.getName(), null, "image/png")));
 
                         collectionRepo.save(collection);
                         System.out.println("保存成功" + collection.getId());
@@ -91,7 +104,7 @@ class CollectionServiceTest extends ApplicationTests {
     public void createBlindBox() throws IOException {
         List<Collection> items = collectionRepo.findByNameLike("OASISPUNK.EVO #%").stream().filter(i -> {
             int num = Integer.parseInt(i.getName().substring("OASISPUNK.EVO #".length()));
-            return num > 2500 && num <= 3000;
+            return num > 0 && num <= 280;
         }).collect(Collectors.toList());
 
         String jsonStr = FileUtils.readFileToString(new File("/Users/qiufangchao/Desktop/evo.json"), "UTF-8");
@@ -144,4 +157,54 @@ class CollectionServiceTest extends ApplicationTests {
         collectionService.savePoint(3749128L, LocalDateTime.of(2022, 3, 23, 15, 0, 0));
     }
 
+    @Test
+    public void uploadMp4() {
+        Arrays.stream(new File("/Users/qiufangchao/Desktop/majiang").listFiles())
+                .parallel()
+                .filter(f -> !f.getName().contains(".DS_Store"))
+                .forEach(file -> {
+                    System.out.println(file.getName());
+                    try {
+                        String url = storageService.uploadFromInputStream(new FileInputStream(file), "video/mahjongman/" + file.getName());
+                        String thumbPath = "thumb_image/mahjongman/" + file.getName()
+                                .substring(0, file.getName().lastIndexOf(".")) + ".jpg";
+
+                        FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(file);
+                        Java2DFrameConverter frameConverter = new Java2DFrameConverter();
+                        try {
+                            frameGrabber.start();
+
+                            Frame frame = null;
+                            while (frame == null) {
+                                frame = frameGrabber.grabKeyFrame();
+                            }
+                            Objects.requireNonNull(frame, "获取视频缩略图失败");
+                            BufferedImage thumbBi = frameConverter.convert(frame);
+
+                            BufferedImage thumbResized = ImageUtils.resizeJpg(thumbBi, 1000, 1000, false);
+                            ByteArrayOutputStream os = new ByteArrayOutputStream();
+                            ImageIO.write(thumbResized, "jpg", os);
+                            InputStream is = new ByteArrayInputStream(os.toByteArray());
+                            String thumbUrl = storageService.uploadFromInputStream(is, thumbPath);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        } finally {
+                            frameGrabber.stop();
+                        }
+                    } catch (Exception e) {
+                    }
+                });
+    }
+
+    @Test
+    public void test2() {
+        String name = "/Users/qiufangchao/Desktop/majiang/bai1-1.mp4";
+        Pattern p = Pattern.compile("(\\d+)-(\\d+)");
+        Matcher matcher = p.matcher(name);
+        matcher.find();
+        String firstHour = matcher.group();
+        System.out.println(matcher.start());
+        System.out.println(firstHour);
+    }
+
 }

+ 4 - 0
src/test/java/com/izouma/nineth/service/OrderServiceTest.java

@@ -257,4 +257,8 @@ public class OrderServiceTest extends ApplicationTests {
         System.out.println(orderRepo.countByUserIdAndCollectionIdAndVipTrueAndStatusIn(9850L, 196308L,
                 Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING)));
     }
+
+    @Test
+    public void calcSettle() {
+    }
 }