Forráskód Böngészése

Merge branch 'pai_mai' into hb_dev_pai

# Conflicts:
#	src/main/java/com/izouma/nineth/repo/AssetRepo.java
#	src/main/java/com/izouma/nineth/security/WebSecurityConfig.java
#	src/main/java/com/izouma/nineth/service/CacheService.java
#	src/main/java/com/izouma/nineth/service/OrderCancelService.java
#	src/main/java/com/izouma/nineth/service/OrderPayService.java
#	src/main/java/com/izouma/nineth/service/OrderService.java
#	src/main/java/com/izouma/nineth/service/SandPayService.java
#	src/main/java/com/izouma/nineth/service/UserService.java
#	src/main/java/com/izouma/nineth/web/HmPayController.java
#	src/main/java/com/izouma/nineth/web/PayEaseController.java
#	src/main/java/com/izouma/nineth/web/SandPayController.java
#	src/test/java/com/izouma/nineth/repo/UserPropertyRepoTest.java
#	src/test/java/com/izouma/nineth/service/AirDropServiceTest.java
licailing 3 éve
szülő
commit
db09d8c82b
92 módosított fájl, 4921 hozzáadás és 154 törlés
  1. 7 0
      run_java.sh
  2. 2 0
      src/main/java/com/izouma/nineth/config/Constants.java
  3. 5 0
      src/main/java/com/izouma/nineth/config/RedisKeys.java
  4. 3 0
      src/main/java/com/izouma/nineth/domain/Asset.java
  5. 99 0
      src/main/java/com/izouma/nineth/domain/AuctionActivity.java
  6. 107 0
      src/main/java/com/izouma/nineth/domain/AuctionOrder.java
  7. 25 0
      src/main/java/com/izouma/nineth/domain/AuctionPassRecord.java
  8. 52 0
      src/main/java/com/izouma/nineth/domain/AuctionRecord.java
  9. 2 0
      src/main/java/com/izouma/nineth/domain/BlindBoxItem.java
  10. 2 0
      src/main/java/com/izouma/nineth/domain/Collection.java
  11. 2 0
      src/main/java/com/izouma/nineth/domain/CompanyCollection.java
  12. 3 1
      src/main/java/com/izouma/nineth/domain/NewsLike.java
  13. 4 0
      src/main/java/com/izouma/nineth/domain/UserAddress.java
  14. 31 0
      src/main/java/com/izouma/nineth/dto/auction/AuctionInputDTO.java
  15. 48 0
      src/main/java/com/izouma/nineth/dto/auction/AuctionRecordDTO.java
  16. 27 0
      src/main/java/com/izouma/nineth/dto/oasis/OasisDistrictCollectionDTO.java
  17. 45 0
      src/main/java/com/izouma/nineth/dto/oasis/OasisDistrictDTO.java
  18. 17 0
      src/main/java/com/izouma/nineth/dto/oasis/OasisLoginDTO.java
  19. 4 1
      src/main/java/com/izouma/nineth/enums/AssetStatus.java
  20. 22 0
      src/main/java/com/izouma/nineth/enums/AuctionOrderStatus.java
  21. 17 0
      src/main/java/com/izouma/nineth/enums/AuctionPaymentType.java
  22. 17 0
      src/main/java/com/izouma/nineth/enums/AuctionRecordType.java
  23. 16 0
      src/main/java/com/izouma/nineth/enums/AuctionSource.java
  24. 20 0
      src/main/java/com/izouma/nineth/enums/AuctionStatus.java
  25. 16 0
      src/main/java/com/izouma/nineth/enums/AuctionType.java
  26. 1 0
      src/main/java/com/izouma/nineth/enums/BannerType.java
  27. 1 0
      src/main/java/com/izouma/nineth/enums/TransferReason.java
  28. 1 1
      src/main/java/com/izouma/nineth/listener/CreateOrderListener.java
  29. 1 1
      src/main/java/com/izouma/nineth/listener/RegisterListener.java
  30. 1 1
      src/main/java/com/izouma/nineth/listener/UpdateActivityStockListener.java
  31. 1 1
      src/main/java/com/izouma/nineth/listener/UpdateQuotaListener.java
  32. 1 1
      src/main/java/com/izouma/nineth/listener/UpdateSaleListener.java
  33. 1 1
      src/main/java/com/izouma/nineth/listener/UpdateStockListener.java
  34. 9 0
      src/main/java/com/izouma/nineth/repo/AssetRepo.java
  35. 56 0
      src/main/java/com/izouma/nineth/repo/AuctionActivityRepo.java
  36. 35 0
      src/main/java/com/izouma/nineth/repo/AuctionOrderRepo.java
  37. 21 0
      src/main/java/com/izouma/nineth/repo/AuctionPassRecordRepo.java
  38. 31 0
      src/main/java/com/izouma/nineth/repo/AuctionRecordRepo.java
  39. 4 1
      src/main/java/com/izouma/nineth/repo/CollectionRepo.java
  40. 4 0
      src/main/java/com/izouma/nineth/repo/CompanyCollectionRepo.java
  41. 2 0
      src/main/java/com/izouma/nineth/repo/NewsLikeRepo.java
  42. 3 0
      src/main/java/com/izouma/nineth/repo/UserBalanceRepo.java
  43. 5 0
      src/main/java/com/izouma/nineth/repo/UserRepo.java
  44. 7 0
      src/main/java/com/izouma/nineth/security/WebSecurityConfig.java
  45. 18 4
      src/main/java/com/izouma/nineth/service/AssetService.java
  46. 302 0
      src/main/java/com/izouma/nineth/service/AuctionActivityService.java
  47. 519 0
      src/main/java/com/izouma/nineth/service/AuctionOrderService.java
  48. 209 0
      src/main/java/com/izouma/nineth/service/AuctionRecordService.java
  49. 5 0
      src/main/java/com/izouma/nineth/service/CacheService.java
  50. 1 1
      src/main/java/com/izouma/nineth/service/CaptchaService.java
  51. 37 3
      src/main/java/com/izouma/nineth/service/CollectionService.java
  52. 106 1
      src/main/java/com/izouma/nineth/service/CompanyCollectionService.java
  53. 1 3
      src/main/java/com/izouma/nineth/service/MintOrderService.java
  54. 25 4
      src/main/java/com/izouma/nineth/service/NewsLikeService.java
  55. 20 14
      src/main/java/com/izouma/nineth/service/OrderCancelService.java
  56. 82 18
      src/main/java/com/izouma/nineth/service/OrderPayService.java
  57. 1 2
      src/main/java/com/izouma/nineth/service/OrderService.java
  58. 2 2
      src/main/java/com/izouma/nineth/service/SandPayService.java
  59. 51 0
      src/main/java/com/izouma/nineth/service/UserService.java
  60. 77 0
      src/main/java/com/izouma/nineth/web/AuctionActivityController.java
  61. 124 0
      src/main/java/com/izouma/nineth/web/AuctionOrderController.java
  62. 86 0
      src/main/java/com/izouma/nineth/web/AuctionRecordController.java
  63. 18 0
      src/main/java/com/izouma/nineth/web/AuthenticationController.java
  64. 12 0
      src/main/java/com/izouma/nineth/web/CollectionController.java
  65. 63 4
      src/main/java/com/izouma/nineth/web/CompanyCollectionController.java
  66. 5 0
      src/main/java/com/izouma/nineth/web/HmPayController.java
  67. 14 1
      src/main/java/com/izouma/nineth/web/NewsLikeController.java
  68. 6 4
      src/main/java/com/izouma/nineth/web/OrderPayController.java
  69. 31 0
      src/main/java/com/izouma/nineth/web/OrderPayControllerV2.java
  70. 10 0
      src/main/java/com/izouma/nineth/web/PayEaseController.java
  71. 5 0
      src/main/java/com/izouma/nineth/web/SandPayController.java
  72. 5 5
      src/main/java/com/izouma/nineth/web/SmsController.java
  73. 0 0
      src/main/resources/genjson/AuctionOrder.json
  74. 69 0
      src/main/vue/src/router.js
  75. 410 0
      src/main/vue/src/views/AuctionActivityEdit.vue
  76. 259 0
      src/main/vue/src/views/AuctionActivityList.vue
  77. 270 0
      src/main/vue/src/views/AuctionOrderEdit.vue
  78. 289 0
      src/main/vue/src/views/AuctionOrderList.vue
  79. 289 0
      src/main/vue/src/views/AuctionOrderUsedList.vue
  80. 132 0
      src/main/vue/src/views/AuctionRecordEdit.vue
  81. 196 0
      src/main/vue/src/views/AuctionRecordList.vue
  82. 260 0
      src/main/vue/src/views/AuctionUsedList.vue
  83. 2 0
      src/main/vue/src/views/BannerEdit.vue
  84. 1 0
      src/main/vue/src/views/BannerList.vue
  85. 1 1
      src/main/vue/src/views/MintOrderList.vue
  86. 18 0
      src/test/java/com/izouma/nineth/repo/AuctionRecordRepoTest.java
  87. 24 73
      src/test/java/com/izouma/nineth/repo/UserPropertyRepoTest.java
  88. 10 4
      src/test/java/com/izouma/nineth/repo/UserRepoTest.java
  89. 44 0
      src/test/java/com/izouma/nineth/service/AuctionActivityServiceTest.java
  90. 16 0
      src/test/java/com/izouma/nineth/service/AuctionOrderServiceTest.java
  91. 17 0
      src/test/java/com/izouma/nineth/service/AuctionRecordServiceTest.java
  92. 1 1
      src/test/java/com/izouma/nineth/service/OrderServiceTest.java

+ 7 - 0
run_java.sh

@@ -0,0 +1,7 @@
+cd /usr/local/src/raex_back_dev
+git pull
+sh install-jar.sh
+mvn clean package
+systemctl stop 9th_test
+mv -f target/9th-0.0.1-SNAPSHOT.jar /var/www/9th_test/9th-0.0.1-SNAPSHOT.jar
+systemctl start 9th_test

+ 2 - 0
src/main/java/com/izouma/nineth/config/Constants.java

@@ -37,5 +37,7 @@ public interface Constants {
         String GIFT     = "gift";
         String GIFT     = "gift";
         String MINT     = "mintOrder";
         String MINT     = "mintOrder";
         String RECHARGE = "recharge";
         String RECHARGE = "recharge";
+
+        String AUCTION = "auctionOrder";
     }
     }
 }
 }

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

@@ -40,4 +40,9 @@ public class RedisKeys {
     public static final String BIND_CARD = "bindCard::";
     public static final String BIND_CARD = "bindCard::";
 
 
     public static final String PAY_TMP = "payTmp::";
     public static final String PAY_TMP = "payTmp::";
+
+    public static final String AUCTION_STATUS = "auctionStatus::";
+
+    public static final String AUCTION_ORDER_LOCK = "auctionOrderLock::";
+
 }
 }

+ 3 - 0
src/main/java/com/izouma/nineth/domain/Asset.java

@@ -170,6 +170,9 @@ public class Asset extends CollectionBaseEntity {
 
 
     private Long fromAssetId;
     private Long fromAssetId;
 
 
+    //地块ID
+    private Long oasisId;
+
     @ApiModelProperty("类型")
     @ApiModelProperty("类型")
     @Enumerated(EnumType.STRING)
     @Enumerated(EnumType.STRING)
     private CollectionType type;
     private CollectionType type;

+ 99 - 0
src/main/java/com/izouma/nineth/domain/AuctionActivity.java

@@ -0,0 +1,99 @@
+package com.izouma.nineth.domain;
+
+import com.izouma.nineth.annotations.Searchable;
+import com.izouma.nineth.converter.FileObjectConverter;
+import com.izouma.nineth.converter.FileObjectListConverter;
+import com.izouma.nineth.enums.AuctionSource;
+import com.izouma.nineth.enums.AuctionStatus;
+import com.izouma.nineth.enums.AuctionType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Entity
+@ApiModel("拍卖藏品")
+public class AuctionActivity extends BaseEntity {
+    @ApiModelProperty("起拍人ID")
+    private Long             sellerId;
+    @ApiModelProperty("起拍人昵称")
+    private String           seller;
+    @ApiModelProperty("起拍人头像")
+    private String           sellerAvatar;
+    @ApiModelProperty("拍卖名称")
+    @Searchable
+    private String           name;
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty("拍卖类型")
+    private AuctionType      auctionType;
+    @ApiModelProperty("铸造者")
+    private String           minter;
+    @ApiModelProperty("藏品ID")
+    private Long             assetId;
+    @ApiModelProperty("图片")
+    @Column(columnDefinition = "TEXT")
+    @Convert(converter = FileObjectListConverter.class)
+    private List<FileObject> pic;
+    @Column(columnDefinition = "TEXT")
+    @Convert(converter = FileObjectConverter.class)
+    private FileObject       model3d;
+    @ApiModelProperty("详情")
+    @Column(columnDefinition = "TEXT")
+    private String           detail;
+    @ApiModelProperty("分类")
+    private String           category;
+    @ApiModelProperty("起拍价")
+    private BigDecimal       startingPrice;
+    @ApiModelProperty("保证金")
+    private BigDecimal       deposit;
+    @ApiModelProperty("一口价")
+    private BigDecimal       fixedPrice;
+    @ApiModelProperty("开始时间")
+    private LocalDateTime    startTime;
+    @ApiModelProperty("加价幅度")
+    private BigDecimal       increment;
+    @ApiModelProperty("截止时间")
+    private LocalDateTime    endTime;
+    //每次出价实时更新
+    @ApiModelProperty("成交价")
+    private BigDecimal       purchasePrice;
+    @ApiModelProperty("买家id")
+    private Long             purchaserId;
+    @ApiModelProperty("当前竞价id")
+    private Long             recordId;
+    @ApiModelProperty("买家")
+    private String           purchaser;
+    @ApiModelProperty("状态")
+    @Enumerated(EnumType.STRING)
+    private AuctionStatus    status;
+    @ApiModelProperty("来源")
+    private AuctionSource    source;
+    @ApiModelProperty("版税比例")
+    private int              royalties;
+    @ApiModelProperty("手续费比例")
+    private int              serviceCharge;
+    @Column(columnDefinition = "int(11) default 0")
+    @ApiModelProperty("围观次数")
+    private int              likes;
+    @Column(columnDefinition = "int(11) default 0")
+    @ApiModelProperty("出价次数")
+    private int              bids;
+
+    private boolean hasFixedPrice;
+    private boolean liked;
+
+    @ApiModelProperty("上架")
+    @Column(columnDefinition = "tinyint unsigned default 0")
+    private boolean onShelf = false;
+}

+ 107 - 0
src/main/java/com/izouma/nineth/domain/AuctionOrder.java

@@ -0,0 +1,107 @@
+package com.izouma.nineth.domain;
+
+import com.izouma.nineth.annotations.Searchable;
+import com.izouma.nineth.annotations.SearchableOne;
+import com.izouma.nineth.converter.FileObjectListConverter;
+import com.izouma.nineth.enums.*;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Entity
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AuctionOrder extends BaseEntityNoID {
+    @Id
+    private Long id;
+
+    @ApiModelProperty("用户ID")
+    @SearchableOne
+    private Long userId;
+
+    private String nickname;
+
+    @ApiModelProperty("拍卖ID")
+    private Long auctionId;
+
+    @ApiModelProperty("名称")
+    @SearchableOne
+    private String name;
+
+    @ApiModelProperty("图片")
+    @Column(columnDefinition = "TEXT")
+    @Convert(converter = FileObjectListConverter.class)
+    private List<FileObject> pic;
+
+    @ApiModelProperty("版税比例")
+    private int royalties;
+
+    @ApiModelProperty("手续费比例")
+    private int serviceCharge;
+
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty("拍卖类型")
+    private AuctionSource source;
+
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty("支付类型")
+    private AuctionPaymentType paymentType;
+
+    @ApiModelProperty("价格")
+    @Column(precision = 10, scale = 2)
+    private BigDecimal price;
+
+//    @ApiModelProperty("gas费")
+//    @Column(precision = 10, scale = 2)
+//    private BigDecimal gasPrice;
+
+    @ApiModelProperty("总价")
+    @Column(precision = 10, scale = 2)
+    private BigDecimal totalPrice;
+
+    @ApiModelProperty("状态")
+    @Enumerated(EnumType.STRING)
+    private AuctionOrderStatus status;
+
+    @ApiModelProperty("支付方式")
+    @Enumerated(EnumType.STRING)
+    private PayMethod payMethod;
+
+    @ApiModelProperty("交易ID")
+    @Searchable
+    @Column(length = 90)
+    private String transactionId;
+
+    @ApiModelProperty("支付时间")
+    private LocalDateTime payTime;
+
+    @ApiModelProperty("取消时间")
+    private LocalDateTime cancelTime;
+
+    @ApiModelProperty("退款时间")
+    private LocalDateTime refundTime;
+
+    @ApiModelProperty("收货人")
+    private String contactName;
+
+    @ApiModelProperty("收货电话")
+    private String contactPhone;
+
+    @ApiModelProperty("收货地址")
+    private String address;
+
+    @ApiModelProperty("拍卖记录id")
+    private Long auctionRecordId;
+
+    @ApiModelProperty("拍卖记录id")
+    private String courierId;
+}

+ 25 - 0
src/main/java/com/izouma/nineth/domain/AuctionPassRecord.java

@@ -0,0 +1,25 @@
+package com.izouma.nineth.domain;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import java.math.BigDecimal;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Entity
+@ApiModel("流拍记录表")
+public class AuctionPassRecord extends BaseEntity {
+    private Long auctionId;
+
+    private Long userId;
+
+    private BigDecimal purchasePrice;
+
+}

+ 52 - 0
src/main/java/com/izouma/nineth/domain/AuctionRecord.java

@@ -0,0 +1,52 @@
+package com.izouma.nineth.domain;
+
+import com.izouma.nineth.enums.AuctionRecordType;
+import com.izouma.nineth.enums.AuctionType;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.math.BigDecimal;
+
+@Entity
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AuctionRecord extends BaseEntity {
+    @ApiModelProperty("用户ID")
+    private Long              userId;
+    @ApiModelProperty("用户头像")
+    private String            avatar;
+    @ApiModelProperty("用户昵称")
+    private String            user;
+    @ApiModelProperty("拍卖活动ID")
+    private Long              auctionId;
+    @ApiModelProperty("拍卖活动")
+    private String            name;
+    @ApiModelProperty("拍卖活动图片")
+    private String            auctionPic;
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty("类型")
+    private AuctionRecordType type;
+    @ApiModelProperty("是否竞得")
+    private boolean           purchased;
+    @ApiModelProperty("出价")
+    private BigDecimal        bidderPrice;
+    @ApiModelProperty("是否支付保证金")
+    private boolean           payDeposit;
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty("拍卖类型")
+    private AuctionType       auctionType;
+//    @ApiModelProperty("收货人")
+//    private String            contactName;
+//    @ApiModelProperty("收货电话")
+//    private String            contactPhone;
+//    @ApiModelProperty("收货地址")
+//    private String            address;
+}

+ 2 - 0
src/main/java/com/izouma/nineth/domain/BlindBoxItem.java

@@ -31,6 +31,8 @@ public class BlindBoxItem extends BaseEntity {
 
 
     private Long collectionId;
     private Long collectionId;
 
 
+    private Long oasisId;
+
     @ApiModelProperty("名称")
     @ApiModelProperty("名称")
     @Searchable
     @Searchable
     private String name;
     private String name;

+ 2 - 0
src/main/java/com/izouma/nineth/domain/Collection.java

@@ -104,6 +104,8 @@ public class Collection extends CollectionBaseEntity {
     @ApiModelProperty("持有者者ID")
     @ApiModelProperty("持有者者ID")
     private Long ownerId;
     private Long ownerId;
 
 
+    private Long oasisId;
+
     @ApiModelProperty("铸造者头像")
     @ApiModelProperty("铸造者头像")
     private String ownerAvatar;
     private String ownerAvatar;
 
 

+ 2 - 0
src/main/java/com/izouma/nineth/domain/CompanyCollection.java

@@ -66,6 +66,8 @@ public class CompanyCollection extends BaseEntity {
     @ApiModelProperty("限购识别码")
     @ApiModelProperty("限购识别码")
     private String countId;
     private String countId;
 
 
+    private Long oasisId;
+
     @Column(columnDefinition = "TEXT")
     @Column(columnDefinition = "TEXT")
     @Convert(converter = PropertyListConverter.class)
     @Convert(converter = PropertyListConverter.class)
     @ApiModelProperty("特性")
     @ApiModelProperty("特性")

+ 3 - 1
src/main/java/com/izouma/nineth/domain/NewsLike.java

@@ -13,7 +13,7 @@ import javax.persistence.Table;
 @Data
 @Data
 @Entity
 @Entity
 @Table(name = "like_info", indexes =
 @Table(name = "like_info", indexes =
-        {@Index(columnList = "userId"), @Index(columnList = "newsId"), @Index(columnList = "showroomId")})
+        {@Index(columnList = "userId"), @Index(columnList = "newsId"), @Index(columnList = "showroomId"), @Index(columnList = "auctionId")})
 @AllArgsConstructor
 @AllArgsConstructor
 @NoArgsConstructor
 @NoArgsConstructor
 @Builder
 @Builder
@@ -25,4 +25,6 @@ public class NewsLike extends BaseEntity {
     private Long newsId;
     private Long newsId;
 
 
     private Long showroomId;
     private Long showroomId;
+
+    private Long auctionId;
 }
 }

+ 4 - 0
src/main/java/com/izouma/nineth/domain/UserAddress.java

@@ -35,4 +35,8 @@ public class UserAddress extends BaseEntity {
     private String phone;
     private String phone;
 
 
     private boolean def;
     private boolean def;
+
+    public String getDetail() {
+        return this.getProvinceName() + " " + this.getCityName() + " " + this.getDistrictName() + " " + this.getAddress();
+    }
 }
 }

+ 31 - 0
src/main/java/com/izouma/nineth/dto/auction/AuctionInputDTO.java

@@ -0,0 +1,31 @@
+package com.izouma.nineth.dto.auction;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AuctionInputDTO {
+    @ApiModelProperty("藏品id")
+    private Long          assetId;
+    @ApiModelProperty("起拍价")
+    private BigDecimal    startingPrice;
+    @ApiModelProperty("保证金")
+    private BigDecimal    deposit;
+    @ApiModelProperty("一口价")
+    private BigDecimal    fixedPrice;
+    @ApiModelProperty("开始时间")
+    private LocalDateTime startTime;
+    @ApiModelProperty("加价幅度")
+    private BigDecimal    increment;
+    @ApiModelProperty("截止时间")
+    private LocalDateTime endTime;
+
+    private String tradeCode;
+}

+ 48 - 0
src/main/java/com/izouma/nineth/dto/auction/AuctionRecordDTO.java

@@ -0,0 +1,48 @@
+package com.izouma.nineth.dto.auction;
+
+import com.izouma.nineth.domain.FileObject;
+import com.izouma.nineth.enums.*;
+import com.izouma.nineth.service.AuctionOrderService;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import net.bytebuddy.agent.builder.AgentBuilder;
+
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AuctionRecordDTO {
+    @ApiModelProperty("用户ID")
+    private Long               userId;
+    @ApiModelProperty("创作者")
+    private String             minter;
+    @ApiModelProperty("拍卖活动ID")
+    private Long               auctionId;
+    @ApiModelProperty("拍卖活动")
+    private String             name;
+    @ApiModelProperty("拍卖活动图片")
+    private List<FileObject>   auctionPic;
+    @Enumerated(EnumType.STRING)
+    @ApiModelProperty("类型")
+    private AuctionRecordType  type;
+    @ApiModelProperty("是否竞得")
+    private boolean            purchased;
+    @ApiModelProperty("出价")
+    private BigDecimal         bidderPrice;
+    private Long               actPurchasedId;
+    private AuctionStatus      auctionStatus;
+    private Long               orderId;
+    private LocalDateTime      endTime;
+    private LocalDateTime      createdTime;
+    private BigDecimal         deposit;
+    private AuctionType        auctionType;
+    private AuctionOrderStatus orderStatus;
+    private AuctionOrderStatus depositStatus;
+}

+ 27 - 0
src/main/java/com/izouma/nineth/dto/oasis/OasisDistrictCollectionDTO.java

@@ -0,0 +1,27 @@
+package com.izouma.nineth.dto.oasis;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class OasisDistrictCollectionDTO {
+    private Long       oasisId;
+    private String     collectionName;
+    private BigDecimal originPrice;
+    private BigDecimal sellPrice;
+    private String     status;
+    private String     source;
+    private Long       ownerId;
+    private String     owner;
+    private String     ownerName;
+    private String     ownerAvatar;
+    private boolean    salable;
+    private boolean    scanOnly;
+    private Long       collectionId;
+    private String     url;
+}

+ 45 - 0
src/main/java/com/izouma/nineth/dto/oasis/OasisDistrictDTO.java

@@ -0,0 +1,45 @@
+package com.izouma.nineth.dto.oasis;
+
+import com.izouma.nineth.converter.FileObjectConverter;
+import com.izouma.nineth.converter.FileObjectListConverter;
+import com.izouma.nineth.converter.PrivilegeListConverter;
+import com.izouma.nineth.converter.PropertyListConverter;
+import com.izouma.nineth.domain.CollectionProperty;
+import com.izouma.nineth.domain.FileObject;
+import com.izouma.nineth.domain.Privilege;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Convert;
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class OasisDistrictDTO {
+    private Long                     id;
+    private Long                     oasisId;
+    private String                   name;
+    @Convert(converter = FileObjectListConverter.class)
+    private List<FileObject>         pic;
+    @Convert(converter = FileObjectConverter.class)
+    private FileObject               model3d;
+    private String                   detail;
+    private String                   category;
+    private int                      total;
+    private BigDecimal               price;
+    private BigDecimal               originalPrice;
+
+    private int                      maxCount;
+    @Convert(converter = PropertyListConverter.class)
+    @ApiModelProperty("特性")
+    private List<CollectionProperty> properties;
+    @Convert(converter = PrivilegeListConverter.class)
+    @ApiModelProperty("特权")
+    private List<Privilege>          privileges;
+    @ApiModelProperty("是否可转售")
+    private boolean                  canResale;
+}

+ 17 - 0
src/main/java/com/izouma/nineth/dto/oasis/OasisLoginDTO.java

@@ -0,0 +1,17 @@
+package com.izouma.nineth.dto.oasis;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class OasisLoginDTO {
+    private Long   assetId;
+    private Long   oasisId;
+    private String url;
+    private String source;
+    private String token;
+    private Long   userId;
+}

+ 4 - 1
src/main/java/com/izouma/nineth/enums/AssetStatus.java

@@ -6,7 +6,10 @@ public enum AssetStatus {
     TRANSFERRED("已转让"),
     TRANSFERRED("已转让"),
     GIFTING("转赠中"),
     GIFTING("转赠中"),
     GIFTED("已转赠"),
     GIFTED("已转赠"),
-    MINTING("铸造中")
+    MINTING("铸造中"),
+    AUCTIONING("拍卖中"),
+    AUCTION_TRADING("拍卖中"),
+    AUCTIONED("已拍卖")
     ;
     ;
 
 
     private final String description;
     private final String description;

+ 22 - 0
src/main/java/com/izouma/nineth/enums/AuctionOrderStatus.java

@@ -0,0 +1,22 @@
+package com.izouma.nineth.enums;
+
+public enum AuctionOrderStatus {
+    NOT_PAID("未支付"),
+    FINISH("已完成"),
+    CANCELLED("已取消"),
+    REFUNDING("退款中"),
+    REFUNDED("已退款"),
+    DELIVERY("待发货"),
+    RECEIVE("待收货"),
+    AIR_DROP("待空投");
+
+    private final String description;
+
+    AuctionOrderStatus(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 17 - 0
src/main/java/com/izouma/nineth/enums/AuctionPaymentType.java

@@ -0,0 +1,17 @@
+package com.izouma.nineth.enums;
+
+public enum AuctionPaymentType {
+    DEPOSIT("保证金"),
+    PURCHASE_PRICE("成交金"),
+    FIXED_PRICE("一口价");
+
+    private final String description;
+
+    AuctionPaymentType(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 17 - 0
src/main/java/com/izouma/nineth/enums/AuctionRecordType.java

@@ -0,0 +1,17 @@
+package com.izouma.nineth.enums;
+
+public enum AuctionRecordType {
+    DEPOSIT("保证金"),
+    BIDDER("竞拍"),
+    FIXEDPRICE("一口价");
+
+    private final String description;
+
+    AuctionRecordType(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 16 - 0
src/main/java/com/izouma/nineth/enums/AuctionSource.java

@@ -0,0 +1,16 @@
+package com.izouma.nineth.enums;
+
+public enum AuctionSource {
+    OFFICIAL("官方拍卖"),
+    TRANSFER("转让拍卖");
+
+    private final String description;
+
+    AuctionSource(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 20 - 0
src/main/java/com/izouma/nineth/enums/AuctionStatus.java

@@ -0,0 +1,20 @@
+package com.izouma.nineth.enums;
+
+public enum AuctionStatus {
+    NOTSTARTED("未开始"),
+    ONGOING("进行中"),
+    PURCHASED("成交"),
+    FIXED_PRICE_PURCHASED("一口价成交"),
+    PASS("流拍"),
+    FINISH("完成");
+
+    private final String description;
+
+    AuctionStatus(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 16 - 0
src/main/java/com/izouma/nineth/enums/AuctionType.java

@@ -0,0 +1,16 @@
+package com.izouma.nineth.enums;
+
+public enum AuctionType {
+    NFT("虚拟藏品"),
+    ENTITY("实物");
+
+    private final String description;
+
+    AuctionType(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 1 - 0
src/main/java/com/izouma/nineth/enums/BannerType.java

@@ -5,6 +5,7 @@ public enum BannerType {
     DISCOVER("探索"),
     DISCOVER("探索"),
     MINTER("铸造者"),
     MINTER("铸造者"),
     MARKET("市场"),
     MARKET("市场"),
+    AUCTION("拍卖"),
     PC_ACT("PC官方活动"),
     PC_ACT("PC官方活动"),
     PC_TITLE("PC首页大图");
     PC_TITLE("PC首页大图");
 
 

+ 1 - 0
src/main/java/com/izouma/nineth/enums/TransferReason.java

@@ -3,6 +3,7 @@ package com.izouma.nineth.enums;
 public enum TransferReason {
 public enum TransferReason {
     TRANSFER("转让"),
     TRANSFER("转让"),
     GIFT("转赠"),
     GIFT("转赠"),
+    AUCTION("拍卖")
 
 
     ;
     ;
 
 

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

@@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit;
         consumerGroup = "${general.create-order-group}",
         consumerGroup = "${general.create-order-group}",
         topic = "${general.create-order-topic}",
         topic = "${general.create-order-topic}",
         consumeMode = ConsumeMode.ORDERLY)
         consumeMode = ConsumeMode.ORDERLY)
-@ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
+@ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
 public class CreateOrderListener implements RocketMQListener<CreateOrderEvent> {
 public class CreateOrderListener implements RocketMQListener<CreateOrderEvent> {
     private OrderService                  orderService;
     private OrderService                  orderService;
     private RedisTemplate<String, Object> redisTemplate;
     private RedisTemplate<String, Object> redisTemplate;

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

@@ -26,7 +26,7 @@ import java.util.regex.Pattern;
         consumerGroup = "${general.register-group}",
         consumerGroup = "${general.register-group}",
         topic = "${general.register-topic}",
         topic = "${general.register-topic}",
         consumeMode = ConsumeMode.ORDERLY)
         consumeMode = ConsumeMode.ORDERLY)
-@ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
+@ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
 public class RegisterListener implements RocketMQListener<RegisterEvent> {
 public class RegisterListener implements RocketMQListener<RegisterEvent> {
     private       UserService                   userService;
     private       UserService                   userService;
     private       RedisTemplate<String, Object> redisTemplate;
     private       RedisTemplate<String, Object> redisTemplate;

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

@@ -16,7 +16,7 @@ import org.springframework.stereotype.Service;
         consumerGroup = "${general.update-activity-stock-group}",
         consumerGroup = "${general.update-activity-stock-group}",
         topic = "${general.update-activity-stock-topic}",
         topic = "${general.update-activity-stock-topic}",
         consumeMode = ConsumeMode.ORDERLY)
         consumeMode = ConsumeMode.ORDERLY)
-@ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
+@ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
 public class UpdateActivityStockListener implements RocketMQListener<Long> {
 public class UpdateActivityStockListener implements RocketMQListener<Long> {
 
 
     private MintActivityService mintActivityService;
     private MintActivityService mintActivityService;

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

@@ -16,7 +16,7 @@ import org.springframework.stereotype.Service;
         consumerGroup = "${general.update-quota-group}",
         consumerGroup = "${general.update-quota-group}",
         topic = "${general.update-quota-topic}",
         topic = "${general.update-quota-topic}",
         consumeMode = ConsumeMode.ORDERLY)
         consumeMode = ConsumeMode.ORDERLY)
-@ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
+@ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
 public class UpdateQuotaListener implements RocketMQListener<Long> {
 public class UpdateQuotaListener implements RocketMQListener<Long> {
 
 
     private CollectionService collectionService;
     private CollectionService collectionService;

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

@@ -22,7 +22,7 @@ import java.util.Set;
         consumerGroup = "${general.update-sale-group}",
         consumerGroup = "${general.update-sale-group}",
         topic = "${general.update-sale-topic}",
         topic = "${general.update-sale-topic}",
         consumeMode = ConsumeMode.ORDERLY)
         consumeMode = ConsumeMode.ORDERLY)
-@ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
+@ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
 public class UpdateSaleListener implements RocketMQListener<Long> {
 public class UpdateSaleListener implements RocketMQListener<Long> {
 
 
     private CollectionService             collectionService;
     private CollectionService             collectionService;

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

@@ -22,7 +22,7 @@ import java.util.Set;
         consumerGroup = "${general.update-stock-group}",
         consumerGroup = "${general.update-stock-group}",
         topic = "${general.update-stock-topic}",
         topic = "${general.update-stock-topic}",
         consumeMode = ConsumeMode.ORDERLY)
         consumeMode = ConsumeMode.ORDERLY)
-@ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
+@ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
 public class UpdateStockListener implements RocketMQListener<Long> {
 public class UpdateStockListener implements RocketMQListener<Long> {
 
 
     private CollectionService             collectionService;
     private CollectionService             collectionService;

+ 9 - 0
src/main/java/com/izouma/nineth/repo/AssetRepo.java

@@ -14,6 +14,7 @@ import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.Collection;
 import java.util.List;
 import java.util.List;
 import java.util.Optional;
 import java.util.Optional;
+import java.util.Set;
 
 
 public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationExecutor<Asset> {
 public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationExecutor<Asset> {
     @Query("update Asset t set t.del = true where t.id = ?1")
     @Query("update Asset t set t.del = true where t.id = ?1")
@@ -27,6 +28,8 @@ public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationE
 
 
     List<Asset> findByCollectionIdInAndStatus(Iterable<Long> collectionId, AssetStatus status);
     List<Asset> findByCollectionIdInAndStatus(Iterable<Long> collectionId, AssetStatus status);
 
 
+    List<Asset> findAllByCollectionIdInAndStatusIn(List<Long> collectionId, Iterable<AssetStatus> statuses);
+
     List<Asset> findByCreatedAtBefore(LocalDateTime localDateTime);
     List<Asset> findByCreatedAtBefore(LocalDateTime localDateTime);
 
 
     List<Asset> findByConsignmentTrue();
     List<Asset> findByConsignmentTrue();
@@ -43,6 +46,8 @@ public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationE
     @Query("select a from Asset a join User u on a.userId = u.id where a.consignment = true and u.settleAccountId is null")
     @Query("select a from Asset a join User u on a.userId = u.id where a.consignment = true and u.settleAccountId is null")
     List<Asset> findNoAccount();
     List<Asset> findNoAccount();
 
 
+    Set<Asset> findAllByUserIdInAndCollectionId(List<Long> ids, Long collectionId);
+
     List<Asset> findByTxHash(String hash);
     List<Asset> findByTxHash(String hash);
 
 
     List<Asset> findByIdIn(Iterable<Long> ids);
     List<Asset> findByIdIn(Iterable<Long> ids);
@@ -67,6 +72,8 @@ public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationE
     @Query(value = "select c.id, c.pic, c.model3d, c.minter_avatar, c.owner_avatar, c.detail from asset c", nativeQuery = true)
     @Query(value = "select c.id, c.pic, c.model3d, c.minter_avatar, c.owner_avatar, c.detail from asset c", nativeQuery = true)
     List<List<String>> selectResource();
     List<List<String>> selectResource();
 
 
+    List<Asset> findAllByOwnerIdAndStatusAndOasisIdNotNull(Long userId, AssetStatus status);
+
     @Modifying
     @Modifying
     @Transactional
     @Transactional
     @Query(value = "update asset c set c.pic = ?2, c.model3d = ?3, c.minter_avatar = ?4, " +
     @Query(value = "update asset c set c.pic = ?2, c.model3d = ?3, c.minter_avatar = ?4, " +
@@ -76,5 +83,7 @@ public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationE
 
 
     Page<Asset> findByUserIdAndStatusAndNameLike(Long userId, AssetStatus status, String name, Pageable pageable);
     Page<Asset> findByUserIdAndStatusAndNameLike(Long userId, AssetStatus status, String name, Pageable pageable);
 
 
+    List<Asset> findAllByOasisIdInAndStatusIn(List<Long> oasisIds, List<AssetStatus> assetStatuses);
+
     List<Asset> findAllByUserIdAndCollectionIdAndStatus(Long userId, Long collectionId, AssetStatus status);
     List<Asset> findAllByUserIdAndCollectionIdAndStatus(Long userId, Long collectionId, AssetStatus status);
 }
 }

+ 56 - 0
src/main/java/com/izouma/nineth/repo/AuctionActivityRepo.java

@@ -0,0 +1,56 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.AuctionActivity;
+import com.izouma.nineth.enums.AuctionStatus;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+
+public interface AuctionActivityRepo extends JpaRepository<AuctionActivity, Long>, JpaSpecificationExecutor<AuctionActivity> {
+    @Query("update AuctionActivity t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    @Query("select status from AuctionActivity where id = ?1")
+    String getStatus(Long id);
+
+    @Modifying
+    @Transactional
+    @Query("update AuctionActivity set status = ?2 where id = ?1")
+    void updateStatus(Long id, AuctionStatus status);
+
+    @Query("update AuctionActivity t set t.likes = t.likes + ?2 where t.id = ?1")
+    @Modifying
+    @Transactional
+    void addLike(Long id, int num);
+
+    @Transactional
+    @Modifying
+    @Query("update AuctionActivity c set c.status = ?2 where c.id = ?1")
+    void scheduleOnShelf(Long id, AuctionStatus status);
+
+    @Transactional
+    @Modifying
+    @Query("update AuctionActivity c set c.status = ?2 where c.id = ?1")
+    void scheduleOffShelf(Long id, AuctionStatus status);
+
+    List<AuctionActivity> findAllByStatus(AuctionStatus auctionStatus);
+
+    List<AuctionActivity> findByAssetId(Long assetId);
+
+    List<AuctionActivity> findByStartTimeBeforeAndStatusIn(LocalDateTime startTime, Collection<AuctionStatus> status);
+
+    List<AuctionActivity> findByStartTimeBeforeAndStatus(LocalDateTime startTime, AuctionStatus status);
+
+    @Modifying
+    @Transactional
+    @Query("update AuctionActivity set onShelf = ?2 where assetId = ?1 and onShelf <> ?2")
+    void updateOnShelf(Long assetId, boolean onShelf);
+}

+ 35 - 0
src/main/java/com/izouma/nineth/repo/AuctionOrderRepo.java

@@ -0,0 +1,35 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.AuctionOrder;
+import com.izouma.nineth.enums.AuctionPaymentType;
+import com.izouma.nineth.enums.AuctionOrderStatus;
+import com.izouma.nineth.enums.AuctionStatus;
+import com.izouma.nineth.service.AuctionOrderService;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+
+public interface AuctionOrderRepo extends JpaRepository<AuctionOrder, Long>, JpaSpecificationExecutor<AuctionOrder> {
+    @Query("update AuctionOrder t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    AuctionOrder findByUserIdAndAuctionIdAndPaymentTypeAndStatusIn(Long userId, Long auctionId, AuctionPaymentType paymentType, Collection<AuctionOrderStatus> status);
+
+    List<AuctionOrder> findAllByAuctionIdAndPaymentTypeAndStatus(Long auctionId, AuctionPaymentType paymentType, AuctionOrderStatus status);
+
+    List<AuctionOrder> findByStatusAndCreatedAtBeforeAndDelFalse(AuctionOrderStatus status, LocalDateTime createdAt);
+
+    AuctionOrder findFirstByAuctionRecordIdOrderByCreatedAt(Long recordId);
+
+    AuctionOrder findFirstByAuctionRecordIdOrderByIdDesc(Long recordId);
+
+    AuctionOrder findFirstByAuctionIdAndPaymentTypeAndStatusNotIn(Long auctionId, AuctionPaymentType type, Collection<AuctionOrderStatus> status);
+}

+ 21 - 0
src/main/java/com/izouma/nineth/repo/AuctionPassRecordRepo.java

@@ -0,0 +1,21 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.AuctionPassRecord;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+public interface AuctionPassRecordRepo extends JpaRepository<AuctionPassRecord, Long>, JpaSpecificationExecutor<AuctionPassRecord> {
+    @Query("update AuctionPassRecord t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    @Query(nativeQuery = true, value = "select r.user_id  from auction_pass_record r " +
+            "GROUP BY r.user_id HAVING count(*) > 5")
+    List<Long> checkUserId();
+}

+ 31 - 0
src/main/java/com/izouma/nineth/repo/AuctionRecordRepo.java

@@ -0,0 +1,31 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.AuctionRecord;
+import com.izouma.nineth.enums.AuctionType;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+public interface AuctionRecordRepo extends JpaRepository<AuctionRecord, Long>, JpaSpecificationExecutor<AuctionRecord> {
+    @Query("update AuctionRecord t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    AuctionRecord findTopByAuctionIdAndUserIdOrderByIdDesc(Long auctionId, Long userId);
+
+    @Modifying
+    @Transactional
+    void deleteAllByAuctionId(Long auctionId);
+
+    @Query(nativeQuery = true, value = "WITH ranked_messages AS (" +
+            " SELECT m.*, ROW_NUMBER() OVER (PARTITION BY auction_id ORDER BY id DESC) AS rn" +
+            "    FROM auction_record AS m where user_id = ?1 and auction_type = ?2" +
+            ")" +
+            " SELECT * FROM ranked_messages WHERE rn = 1;")
+    List<AuctionRecord> findByUserId(Long userId, String type);
+}

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

@@ -1,6 +1,5 @@
 package com.izouma.nineth.repo;
 package com.izouma.nineth.repo;
 
 
-import com.fasterxml.jackson.annotation.JsonView;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.dto.CollectionInfoDTO;
 import com.izouma.nineth.dto.CollectionInfoDTO;
 import com.izouma.nineth.dto.CollectionStockAndSale;
 import com.izouma.nineth.dto.CollectionStockAndSale;
@@ -164,4 +163,8 @@ public interface CollectionRepo extends JpaRepository<Collection, Long>, JpaSpec
             "and c.salable = true " +
             "and c.salable = true " +
             "and c.stock > 0 ", nativeQuery = true)
             "and c.stock > 0 ", nativeQuery = true)
     String lowestPrice(String search);
     String lowestPrice(String search);
+
+    Collection findFirstByOnShelfAndAssetId(boolean onShelf, Long assetId);
+
+    List<Collection> findAllByOasisIdInAndSourceAndSaleLessThan(List<Long> oasisIds, CollectionSource source, int sale);
 }
 }

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

@@ -1,16 +1,20 @@
 package com.izouma.nineth.repo;
 package com.izouma.nineth.repo;
 
 
 import com.izouma.nineth.domain.CompanyCollection;
 import com.izouma.nineth.domain.CompanyCollection;
+import com.izouma.nineth.enums.CollectionStatus;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.jpa.repository.Query;
 
 
 import javax.transaction.Transactional;
 import javax.transaction.Transactional;
+import java.util.List;
 
 
 public interface CompanyCollectionRepo extends JpaRepository<CompanyCollection, Long>, JpaSpecificationExecutor<CompanyCollection> {
 public interface CompanyCollectionRepo extends JpaRepository<CompanyCollection, Long>, JpaSpecificationExecutor<CompanyCollection> {
     @Query("update CompanyCollection t set t.del = true where t.id = ?1")
     @Query("update CompanyCollection t set t.del = true where t.id = ?1")
     @Modifying
     @Modifying
     @Transactional
     @Transactional
     void softDelete(Long id);
     void softDelete(Long id);
+
+    List<CompanyCollection> findAllByOasisIdInAndStatusNot(List<Long> ids, CollectionStatus status);
 }
 }

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

@@ -20,5 +20,7 @@ public interface NewsLikeRepo extends JpaRepository<NewsLike, Long>, JpaSpecific
 
 
     List<NewsLike> findByUserIdAndShowroomId(Long userId, Long showroomId);
     List<NewsLike> findByUserIdAndShowroomId(Long userId, Long showroomId);
 
 
+    List<NewsLike> findByUserIdAndAuctionId(Long userId, Long auctionId);
+
     List<NewsLike> findByUserIdAndShowroomIdIn(Long userId, Collection<Long> showroomId);
     List<NewsLike> findByUserIdAndShowroomIdIn(Long userId, Collection<Long> showroomId);
 }
 }

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

@@ -9,6 +9,7 @@ import org.springframework.data.jpa.repository.Query;
 import javax.transaction.Transactional;
 import javax.transaction.Transactional;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.List;
+import java.util.Optional;
 
 
 public interface UserBalanceRepo extends JpaRepository<UserBalance, Long>, JpaSpecificationExecutor<UserBalance> {
 public interface UserBalanceRepo extends JpaRepository<UserBalance, Long>, JpaSpecificationExecutor<UserBalance> {
 
 
@@ -21,4 +22,6 @@ public interface UserBalanceRepo extends JpaRepository<UserBalance, Long>, JpaSp
     @Transactional
     @Transactional
     int unlock(Long userId);
     int unlock(Long userId);
 
 
+    Optional<UserBalance> findByUserId(Long userId);
+
 }
 }

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

@@ -24,6 +24,11 @@ public interface UserRepo extends JpaRepository<User, Long>, JpaSpecificationExe
     @Query("update User u set u.del = true where u.id = ?1")
     @Query("update User u set u.del = true where u.id = ?1")
     void softDelete(Long id);
     void softDelete(Long id);
 
 
+    @Transactional
+    @Modifying
+    @Query("update User u set u.del = true where u.del = false and u.id in ?1")
+    void softDeleteIn(Collection<Long> id);
+
     Optional<User> findByUsernameAndDelFalse(String username);
     Optional<User> findByUsernameAndDelFalse(String username);
 
 
     List<User> findAllByAuthoritiesContainsAndDelFalse(Authority authority);
     List<User> findAllByAuthoritiesContainsAndDelFalse(Authority authority);

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

@@ -122,9 +122,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/hmpay/**").permitAll()
                 .antMatchers("/hmpay/**").permitAll()
                 .antMatchers("/payease/**").permitAll()
                 .antMatchers("/payease/**").permitAll()
                 .antMatchers("/order/calcSettle").permitAll()
                 .antMatchers("/order/calcSettle").permitAll()
+                .antMatchers("/auctionOrder/all").permitAll()
+                .antMatchers("/auctionOrder/get/**").permitAll()
+                .antMatchers("/auctionActivity/all").permitAll()
+                .antMatchers("/auctionActivity/get/**").permitAll()
+                .antMatchers("/auctionRecord/all").permitAll()
                 .antMatchers("/ossNotify").permitAll()
                 .antMatchers("/ossNotify").permitAll()
                 .antMatchers("/priceList/list").permitAll()
                 .antMatchers("/priceList/list").permitAll()
                 .antMatchers("/user/collectionInvitorList").permitAll()
                 .antMatchers("/user/collectionInvitorList").permitAll()
+                .antMatchers("/auth/oasisLogin").permitAll()
+                .antMatchers("/auth/oasisLoginPhone").permitAll()
                 .antMatchers("/payOrder/v2/**/sandQuick").permitAll()
                 .antMatchers("/payOrder/v2/**/sandQuick").permitAll()
                 .antMatchers("/pay/v2/**/sandQuick").permitAll()
                 .antMatchers("/pay/v2/**/sandQuick").permitAll()
                 // all other requests need to be authenticated
                 // all other requests need to be authenticated

+ 18 - 4
src/main/java/com/izouma/nineth/service/AssetService.java

@@ -87,6 +87,7 @@ public class AssetService {
         Asset asset = Asset.create(collection, user);
         Asset asset = Asset.create(collection, user);
         asset.setTokenId(TokenUtils.genTokenId());
         asset.setTokenId(TokenUtils.genTokenId());
         asset.setNumber(number);
         asset.setNumber(number);
+        asset.setOasisId(collection.getOasisId());
         asset.setOrderId(orderId);
         asset.setOrderId(orderId);
         asset.setPrice(price);
         asset.setPrice(price);
         assetRepo.saveAndFlush(asset);
         assetRepo.saveAndFlush(asset);
@@ -115,6 +116,7 @@ public class AssetService {
         Asset asset = Asset.create(winItem, user, holdDays);
         Asset asset = Asset.create(winItem, user, holdDays);
         asset.setTokenId(TokenUtils.genTokenId());
         asset.setTokenId(TokenUtils.genTokenId());
         asset.setNumber(number);
         asset.setNumber(number);
+        asset.setOasisId(winItem.getOasisId());
         asset.setOrderId(orderId);
         asset.setOrderId(orderId);
         asset.setPrice(price);
         asset.setPrice(price);
         asset.setTags(new HashSet<>());
         asset.setTags(new HashSet<>());
@@ -161,6 +163,7 @@ public class AssetService {
                 .minterId(asset.getMinterId())
                 .minterId(asset.getMinterId())
                 .minterAvatar(asset.getMinterAvatar())
                 .minterAvatar(asset.getMinterAvatar())
                 .owner(owner.getNickname())
                 .owner(owner.getNickname())
+                .oasisId(asset.getOasisId())
                 .ownerId(owner.getId())
                 .ownerId(owner.getId())
                 .ownerAvatar(owner.getAvatar())
                 .ownerAvatar(owner.getAvatar())
                 .detail(asset.getDetail())
                 .detail(asset.getDetail())
@@ -237,6 +240,7 @@ public class AssetService {
                 .minterAvatar(asset.getMinterAvatar())
                 .minterAvatar(asset.getMinterAvatar())
                 .owner(owner.getNickname())
                 .owner(owner.getNickname())
                 .ownerId(owner.getId())
                 .ownerId(owner.getId())
+                .oasisId(asset.getOasisId())
                 .ownerAvatar(owner.getAvatar())
                 .ownerAvatar(owner.getAvatar())
                 .detail(asset.getDetail())
                 .detail(asset.getDetail())
                 .type(CollectionType.DEFAULT)
                 .type(CollectionType.DEFAULT)
@@ -349,6 +353,7 @@ public class AssetService {
         newAsset.setPrice(price);
         newAsset.setPrice(price);
         newAsset.setSellPrice(null);
         newAsset.setSellPrice(null);
         newAsset.setOrderId(orderId);
         newAsset.setOrderId(orderId);
+        newAsset.setOasisId(asset.getOasisId());
         newAsset.setFromAssetId(asset.getId());
         newAsset.setFromAssetId(asset.getId());
         newAsset.setType(CollectionType.DEFAULT);
         newAsset.setType(CollectionType.DEFAULT);
         newAsset.setSource(TransferReason.GIFT == reason ? AssetSource.GIFT : AssetSource.TRANSFER);
         newAsset.setSource(TransferReason.GIFT == reason ? AssetSource.GIFT : AssetSource.TRANSFER);
@@ -370,7 +375,16 @@ public class AssetService {
         asset.setPublicShow(false);
         asset.setPublicShow(false);
         asset.setConsignment(false);
         asset.setConsignment(false);
         asset.setPublicCollectionId(null);
         asset.setPublicCollectionId(null);
-        asset.setStatus(TransferReason.GIFT == reason ? AssetStatus.GIFTED : AssetStatus.TRANSFERRED);
+        switch (reason) {
+            case GIFT:
+                asset.setStatus(AssetStatus.GIFTED);
+                break;
+            case AUCTION:
+                asset.setStatus(AssetStatus.AUCTIONED);
+                break;
+            case TRANSFER:
+                asset.setStatus(AssetStatus.TRANSFERRED);
+        }
         asset.setOwner(toUser.getNickname());
         asset.setOwner(toUser.getNickname());
         asset.setOwnerId(toUser.getId());
         asset.setOwnerId(toUser.getId());
         asset.setOwnerAvatar(toUser.getAvatar());
         asset.setOwnerAvatar(toUser.getAvatar());
@@ -598,7 +612,7 @@ public class AssetService {
         assetRepo.save(asset);
         assetRepo.save(asset);
     }
     }
 
 
-//    @Cacheable(cacheNames = "fmaa", key = "#userId+'#'+#mintActivityId+'#'+#pageable.hashCode()")
+    //    @Cacheable(cacheNames = "fmaa", key = "#userId+'#'+#mintActivityId+'#'+#pageable.hashCode()")
     public PageWrapper<Asset> findMintActivityAssetsWrap(Long userId, Long mintActivityId, Pageable pageable) {
     public PageWrapper<Asset> findMintActivityAssetsWrap(Long userId, Long mintActivityId, Pageable pageable) {
         return PageWrapper.of(findMintActivityAssets(userId, mintActivityId, pageable));
         return PageWrapper.of(findMintActivityAssets(userId, mintActivityId, pageable));
     }
     }
@@ -612,8 +626,8 @@ public class AssetService {
             if (tags.isEmpty()) return new PageImpl<>(Collections.emptyList());
             if (tags.isEmpty()) return new PageImpl<>(Collections.emptyList());
             return assetRepo.findAll((Specification<Asset>) (root, query, criteriaBuilder) ->
             return assetRepo.findAll((Specification<Asset>) (root, query, criteriaBuilder) ->
                     query.distinct(true).where(criteriaBuilder.equal(root.get("userId"), userId),
                     query.distinct(true).where(criteriaBuilder.equal(root.get("userId"), userId),
-                            criteriaBuilder.equal(root.get("status"), AssetStatus.NORMAL),
-                            root.join("tags").get("id").in(tags.stream().map(Tag::getId).toArray()))
+                                    criteriaBuilder.equal(root.get("status"), AssetStatus.NORMAL),
+                                    root.join("tags").get("id").in(tags.stream().map(Tag::getId).toArray()))
                             .getRestriction(), pageable);
                             .getRestriction(), pageable);
         } else {
         } else {
             return assetRepo.findByUserIdAndStatusAndNameLike(userId, AssetStatus.NORMAL,
             return assetRepo.findByUserIdAndStatusAndNameLike(userId, AssetStatus.NORMAL,

+ 302 - 0
src/main/java/com/izouma/nineth/service/AuctionActivityService.java

@@ -0,0 +1,302 @@
+package com.izouma.nineth.service;
+
+import cn.hutool.core.collection.CollUtil;
+import com.izouma.nineth.annotations.Debounce;
+import com.izouma.nineth.config.RedisKeys;
+import com.izouma.nineth.domain.Asset;
+import com.izouma.nineth.domain.AuctionActivity;
+import com.izouma.nineth.domain.User;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.auction.AuctionInputDTO;
+import com.izouma.nineth.enums.*;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.AssetRepo;
+import com.izouma.nineth.repo.AuctionActivityRepo;
+import com.izouma.nineth.repo.TokenHistoryRepo;
+import com.izouma.nineth.repo.UserRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.core.env.Environment;
+import org.springframework.data.domain.Page;
+import org.springframework.data.redis.core.BoundValueOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Service
+@AllArgsConstructor
+public class AuctionActivityService {
+
+    private final AuctionActivityRepo           auctionActivityRepo;
+    private final AssetRepo                     assetRepo;
+    private final UserRepo                      userRepo;
+    private final PasswordEncoder               passwordEncoder;
+    private final RedisTemplate<String, Object> redisTemplate;
+    private final CacheService                  cacheService;
+    private final TaskScheduler                 taskScheduler;
+    private final Environment                   env;
+    private final TokenHistoryRepo              tokenHistoryRepo;
+    private final SysConfigService              sysConfigService;
+
+    private final Map<Long, ScheduledFuture<?>> tasks = new HashMap<>();
+
+    @PostConstruct
+    public void init() {
+        if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
+            return;
+        }
+        List<AuctionActivity> activities = auctionActivityRepo.findByStartTimeBeforeAndStatus(LocalDateTime.now(),
+                AuctionStatus.NOTSTARTED);
+        for (AuctionActivity activity : activities) {
+            onShelfTask(activity);
+        }
+    }
+
+    public Page<AuctionActivity> all(PageQuery pageQuery) {
+        return auctionActivityRepo
+                .findAll(JpaUtils.toSpecification(pageQuery, AuctionActivity.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    public AuctionActivity createFromAsset(AuctionInputDTO dto) {
+        Asset asset = assetRepo.findById(dto.getAssetId()).orElseThrow(new BusinessException("暂无"));
+
+        //拍卖周期
+        int auctionCycle = sysConfigService.getInt("auction_cycle");
+
+        AuctionActivity auctionActivity = new AuctionActivity();
+        auctionActivity.setAuctionType(AuctionType.NFT);
+        auctionActivity.setAssetId(dto.getAssetId());
+        auctionActivity.setStatus(AuctionStatus.ONGOING);
+        auctionActivity.setBids(0);
+        auctionActivity.setCategory(asset.getCategory());
+        auctionActivity.setEndTime(LocalDateTime.now().plusDays(auctionCycle));
+        auctionActivity.setDeposit(dto.getDeposit());
+        if (Arrays.asList(env.getActiveProfiles()).contains("staging")) {
+            auctionActivity.setEndTime(LocalDateTime.now().plusMinutes(8));
+        }
+        auctionActivity.setDetail(asset.getDetail());
+        auctionActivity.setFixedPrice(dto.getFixedPrice());
+        auctionActivity.setIncrement(dto.getIncrement());
+        auctionActivity.setMinter(asset.getMinter());
+        auctionActivity.setPic(asset.getPic());
+        auctionActivity.setModel3d(asset.getModel3d());
+        auctionActivity.setName(asset.getName());
+        auctionActivity.setSeller(asset.getOwner());
+        auctionActivity.setSellerId(asset.getOwnerId());
+        auctionActivity.setStartTime(LocalDateTime.now());
+        auctionActivity.setSource(AuctionSource.TRANSFER);
+        //固定值 or 资产值
+        auctionActivity.setServiceCharge(asset.getServiceCharge());
+        auctionActivity.setRoyalties(asset.getRoyalties());
+
+        auctionActivity.setStartingPrice(dto.getStartingPrice());
+        auctionActivity.setHasFixedPrice(auctionActivity.getFixedPrice() != null);
+        return save(auctionActivity, dto.getTradeCode());
+    }
+
+
+    public AuctionActivity save(AuctionActivity record, String tradeCode) {
+        if (record.getSource().equals(AuctionSource.OFFICIAL)) {
+            record.setStatus(AuctionStatus.NOTSTARTED);
+        }
+        if (record.getSource().equals(AuctionSource.TRANSFER) && !record.getSellerId().equals(9859L)) {
+            User user = userRepo.findById(record.getSellerId()).orElseThrow(new BusinessException("无用户信息"));
+            if (!passwordEncoder.matches(tradeCode, user.getTradeCode())) {
+                throw new BusinessException("交易密码错误");
+            }
+            if (!AuthStatus.SUCCESS.equals(user.getAuthStatus())) {
+                throw new BusinessException("未实名或实名未通过");
+            }
+            BigDecimal userBuy = tokenHistoryRepo.userBuy(record.getSellerId());
+            BigDecimal num = sysConfigService.getBigDecimal("auction_lvzhoushi_num");
+            if (userBuy.compareTo(num) < 0) {
+                throw new BusinessException("绿洲石不足");
+            }
+
+            Asset asset = assetRepo.findById(record.getAssetId()).orElseThrow(new BusinessException("未找到该藏品"));
+            if (!asset.getOwnerId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
+                throw new BusinessException("非本人藏品,无法操作.");
+            }
+            if (!asset.getStatus().equals(AssetStatus.NORMAL)) {
+                throw new BusinessException("藏品状态异常,无法操作.");
+            }
+            if (asset.isPublicShow() || asset.isConsignment()) {
+//                throw new BusinessException("藏品已寄售,取消寄售后再申请拍卖。");
+                throw new BusinessException("请先下架藏品");
+            }
+
+            //是否二次拍卖
+            List<AuctionActivity> activity = auctionActivityRepo.findByAssetId(asset.getId());
+            if (CollUtil.isNotEmpty(activity)) {
+                if (activity.stream().anyMatch(ac -> !AuctionStatus.PASS.equals(ac.getStatus()))) {
+                    throw new BusinessException("已有拍卖");
+                }
+                log.info("下架流拍拍卖:assetId-{}", asset.getId());
+                auctionActivityRepo.updateOnShelf(asset.getId(), false);
+            }
+
+            asset.setStatus(AssetStatus.AUCTIONING);
+            assetRepo.save(asset);
+        }
+
+        //上架
+        record.setOnShelf(true);
+        AuctionActivity saved = auctionActivityRepo.save(record);
+        if (saved.getStatus().equals(AuctionStatus.NOTSTARTED)) {
+            onShelfTask(saved);
+        }
+        return saved;
+    }
+
+    public synchronized String changeStatus(Long id, AuctionStatus status) {
+        BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.AUCTION_STATUS + id);
+        if (ops.get() == null) {
+            Boolean success = ops.setIfAbsent(Optional.ofNullable(auctionActivityRepo.getStatus(id))
+                    .orElse(AuctionStatus.NOTSTARTED.toString()), 7, TimeUnit.DAYS);
+            log.info("创建redis拍卖活动状态:{}", success);
+        }
+        String stock = (String) ops.getAndSet(status.toString());
+        syncStatus(id);
+        return stock;
+    }
+
+    @Debounce(key = "#id", delay = 500)
+    public void syncStatus(Long id) {
+        String stock = (String) redisTemplate.opsForValue().get(RedisKeys.AUCTION_STATUS + id);
+        if (stock != null) {
+            log.info("同步拍卖活动状态信息{}", id);
+            auctionActivityRepo.updateStatus(id, AuctionStatus.valueOf(stock));
+            cacheService.clearAuction(id);
+        }
+    }
+
+
+    private void onShelfTask(AuctionActivity record) {
+        ScheduledFuture<?> task = tasks.get(record.getId());
+        if (task != null) {
+            if (!task.cancel(true)) {
+                return;
+            }
+        }
+        if (record.getStatus().equals(AuctionStatus.NOTSTARTED)) {
+            if (record.getStartTime().minusSeconds(2).isAfter(LocalDateTime.now())) {
+                Date date = Date.from(record.getStartTime().atZone(ZoneId.systemDefault()).toInstant());
+                ScheduledFuture<?> future = taskScheduler.schedule(() -> {
+//                    AuctionActivity recordNew1 = auctionActivityRepo.findById(record.getId())
+//                            .orElseThrow(new BusinessException("无数据"));
+                    this.changeStatus(record.getId(), AuctionStatus.ONGOING);
+                    tasks.remove(record.getId());
+//                    offShelfTask(auctionActivityRepo.findById(record.getId()).orElseThrow(new BusinessException("无数据")));
+                }, date);
+                tasks.put(record.getId(), future);
+            } else {
+                this.changeStatus(record.getId(), AuctionStatus.ONGOING);
+//                offShelfTask(auctionActivityRepo.findById(record.getId()).orElseThrow(new BusinessException("无数据")));
+            }
+        }
+    }
+
+    public void offShelfTask(AuctionActivity record) {
+        Long id = record.getId();
+        ScheduledFuture<?> task = tasks.get(id);
+        if (task != null) {
+            if (!task.cancel(true)) {
+                return;
+            }
+        }
+//        AuctionActivity recordNew = auctionActivityRepo.findById(id)
+//                .orElseThrow(new BusinessException("无数据"));
+        if (record.getStatus().equals(AuctionStatus.ONGOING)) {
+            if (record.getEndTime().minusSeconds(2).isAfter(LocalDateTime.now())) {
+                Date date = Date.from(record.getEndTime().atZone(ZoneId.systemDefault()).toInstant());
+                ScheduledFuture<?> future = taskScheduler.schedule(() -> {
+                    AuctionActivity recordNew1 = auctionActivityRepo.findById(id)
+                            .orElseThrow(new BusinessException("无数据"));
+
+                    if (ObjectUtils.isNotEmpty(recordNew1.getPurchasePrice())) {
+                        log.info("拍卖成交{}", recordNew1.getId());
+                        this.changeStatus(recordNew1.getId(), AuctionStatus.PURCHASED);
+                    } else {
+                        //没有成交价,无人出价过
+                        log.info("拍卖流拍Task-else{}", recordNew1.getId());
+                        auctionActivityRepo.scheduleOffShelf(recordNew1.getId(), AuctionStatus.PASS);
+
+                        if (AuctionSource.TRANSFER.equals(recordNew1.getSource())) {
+                            Asset asset = assetRepo.findById(recordNew1.getAssetId())
+                                    .orElseThrow(new BusinessException("暂无"));
+                            asset.setStatus(AssetStatus.NORMAL);
+                            asset.setConsignment(false);
+                            asset.setPublicShow(false);
+                            assetRepo.save(asset);
+                        }
+                    }
+                    tasks.remove(id);
+                }, date);
+                tasks.put(id, future);
+            } else {
+                AuctionActivity recordNew1 = auctionActivityRepo.findById(id)
+                        .orElseThrow(new BusinessException("无数据"));
+                if (ObjectUtils.isNotEmpty(recordNew1.getPurchasePrice())) {
+                    log.info("拍卖成交{}", id);
+                    auctionActivityRepo.scheduleOffShelf(id, AuctionStatus.PURCHASED);
+                } else {
+                    log.info("拍卖流拍Task-else-else{}", id);
+                    auctionActivityRepo.scheduleOffShelf(id, AuctionStatus.PASS);
+
+                    if (AuctionSource.TRANSFER.equals(recordNew1.getSource())) {
+                        Asset asset = assetRepo.findById(recordNew1.getAssetId())
+                                .orElseThrow(new BusinessException("暂无"));
+                        asset.setStatus(AssetStatus.NORMAL);
+                        asset.setConsignment(false);
+                        asset.setPublicShow(false);
+                        assetRepo.save(asset);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 定时下架拍卖
+     * (每隔1分钟执行一次)
+     */
+    @Scheduled(cron = "0 */1 * * * ?")
+    public void passAuction() {
+        List<AuctionActivity> activities = auctionActivityRepo.findAllByStatus(AuctionStatus.ONGOING);
+        activities.forEach(activity -> {
+            if (activity.getEndTime().isBefore(LocalDateTime.now())) {
+                if (ObjectUtils.isNotEmpty(activity.getPurchasePrice())) {
+                    log.info("拍卖成交{}", activity.getId());
+                    this.changeStatus(activity.getId(), AuctionStatus.PURCHASED);
+                } else {
+                    //没有成交价,无人出价过
+                    log.info("拍卖流拍Task-else-else{}", activity.getId());
+                    this.changeStatus(activity.getId(), AuctionStatus.PASS);
+
+                    if (AuctionSource.TRANSFER.equals(activity.getSource())) {
+                        Asset asset = assetRepo.findById(activity.getAssetId())
+                                .orElseThrow(new BusinessException("暂无"));
+                        asset.setStatus(AssetStatus.NORMAL);
+                        asset.setConsignment(false);
+                        asset.setPublicShow(false);
+                        assetRepo.save(asset);
+                    }
+                }
+            }
+        });
+    }
+}

+ 519 - 0
src/main/java/com/izouma/nineth/service/AuctionOrderService.java

@@ -0,0 +1,519 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.config.Constants;
+import com.izouma.nineth.config.RedisKeys;
+import com.izouma.nineth.domain.*;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.*;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.*;
+import com.izouma.nineth.service.sms.SmsService;
+import com.izouma.nineth.utils.JpaUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import com.izouma.nineth.utils.SnowflakeIdWorker;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.data.domain.Page;
+import org.springframework.data.redis.core.BoundValueOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.Transient;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Service
+public class AuctionOrderService {
+
+    @Autowired
+    private AuctionOrderRepo              auctionOrderRepo;
+    @Autowired
+    private SysConfigService              sysConfigService;
+    @Autowired
+    private UserRepo                      userRepo;
+    @Autowired
+    private AssetService                  assetService;
+    @Autowired
+    private AuctionActivityRepo           auctionActivityRepo;
+    @Autowired
+    private AuctionRecordRepo             auctionRecordRepo;
+    @Autowired
+    private AssetRepo                     assetRepo;
+    @Autowired
+    private UserAddressRepo               userAddressRepo;
+    @Autowired
+    private AuctionActivityService        auctionActivityService;
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+    @Autowired
+    private SnowflakeIdWorker             snowflakeIdWorker;
+    @Autowired
+    private AuctionPassRecordRepo         auctionPassRecordRepo;
+    @Lazy
+    @Autowired
+    private OrderPayService               orderPayService;
+    @Autowired
+    private SmsService                    smsService;
+    @Autowired
+    private UserBalanceRepo               userBalanceRepo;
+    @Autowired
+    private BalanceRecordRepo             balanceRecordRepo;
+
+    public Page<AuctionOrder> all(PageQuery pageQuery) {
+        return auctionOrderRepo
+                .findAll(JpaUtils.toSpecification(pageQuery, AuctionOrder.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    public AuctionOrder create(Long userId, Long auctionId, Long addressId, Long auctionRecordId, AuctionPaymentType type) {
+        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
+
+        AuctionActivity auction = auctionActivityRepo.findById(auctionId)
+                .orElseThrow(new BusinessException("无拍卖信息"));
+
+        if (!auction.isOnShelf()) {
+            throw new BusinessException("拍卖已结束");
+        }
+
+        String status = (String) redisTemplate.opsForValue().get(RedisKeys.AUCTION_STATUS + auctionId);
+        if (status == null)
+            status = auction.getStatus().toString();
+        switch (AuctionStatus.valueOf(status)) {
+            case NOTSTARTED:
+                throw new BusinessException("拍卖还未开始");
+//            case PURCHASED:
+//                throw new BusinessException("拍卖成交中");
+            case PASS:
+                throw new BusinessException("已经流拍");
+            case FINISH:
+                throw new BusinessException("拍卖已结束");
+            case FIXED_PRICE_PURCHASED:
+                if (AuctionPaymentType.FIXED_PRICE.equals(type)) {
+                    throw new BusinessException("一口价成交中");
+                }
+        }
+
+        if (user.getId().equals(auction.getSellerId())) {
+            throw new BusinessException("不可自己出价自己");
+        }
+
+        if (AuctionPaymentType.PURCHASE_PRICE.equals(type)) {
+            if (auction.getEndTime().isAfter(LocalDateTime.now())) {
+                throw new BusinessException("拍卖还未结束");
+            }
+            AuctionRecord record = auctionRecordRepo.findTopByAuctionIdAndUserIdOrderByIdDesc(auctionId, userId);
+            if (ObjectUtils.isEmpty(record) || !record.isPayDeposit()) {
+                throw new BusinessException("未支付保证金");
+            }
+            if (record.getBidderPrice().compareTo(auction.getPurchasePrice()) != 0) {
+                throw new BusinessException("与成交价不否");
+            }
+            int time = sysConfigService.getInt("auction_cancel_time");
+            if (LocalDateTime.now().isAfter(auction.getEndTime().plusMinutes(time))) {
+                throw new BusinessException("超过支付时长");
+            }
+        } else {
+            if (auction.getEndTime().isBefore(LocalDateTime.now())) {
+                throw new BusinessException("拍卖已结束");
+            }
+            if (AuctionPaymentType.DEPOSIT.equals(type)) {
+                return this.createDeposit(user, auction);
+            }
+        }
+
+        UserAddress userAddress = null;
+        if (addressId != null) {
+            userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
+        }
+
+        try {
+
+            auctionActivityService.changeStatus(auctionId, AuctionPaymentType.FIXED_PRICE
+                    .equals(type) ? AuctionStatus.FIXED_PRICE_PURCHASED : AuctionStatus.PURCHASED);
+
+            if (AuctionSource.TRANSFER.equals(auction.getSource())) {
+                Asset asset = assetRepo.findById(auction.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
+                asset.setStatus(AssetStatus.AUCTION_TRADING);
+                assetRepo.save(asset);
+            }
+
+            BigDecimal price = AuctionPaymentType.FIXED_PRICE.equals(type) ? auction.getFixedPrice() : auction
+                    .getPurchasePrice();
+
+            AuctionOrder order = AuctionOrder.builder()
+                    .id(snowflakeIdWorker.nextId())
+                    .auctionId(auction.getId())
+                    .userId(user.getId())
+                    .nickname(user.getNickname())
+                    .paymentType(type)
+                    .name(auction.getName())
+                    .pic(auction.getPic())
+                    .serviceCharge(auction.getServiceCharge())
+                    .royalties(auction.getRoyalties())
+                    .source(auction.getSource())
+                    .price(price)
+                    .totalPrice(price)
+                    .auctionRecordId(auctionRecordId)
+                    .status(AuctionOrderStatus.NOT_PAID)
+                    .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
+                    .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
+                    .address(Optional.ofNullable(userAddress).map(UserAddress::getDetail).orElse(null))
+                    .build();
+
+            return auctionOrderRepo.save(order);
+        } catch (Exception e) {
+            auctionActivityService.changeStatus(auctionId, AuctionStatus.ONGOING);
+            throw e;
+        }
+    }
+
+
+    public AuctionOrder createDeposit(User user, AuctionActivity auction) {
+        if (user.getId().equals(auction.getSellerId())) {
+            throw new BusinessException("不可自己出价自己的");
+        }
+
+        //保证金
+//        BigDecimal deposit = sysConfigService.getBigDecimal("deposit");
+        AuctionOrder order = auctionOrderRepo
+                .findByUserIdAndAuctionIdAndPaymentTypeAndStatusIn(user.getId(), auction.getId(),
+                        AuctionPaymentType.DEPOSIT, Arrays
+                                .asList(AuctionOrderStatus.NOT_PAID, AuctionOrderStatus.FINISH));
+        if (ObjectUtils.isNotEmpty(order)) {
+            if (AuctionOrderStatus.FINISH.equals(order.getStatus())) {
+                throw new BusinessException("保证金已交过,无需再交");
+            }
+            throw new BusinessException("保证金未支付,取消后再重新出价");
+        }
+
+        AuctionRecord auctionRecord = AuctionRecord.builder()
+                .auctionId(auction.getId())
+                .type(AuctionRecordType.DEPOSIT)
+                .bidderPrice(auction.getDeposit())
+                .auctionPic(null)
+                .userId(SecurityUtils.getAuthenticatedUser().getId())
+                .avatar(SecurityUtils.getAuthenticatedUser().getAvatar())
+                .name(auction.getName())
+                .purchased(false)
+                .auctionType(auction.getAuctionType())
+                .build();
+        AuctionRecord record = auctionRecordRepo.save(auctionRecord);
+
+        order = AuctionOrder.builder()
+                .id(snowflakeIdWorker.nextId())
+                .auctionId(auction.getId())
+                .userId(user.getId())
+                .nickname(user.getNickname())
+                .paymentType(AuctionPaymentType.DEPOSIT)
+                .name(auction.getName())
+                .pic(auction.getPic())
+                .serviceCharge(auction.getServiceCharge())
+                .royalties(auction.getRoyalties())
+                .source(auction.getSource())
+                .price(auction.getDeposit())
+                .totalPrice(auction.getDeposit())
+                .auctionRecordId(record.getId())
+                .status(AuctionOrderStatus.NOT_PAID)
+                .build();
+
+
+        return auctionOrderRepo.save(order);
+
+    }
+
+    @Transient
+    public void notify(Long id, PayMethod payMethod, String transactionId) {
+        AuctionOrder order = auctionOrderRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+        if (!order.getStatus().equals(AuctionOrderStatus.NOT_PAID)) {
+            throw new BusinessException("订单已处理");
+        }
+        AuctionActivity auction = auctionActivityRepo.findById(order.getAuctionId())
+                .orElseThrow(new BusinessException("无拍卖活动"));
+
+        if (auction.getAuctionType().equals(AuctionType.ENTITY)) {
+            order.setStatus(AuctionOrderStatus.DELIVERY);
+        } else {
+            order.setStatus(AuctionOrderStatus.FINISH);
+        }
+        order.setPayMethod(payMethod);
+        order.setTransactionId(transactionId);
+        order.setPayTime(LocalDateTime.now());
+        //存订单
+        auctionOrderRepo.save(order);
+
+        if (AuctionPaymentType.DEPOSIT.equals(order.getPaymentType())) {
+            //改出价记录表
+            AuctionRecord record = auctionRecordRepo.findById(order.getAuctionRecordId())
+                    .orElseThrow(new BusinessException("无出价记录"));
+            record.setPayDeposit(true);
+            auctionRecordRepo.save(record);
+            return;
+        }
+
+        //此拍卖结束
+        auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.FINISH);
+
+        //修改买家和成交价
+        auction.setPurchaserId(order.getUserId());
+        auction.setPurchasePrice(order.getTotalPrice());
+        auctionActivityRepo.save(auction);
+
+        if (AuctionSource.TRANSFER.equals(order.getSource())) {
+            Asset asset = assetRepo.findById(auction.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
+            if (asset.isPublicShow()) {
+                //取消公开展示
+                assetService.cancelPublic(asset);
+            }
+            User user = userRepo.findById(order.getUserId()).orElseThrow(new BusinessException("无用户"));
+            //转让流程
+            assetService.transfer(asset, order.getTotalPrice(), user, TransferReason.AUCTION, order.getId());
+
+            // 发送短信提醒用户转让成功
+            if (asset.getUserId() != null) {
+                smsService.sellOut(userRepo.findPhoneById(asset.getUserId()));
+            }
+
+            //用户冲余额
+            UserBalance userBalance = userBalanceRepo.findByUserId(asset.getOwnerId())
+                    .orElse(UserBalance.builder()
+                            .balance(BigDecimal.ZERO)
+                            .lastBalance(BigDecimal.ZERO)
+                            .userId(asset.getOwnerId())
+                            .build());
+
+            BigDecimal amount = order.getTotalPrice()
+                    .multiply(BigDecimal.valueOf(100 - order.getRoyalties() - order.getServiceCharge()))
+                    .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
+
+            userBalance.setLastBalance(userBalance.getBalance());
+            userBalance.setBalance(userBalance.getBalance().add(amount));
+            userBalanceRepo.save(userBalance);
+            log.info("拍卖冲用户余额{},¥{}", asset.getOwnerId(), amount);
+
+            balanceRecordRepo.save(BalanceRecord.builder()
+                    .time(LocalDateTime.now())
+                    .userId(asset.getOwnerId())
+                    .orderId(order.getId())
+                    .amount(amount)
+                    .balance(userBalance.getBalance())
+                    .lastBalance(userBalance.getLastBalance())
+                    .type(BalanceType.SELL)
+                    .build());
+
+
+        }
+
+        //改出价记录表为竞得(一口价无出价表)
+        auctionRecordRepo.findById(order.getAuctionRecordId())
+                .ifPresent(record -> {
+                    record.setPurchased(true);
+                    auctionRecordRepo.save(record);
+                });
+
+
+        //退保证金
+        List<AuctionOrder> orders = auctionOrderRepo.findAllByAuctionIdAndPaymentTypeAndStatus(order.getAuctionId(),
+                AuctionPaymentType.DEPOSIT, AuctionOrderStatus.FINISH);
+        //退款
+        orders.forEach(this::refund);
+    }
+
+    public void cancel(AuctionOrder order) {
+        if (!getOrderLock(order.getId())) {
+            log.error("订单取消失败 {}, redis锁了", order.getId());
+            return;
+        }
+
+        boolean isRefund = false;
+        try {
+            AuctionActivity auction = auctionActivityRepo.findById(order.getAuctionId())
+                    .orElseThrow(new BusinessException("无记录"));
+
+            if (AuctionPaymentType.PURCHASE_PRICE.equals(order.getPaymentType())) {
+                //如果是拍卖,需获取取消订单的时长
+                int time = sysConfigService.getInt("auction_cancel_time");
+                if (LocalDateTime.now().isAfter(auction.getEndTime().plusMinutes(time))) {
+                    //超过支付时长
+                    log.info("取消订单流拍:{}", auction.getId());
+                    auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.PASS);
+                    //添加到流拍记录表里
+                    auctionPassRecordRepo.save(AuctionPassRecord.builder()
+                            .auctionId(auction.getId())
+                            .userId(auction.getPurchaserId())
+                            .purchasePrice(auction.getPurchasePrice())
+                            .build());
+                    //流拍不退自己的保证金
+                    isRefund = true;
+
+                    if (AuctionSource.TRANSFER.equals(order.getSource())) {
+                        //改回资产状态
+                        Asset asset = assetRepo.findById(auction.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
+                        asset.setStatus(AssetStatus.NORMAL);
+                        assetRepo.save(asset);
+                    }
+
+                }
+            } else if (AuctionPaymentType.DEPOSIT.equals(order.getPaymentType())) {
+                //删除出价记录
+                auctionRecordRepo.softDelete(order.getAuctionRecordId());
+            } else {
+                //拍卖是否结束
+                if (LocalDateTime.now().isBefore(auction.getEndTime())) {
+                    //返回拍卖状态
+                    auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.ONGOING);
+                } else {
+                    //最后一个出价的人得
+                    auctionActivityService.changeStatus(order.getAuctionId(), AuctionStatus.PURCHASED);
+                }
+            }
+
+            order.setStatus(AuctionOrderStatus.CANCELLED);
+            order.setCancelTime(LocalDateTime.now());
+            auctionOrderRepo.save(order);
+            log.info("取消订单{}", order.getId());
+
+        } catch (Exception e) {
+            log.error("订单取消错误 orderId: " + order.getId(), e);
+        }
+
+        if (isRefund) {
+            //退其余保证金
+            List<AuctionOrder> orders = auctionOrderRepo
+                    .findAllByAuctionIdAndPaymentTypeAndStatus(order.getAuctionId(),
+                            AuctionPaymentType.DEPOSIT, AuctionOrderStatus.FINISH);
+            //退款
+            orders.stream()
+                    .filter(o -> !order.getUserId().equals(o.getUserId()))
+                    .forEach(this::refund);
+        }
+        releaseOrderLock(order.getId());
+    }
+
+    /**
+     * 退款方法
+     *
+     * @param order 订单
+     */
+    private void refund(AuctionOrder order) {
+        log.info("退款拍卖保证金订单{}", order.getId());
+        PayMethod payMethod = order.getPayMethod();
+        if (PayMethod.ALIPAY == payMethod) {
+            if (StringUtils.length(order.getTransactionId()) == 28) {
+                payMethod = PayMethod.HMPAY;
+            } else if (StringUtils.length(order.getTransactionId()) == 30) {
+                payMethod = PayMethod.SANDPAY;
+            }
+        }
+        try {
+            switch (payMethod) {
+                case HMPAY:
+                    orderPayService.refund(order.getId().toString(), order.getTransactionId(), order.getTotalPrice(), Constants.PayChannel.HM);
+                    log.info("退款成功{}", order.getId());
+                    break;
+                case SANDPAY:
+                    orderPayService.refund(order.getId().toString(), order.getTransactionId(), order.getTotalPrice(), Constants.PayChannel.SAND);
+                    log.info("退款成功{}", order.getId());
+                    break;
+                case PAYEASE:
+                    orderPayService.refund(order.getId().toString(), order.getTransactionId(), order.getTotalPrice(), Constants.PayChannel.PE);
+                    log.info("退款成功{}", order.getId());
+                    break;
+            }
+            order.setRefundTime(LocalDateTime.now());
+            order.setStatus(AuctionOrderStatus.REFUNDED);
+            auctionOrderRepo.save(order);
+        } catch (Exception e) {
+            log.error("拍卖保证金订单退款失败 {} ", order.getId(), e);
+            order.setRefundTime(LocalDateTime.now());
+            order.setStatus(AuctionOrderStatus.REFUNDING);
+            auctionOrderRepo.save(order);
+        }
+    }
+
+    public boolean getOrderLock(Long orderId) {
+        BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.AUCTION_ORDER_LOCK + orderId);
+        Boolean flag = ops.setIfAbsent(1, 1, TimeUnit.DAYS);
+        return Boolean.TRUE.equals(flag);
+    }
+
+    public void releaseOrderLock(Long orderId) {
+        redisTemplate.delete(RedisKeys.AUCTION_ORDER_LOCK + orderId);
+    }
+
+    @Scheduled(cron = "0 0/10 * * * ?")
+    public void passOverTimeAuction() {
+        List<AuctionActivity> purchased = auctionActivityRepo.findAllByStatus(AuctionStatus.PURCHASED);
+        if (purchased != null) {
+            int time = sysConfigService.getInt("auction_cancel_time");
+            purchased.forEach(act -> {
+                if (LocalDateTime.now().isAfter(act.getEndTime().plusMinutes(time))) {
+                    List<AuctionOrder> auctionOrders = auctionOrderRepo.findAllByAuctionIdAndPaymentTypeAndStatus(act
+                            .getId(), AuctionPaymentType.PURCHASE_PRICE, AuctionOrderStatus.NOT_PAID);
+//                    if (CollUtil.isNotEmpty(auctionOrders)) {
+                    auctionOrders.forEach(this::cancel);
+//                        return;
+//                    }
+
+                    auctionActivityService.changeStatus(act.getId(), AuctionStatus.PASS);
+                    log.info("拍卖定时任务流拍{}", act.getId());
+
+                    if (AuctionSource.TRANSFER.equals(act.getSource())) {
+                        //改回资产状态
+                        Asset asset = assetRepo.findById(act.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
+                        asset.setStatus(AssetStatus.NORMAL);
+                        assetRepo.save(asset);
+                    }
+
+                    //退其余保证金
+                    List<AuctionOrder> orders = auctionOrderRepo
+                            .findAllByAuctionIdAndPaymentTypeAndStatus(act.getId(),
+                                    AuctionPaymentType.DEPOSIT, AuctionOrderStatus.FINISH);
+                    //退款
+                    orders.stream()
+                            .filter(o -> !act.getPurchaserId().equals(o.getUserId()))
+                            .forEach(this::refund);
+
+                    //添加到流拍记录表里
+                    auctionPassRecordRepo.save(AuctionPassRecord.builder()
+                            .auctionId(act.getId())
+                            .userId(act.getPurchaserId())
+                            .purchasePrice(act.getPurchasePrice())
+                            .build());
+                }
+            });
+        }
+    }
+
+    /**
+     * 发货
+     *
+     * @param id        编号
+     * @param courierId 快递单号
+     */
+    public void dispatch(Long id, String courierId) {
+        AuctionOrder auctionOrder = auctionOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
+        auctionOrder.setStatus(AuctionOrderStatus.RECEIVE);
+        auctionOrder.setCourierId(courierId);
+        auctionOrderRepo.save(auctionOrder);
+    }
+
+    /**
+     * 订单
+     *
+     * @param id 编号
+     */
+    public void finish(Long id) {
+        AuctionOrder auctionOrder = auctionOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
+        auctionOrder.setStatus(AuctionOrderStatus.FINISH);
+        auctionOrderRepo.save(auctionOrder);
+    }
+}

+ 209 - 0
src/main/java/com/izouma/nineth/service/AuctionRecordService.java

@@ -0,0 +1,209 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.config.RedisKeys;
+import com.izouma.nineth.domain.*;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.auction.AuctionRecordDTO;
+import com.izouma.nineth.enums.*;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.AuctionActivityRepo;
+import com.izouma.nineth.repo.AuctionOrderRepo;
+import com.izouma.nineth.repo.AuctionRecordRepo;
+import com.izouma.nineth.repo.UserRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Service
+@AllArgsConstructor
+public class AuctionRecordService {
+
+    private AuctionRecordRepo             auctionRecordRepo;
+    private AuctionActivityRepo           auctionActivityRepo;
+    private AuctionOrderRepo              auctionOrderRepo;
+    private RedisTemplate<String, Object> redisTemplate;
+    private UserRepo                      userRepo;
+
+    public Page<AuctionRecord> all(PageQuery pageQuery) {
+        return auctionRecordRepo
+                .findAll(JpaUtils.toSpecification(pageQuery, AuctionRecord.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    public Page<AuctionRecordDTO> recordInfos(PageQuery pageQuery) {
+
+        Page<AuctionRecord> records = auctionRecordRepo
+                .findAll(JpaUtils.toSpecification(pageQuery, AuctionRecord.class), JpaUtils.toPageRequest(pageQuery));
+
+        List<AuctionRecordDTO> auctionRecordDTOS = new ArrayList<>();
+        records.getContent().forEach(record -> {
+            AuctionActivity auctionActivity = auctionActivityRepo.findById(record.getAuctionId())
+                    .orElse(null);
+            if (auctionActivity == null) {
+                return;
+            }
+            AuctionRecordDTO auctionRecordDTO = new AuctionRecordDTO();
+            auctionRecordDTO.setAuctionId(record.getAuctionId());
+            auctionRecordDTO.setAuctionPic(auctionActivity.getPic());
+            auctionRecordDTO.setMinter(auctionActivity.getMinter());
+            auctionRecordDTO.setBidderPrice(record.getBidderPrice());
+            auctionRecordDTO.setActPurchasedId((auctionActivity.getPurchaserId()));
+            auctionRecordDTO.setName(record.getName());
+            auctionRecordDTO.setDeposit(auctionActivity.getDeposit());
+            auctionRecordDTO.setEndTime(auctionActivity.getEndTime());
+            auctionRecordDTO.setCreatedTime(record.getCreatedAt());
+            auctionRecordDTO.setUserId(record.getUserId());
+            auctionRecordDTO.setType(record.getType());
+            auctionRecordDTO.setPurchased(record.isPurchased());
+            auctionRecordDTO.setAuctionStatus(auctionActivity.getStatus());
+            auctionRecordDTO.setAuctionType(auctionActivity.getAuctionType());
+//            if (auctionActivity.getStatus().equals(AuctionStatus.PURCHASED) || auctionActivity.getStatus()
+//                    .equals(AuctionStatus.FINISH)) {
+//                if (auctionActivity.getRecordId() != null) {
+//                    if (auctionActivity.getRecordId().equals(record.getId())) {
+//                        auctionRecordDTO.setPurchased(true);
+//                    }
+//                }
+//            }
+            if (auctionRecordDTO.getType().equals(AuctionRecordType.DEPOSIT) || auctionRecordDTO.isPurchased()) {
+                AuctionOrder auctionOrder = auctionOrderRepo.findFirstByAuctionRecordIdOrderByCreatedAt(record.getId());
+                if (auctionOrder != null) {
+                    auctionRecordDTO.setOrderId(auctionOrder.getId());
+                    auctionRecordDTO.setOrderStatus(auctionOrder.getStatus());
+                }
+            }
+            Set<AuctionOrderStatus> auctionOrderStatuses = new HashSet<>();
+            auctionOrderStatuses.add(AuctionOrderStatus.NOT_PAID);
+            auctionOrderStatuses.add(AuctionOrderStatus.CANCELLED);
+            AuctionOrder depositOrder = auctionOrderRepo.findFirstByAuctionIdAndPaymentTypeAndStatusNotIn(record
+                    .getAuctionId(), AuctionPaymentType.DEPOSIT, auctionOrderStatuses);
+            if (depositOrder != null) {
+                auctionRecordDTO.setDepositStatus(depositOrder.getStatus());
+            } else {
+                auctionRecordDTO.setDepositStatus(AuctionOrderStatus.FINISH);
+            }
+            auctionRecordDTOS.add(auctionRecordDTO);
+        });
+        return new PageImpl<>(auctionRecordDTOS, records.getPageable(), records.getTotalElements());
+    }
+
+    public List<AuctionRecordDTO> userRecord(Long userId, String type) {
+        List<AuctionRecord> records = auctionRecordRepo.findByUserId(userId, type);
+        List<AuctionRecordDTO> auctionRecordDTOS = new ArrayList<>();
+        records.forEach(record -> {
+            AuctionActivity auctionActivity = auctionActivityRepo.findById(record.getAuctionId())
+                    .orElse(null);
+            if (auctionActivity == null) {
+                return;
+            }
+            AuctionRecordDTO auctionRecordDTO = new AuctionRecordDTO();
+            BeanUtils.copyProperties(record, auctionRecordDTO);
+            auctionRecordDTO.setAuctionPic(auctionActivity.getPic());
+            auctionRecordDTO.setMinter(auctionActivity.getMinter());
+            auctionRecordDTO.setAuctionPic(auctionActivity.getPic());
+            auctionRecordDTO.setActPurchasedId((auctionActivity.getPurchaserId()));
+            auctionRecordDTO.setDeposit(auctionActivity.getDeposit());
+            auctionRecordDTO.setEndTime(auctionActivity.getEndTime());
+            auctionRecordDTO.setAuctionType(auctionActivity.getAuctionType());
+            auctionRecordDTO.setAuctionStatus(auctionActivity.getStatus());
+            auctionRecordDTO.setCreatedTime(record.getCreatedAt());
+//            if (auctionRecordDTO.getType().equals(AuctionRecordType.DEPOSIT) || auctionRecordDTO.isPurchased()) {
+            AuctionOrder auctionOrder = auctionOrderRepo.findFirstByAuctionRecordIdOrderByIdDesc(record.getId());
+            if (auctionOrder != null) {
+                auctionRecordDTO.setOrderId(auctionOrder.getId());
+                auctionRecordDTO.setOrderStatus(auctionOrder.getStatus());
+            }
+//            }
+            Set<AuctionOrderStatus> auctionOrderStatuses = new HashSet<>();
+            auctionOrderStatuses.add(AuctionOrderStatus.NOT_PAID);
+            auctionOrderStatuses.add(AuctionOrderStatus.CANCELLED);
+            AuctionOrder depositOrder = auctionOrderRepo.findFirstByAuctionIdAndPaymentTypeAndStatusNotIn(record
+                    .getAuctionId(), AuctionPaymentType.DEPOSIT, auctionOrderStatuses);
+            if (depositOrder != null) {
+                auctionRecordDTO.setDepositStatus(depositOrder.getStatus());
+            } else {
+                auctionRecordDTO.setDepositStatus(AuctionOrderStatus.FINISH);
+            }
+            auctionRecordDTOS.add(auctionRecordDTO);
+        });
+        return auctionRecordDTOS;
+    }
+
+    public AuctionRecord create(Long userId, Long auctionId, BigDecimal amount) {
+        AuctionActivity auction = auctionActivityRepo.findById(auctionId)
+                .orElseThrow(new BusinessException("暂无"));
+
+        String status = (String) redisTemplate.opsForValue().get(RedisKeys.AUCTION_STATUS + auctionId);
+        if (status == null)
+            status = auction.getStatus().toString();
+        switch (AuctionStatus.valueOf(status)) {
+            case NOTSTARTED:
+                throw new BusinessException("拍卖还未开始");
+            case PURCHASED:
+                throw new BusinessException("拍卖成交中");
+            case PASS:
+            case FINISH:
+                throw new BusinessException("拍卖已结束");
+        }
+
+        AuctionRecord record = auctionRecordRepo.findTopByAuctionIdAndUserIdOrderByIdDesc(auctionId, userId);
+        if (ObjectUtils.isEmpty(record)) {
+            User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
+
+            return auctionRecordRepo.save(AuctionRecord.builder()
+                    .auctionId(auctionId)
+                    .userId(userId)
+                    .avatar(user.getAvatar())
+                    .user(user.getNickname())
+                    .name(auction.getName())
+                    .auctionPic(null)
+                    .bidderPrice(amount)
+                    .purchased(false)
+                    .type(AuctionRecordType.DEPOSIT)
+                    .payDeposit(false)
+                    .auctionType(auction.getAuctionType())
+                    .build());
+        }
+
+        if (auction.getPurchasePrice() != null) {
+            if (auction.getPurchasePrice().compareTo(amount) >= 0) {
+                throw new BusinessException("出价低于当前竞拍价");
+            }
+        } else if (auction.getStartingPrice().compareTo(amount) >= 0) {
+
+            throw new BusinessException("出价低于当前起拍价");
+        }
+        if (SecurityUtils.getAuthenticatedUser().getId().equals(auction.getPurchaserId())) {
+            throw new BusinessException("请勿重复竞价");
+        }
+        AuctionRecord save = new AuctionRecord();
+        BeanUtils.copyProperties(record, save);
+        save.setId(null);
+        save.setUser(SecurityUtils.getAuthenticatedUser().getNickname());
+        save.setBidderPrice(amount);
+        save.setType(AuctionRecordType.BIDDER);
+        save = auctionRecordRepo.save(save);
+
+        if (record.isPayDeposit()) {
+            //保证金支付过,改成交价
+            auction.setPurchasePrice(amount);
+            auction.setPurchaser(SecurityUtils.getAuthenticatedUser().getNickname());
+            auction.setPurchaserId(SecurityUtils.getAuthenticatedUser().getId());
+            auction.setRecordId(save.getId());
+            auction.setBids(auction.getBids() + 1);
+            auctionActivityRepo.save(auction);
+        }
+        return save;
+    }
+}

+ 5 - 0
src/main/java/com/izouma/nineth/service/CacheService.java

@@ -112,4 +112,9 @@ public class CacheService {
     @CacheEvict(value = "sysConfigGet", allEntries = true)
     @CacheEvict(value = "sysConfigGet", allEntries = true)
     public void clearSysConfigGet() {
     public void clearSysConfigGet() {
     }
     }
+
+    @CacheEvict(value = "auction", key = "#id")
+    public void clearAuction(Long id) {
+    }
+
 }
 }

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

@@ -32,7 +32,7 @@ public class CaptchaService {
 
 
         // 算术类型
         // 算术类型
         ArithmeticCaptcha captcha = new ArithmeticCaptcha(150, 48);
         ArithmeticCaptcha captcha = new ArithmeticCaptcha(150, 48);
-        captcha.setFont(com.pig4cloud.captcha.base.Captcha.FONT_7, 15 * 2);
+        captcha.setFont(6, 15 * 2);
         captcha.setLen(2);  // 几位数运算,默认是两位
         captcha.setLen(2);  // 几位数运算,默认是两位
         captcha.getArithmeticString();  // 获取运算的公式:3+2=?
         captcha.getArithmeticString();  // 获取运算的公式:3+2=?
         captcha.supportAlgorithmSign(2); // 可设置支持的算法:2 表示只生成带加减法的公式
         captcha.supportAlgorithmSign(2); // 可设置支持的算法:2 表示只生成带加减法的公式

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

@@ -22,6 +22,7 @@ import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.RandomUtils;
 import org.apache.commons.lang3.RandomUtils;
 import org.apache.commons.lang3.Range;
 import org.apache.commons.lang3.Range;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.rocketmq.client.consumer.LitePullConsumer;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.cache.annotation.Cacheable;
@@ -75,7 +76,8 @@ public class CollectionService {
         if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
         if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
             return;
             return;
         }
         }
-        List<Collection> collections = collectionRepo.findByScheduleSaleTrueAndOnShelfFalseAndStartTimeBeforeAndDelFalse(LocalDateTime.now());
+        List<Collection> collections = collectionRepo
+                .findByScheduleSaleTrueAndOnShelfFalseAndStartTimeBeforeAndDelFalse(LocalDateTime.now());
         for (Collection collection : collections) {
         for (Collection collection : collections) {
             onShelfTask(collection);
             onShelfTask(collection);
         }
         }
@@ -235,7 +237,9 @@ public class CollectionService {
                     collectionDTO.setAppointment(appointmentRepo.findFirstByBlindBoxId(collection.getId()).isPresent());
                     collectionDTO.setAppointment(appointmentRepo.findFirstByBlindBoxId(collection.getId()).isPresent());
                 }
                 }
                 if (showVip && collection.getAssignment() > 0 && user.getVipPurchase() > 0) {
                 if (showVip && collection.getAssignment() > 0 && user.getVipPurchase() > 0) {
-                    int purchase = orderRepo.countByUserIdAndCollectionIdAndVipTrueAndStatusIn(user.getId(), collection.getId(), Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
+                    int purchase = orderRepo
+                            .countByUserIdAndCollectionIdAndVipTrueAndStatusIn(user.getId(), collection.getId(), Arrays
+                                    .asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
                     collectionDTO.setVipSurplus(user.getVipPurchase() - purchase);
                     collectionDTO.setVipSurplus(user.getVipPurchase() - purchase);
                 }
                 }
             }
             }
@@ -294,7 +298,8 @@ public class CollectionService {
                 collection.setLiked(likes.stream().anyMatch(l -> l.getCollectionId().equals(collection.getId())));
                 collection.setLiked(likes.stream().anyMatch(l -> l.getCollectionId().equals(collection.getId())));
             }
             }
             if (!appointments.isEmpty()) {
             if (!appointments.isEmpty()) {
-                collection.setAppointment(appointments.stream().anyMatch(a -> a.getBlindBoxId().equals(collection.getId())));
+                collection.setAppointment(appointments.stream()
+                        .anyMatch(a -> a.getBlindBoxId().equals(collection.getId())));
             }
             }
         });
         });
     }
     }
@@ -340,6 +345,7 @@ public class CollectionService {
             BlindBoxItem blindBoxItem = new BlindBoxItem();
             BlindBoxItem blindBoxItem = new BlindBoxItem();
             BeanUtils.copyProperties(collection, blindBoxItem);
             BeanUtils.copyProperties(collection, blindBoxItem);
             blindBoxItem.setId(null);
             blindBoxItem.setId(null);
+            blindBoxItem.setOasisId(collection.getOasisId());
             blindBoxItem.setCollectionId(item.getCollectionId());
             blindBoxItem.setCollectionId(item.getCollectionId());
             blindBoxItem.setSale(0);
             blindBoxItem.setSale(0);
             blindBoxItem.setTotal(item.getTotal());
             blindBoxItem.setTotal(item.getTotal());
@@ -615,4 +621,32 @@ public class CollectionService {
 
 
         return dtos;
         return dtos;
     }
     }
+
+    public List<Collection> setOasisScancode(List<Long> oasisIds) {
+        List<Collection> collections = collectionRepo
+                .findAllByOasisIdInAndSourceAndSaleLessThan(oasisIds, CollectionSource.COMPANY, 1);
+        List<Collection> result = new ArrayList<>();
+        collections.forEach(collection -> {
+            collection.setOnShelf(false);
+            collection.setScanCode(true);
+            collection.setSalable(true);
+            collectionRepo.save(collection);
+            result.add(collection);
+        });
+        return result;
+    }
+
+    public List<Collection> setOasisOnShelf(List<Long> oasisIds) {
+        List<Collection> collections = collectionRepo
+                .findAllByOasisIdInAndSourceAndSaleLessThan(oasisIds, CollectionSource.COMPANY, 1);
+        List<Collection> result = new ArrayList<>();
+        collections.forEach(collection -> {
+            collection.setOnShelf(true);
+            collection.setScanCode(false);
+            collection.setSalable(true);
+            collectionRepo.save(collection);
+            result.add(collection);
+        });
+        return result;
+    }
 }
 }

+ 106 - 1
src/main/java/com/izouma/nineth/service/CompanyCollectionService.java

@@ -1,7 +1,11 @@
 package com.izouma.nineth.service;
 package com.izouma.nineth.service;
 
 
+import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.oasis.OasisDistrictCollectionDTO;
+import com.izouma.nineth.dto.oasis.OasisDistrictDTO;
+import com.izouma.nineth.enums.AssetStatus;
 import com.izouma.nineth.enums.CollectionSource;
 import com.izouma.nineth.enums.CollectionSource;
 import com.izouma.nineth.enums.CollectionStatus;
 import com.izouma.nineth.enums.CollectionStatus;
 import com.izouma.nineth.enums.CollectionType;
 import com.izouma.nineth.enums.CollectionType;
@@ -14,6 +18,11 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 @Service
 @Service
 @AllArgsConstructor
 @AllArgsConstructor
 public class CompanyCollectionService {
 public class CompanyCollectionService {
@@ -23,9 +32,12 @@ public class CompanyCollectionService {
     private UserRepo                userRepo;
     private UserRepo                userRepo;
     private CollectionPrivilegeRepo collectionPrivilegeRepo;
     private CollectionPrivilegeRepo collectionPrivilegeRepo;
     private SysConfigService        sysConfigService;
     private SysConfigService        sysConfigService;
+    private AssetRepo               assetRepo;
+    private GeneralProperties       generalProperties;
 
 
     public Page<CompanyCollection> all(PageQuery pageQuery) {
     public Page<CompanyCollection> all(PageQuery pageQuery) {
-        return companyCollectionRepo.findAll(JpaUtils.toSpecification(pageQuery, CompanyCollection.class), JpaUtils.toPageRequest(pageQuery));
+        return companyCollectionRepo.findAll(JpaUtils.toSpecification(pageQuery, CompanyCollection.class), JpaUtils
+                .toPageRequest(pageQuery));
     }
     }
 
 
     public void audit(Long id, CollectionStatus status, String reason) {
     public void audit(Long id, CollectionStatus status, String reason) {
@@ -85,4 +97,97 @@ public class CompanyCollectionService {
         companyCollectionRepo.save(companyCollection);
         companyCollectionRepo.save(companyCollection);
     }
     }
 
 
+
+    public List<OasisDistrictCollectionDTO> oasisSearch(List<Long> oasisIds) {
+        List<OasisDistrictCollectionDTO> oasisDistrictCollectionDTOS = new ArrayList<>();
+        List<AssetStatus> assetStatuses = new ArrayList<>();
+        assetStatuses.add(AssetStatus.NORMAL);
+        assetStatuses.add(AssetStatus.AUCTION_TRADING);
+        assetStatuses.add(AssetStatus.GIFTING);
+        assetStatuses.add(AssetStatus.TRADING);
+        assetStatuses.add(AssetStatus.MINTING);
+        assetStatuses.add(AssetStatus.AUCTIONING);
+        List<Asset> assets = assetRepo
+                .findAllByOasisIdInAndStatusIn(oasisIds, assetStatuses);
+        List<CompanyCollection> companyCollections = companyCollectionRepo
+                .findAllByOasisIdInAndStatusNot(oasisIds, CollectionStatus.SUCCESS);
+        List<Collection> officialCollections = collectionRepo
+                .findAllByOasisIdInAndSourceAndSaleLessThan(oasisIds, CollectionSource.COMPANY, 1);
+
+        assets.forEach(asset -> {
+            OasisDistrictCollectionDTO oasisDistrictCollectionDTO = new OasisDistrictCollectionDTO();
+            oasisDistrictCollectionDTO.setOasisId(asset.getOasisId());
+            oasisDistrictCollectionDTO.setCollectionName(asset.getName());
+            oasisDistrictCollectionDTO.setOriginPrice(asset.getPrice());
+            oasisDistrictCollectionDTO.setScanOnly(false);
+            oasisDistrictCollectionDTO.setOwnerId(asset.getOwnerId());
+            oasisDistrictCollectionDTO.setOwnerName(asset.getOwner());
+            oasisDistrictCollectionDTO.setOwnerAvatar(asset.getOwnerAvatar());
+            oasisDistrictCollectionDTO.setCollectionId(asset.getId());
+            if (!asset.getStatus().equals(AssetStatus.NORMAL)) {
+                oasisDistrictCollectionDTO.setStatus(asset.getStatus().getDescription());
+            } else {
+                if (asset.isPublicShow()) {
+                    Collection collection = collectionRepo.findFirstByOnShelfAndAssetId(true, asset.getId());
+                    oasisDistrictCollectionDTO.setUrl(
+                            generalProperties.getHost() + "/9th/productDetail/" + collection
+                                    .getId() + "?id=" + collection.getId());
+                    if (asset.isConsignment()) {
+                        oasisDistrictCollectionDTO.setStatus("寄售中");
+                    } else {
+                        oasisDistrictCollectionDTO.setStatus("仅展示");
+                    }
+                } else {
+                    oasisDistrictCollectionDTO.setStatus("未展示");
+                }
+            }
+            oasisDistrictCollectionDTO.setSource("二手");
+            oasisDistrictCollectionDTOS.add(oasisDistrictCollectionDTO);
+        });
+
+        officialCollections.forEach(collection -> {
+            OasisDistrictCollectionDTO oasisDistrictCollectionDTO = new OasisDistrictCollectionDTO();
+            oasisDistrictCollectionDTO.setOasisId(collection.getOasisId());
+            oasisDistrictCollectionDTO.setCollectionName(collection.getName());
+            oasisDistrictCollectionDTO.setOriginPrice(collection.getPrice());
+            oasisDistrictCollectionDTO.setSalable(collection.isSalable());
+            oasisDistrictCollectionDTO.setOwnerId(collection.getOwnerId());
+            oasisDistrictCollectionDTO.setOwnerName(collection.getOwner());
+            oasisDistrictCollectionDTO.setOwnerAvatar(collection.getOwnerAvatar());
+            oasisDistrictCollectionDTO.setCollectionId(collection.getId());
+            oasisDistrictCollectionDTO.setScanOnly(collection.isScanCode());
+            oasisDistrictCollectionDTO.setSource("官方");
+            if (collection.isOnShelf()) {
+                oasisDistrictCollectionDTO.setUrl(
+                        generalProperties.getHost() + "/9th/productDetail/" + collection
+                                .getId() + "?id=" + collection.getId());
+                if (collection.isSalable()) {
+                    oasisDistrictCollectionDTO.setStatus("在售");
+                    if (collection.getStock() == 0) {
+                        oasisDistrictCollectionDTO.setStatus("已有订单,订单处理中");
+                    }
+                } else {
+                    oasisDistrictCollectionDTO.setStatus("仅展示");
+                }
+            } else {
+                oasisDistrictCollectionDTO.setStatus("未上架");
+            }
+            oasisDistrictCollectionDTOS.add(oasisDistrictCollectionDTO);
+        });
+
+        companyCollections.forEach(companyCollection -> {
+            OasisDistrictCollectionDTO oasisDistrictCollectionDTO = new OasisDistrictCollectionDTO();
+            oasisDistrictCollectionDTO.setOasisId(companyCollection.getOasisId());
+            oasisDistrictCollectionDTO.setCollectionName(companyCollection.getName());
+            oasisDistrictCollectionDTO.setScanOnly(false);
+            oasisDistrictCollectionDTO.setOriginPrice(companyCollection.getPrice());
+            oasisDistrictCollectionDTO.setOwnerName(companyCollection.getMinter());
+            oasisDistrictCollectionDTO.setCollectionId(companyCollection.getId());
+            oasisDistrictCollectionDTO.setSalable(false);
+            oasisDistrictCollectionDTO.setStatus("审核中");
+            oasisDistrictCollectionDTO.setSource("官方");
+            oasisDistrictCollectionDTOS.add(oasisDistrictCollectionDTO);
+        });
+        return oasisDistrictCollectionDTOS;
+    }
 }
 }

+ 1 - 3
src/main/java/com/izouma/nineth/service/MintOrderService.java

@@ -347,9 +347,7 @@ public class MintOrderService {
                     .mintActivityId(mintActivityId)
                     .mintActivityId(mintActivityId)
                     .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
                     .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
                     .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
                     .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
-                    .address(Optional.ofNullable(userAddress).map(u ->
-                                    u.getProvinceName() + " " + u.getCityName() + " " + u.getDistrictName() + " " + u.getAddress())
-                            .orElse(null))
+                    .address(Optional.ofNullable(userAddress).map(UserAddress::getDetail).orElse(null))
                     .build());
                     .build());
 
 
             // 铸造资产
             // 铸造资产

+ 25 - 4
src/main/java/com/izouma/nineth/service/NewsLikeService.java

@@ -2,6 +2,7 @@ package com.izouma.nineth.service;
 
 
 import com.izouma.nineth.domain.NewsLike;
 import com.izouma.nineth.domain.NewsLike;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.AuctionActivityRepo;
 import com.izouma.nineth.repo.NewsLikeRepo;
 import com.izouma.nineth.repo.NewsLikeRepo;
 import com.izouma.nineth.repo.NewsRepo;
 import com.izouma.nineth.repo.NewsRepo;
 import com.izouma.nineth.repo.ShowroomRepo;
 import com.izouma.nineth.repo.ShowroomRepo;
@@ -16,12 +17,14 @@ import java.util.List;
 @AllArgsConstructor
 @AllArgsConstructor
 public class NewsLikeService {
 public class NewsLikeService {
 
 
-    private NewsLikeRepo newsLikeRepo;
-    private NewsRepo     newsRepo;
-    private ShowroomRepo showroomRepo;
+    private NewsLikeRepo        newsLikeRepo;
+    private NewsRepo            newsRepo;
+    private ShowroomRepo        showroomRepo;
+    private AuctionActivityRepo auctionActivityRepo;
 
 
     public Page<NewsLike> all(PageQuery pageQuery) {
     public Page<NewsLike> all(PageQuery pageQuery) {
-        return newsLikeRepo.findAll(JpaUtils.toSpecification(pageQuery, NewsLike.class), JpaUtils.toPageRequest(pageQuery));
+        return newsLikeRepo
+                .findAll(JpaUtils.toSpecification(pageQuery, NewsLike.class), JpaUtils.toPageRequest(pageQuery));
     }
     }
 
 
     public void like(Long userId, Long newsId) {
     public void like(Long userId, Long newsId) {
@@ -59,4 +62,22 @@ public class NewsLikeService {
             showroomRepo.addLike(roomId, -list.size());
             showroomRepo.addLike(roomId, -list.size());
         }
         }
     }
     }
+
+    public void likeAuction(Long userId, Long auctionId) {
+        List<NewsLike> list = newsLikeRepo.findByUserIdAndAuctionId(userId, auctionId);
+        if (!list.isEmpty()) return;
+        newsLikeRepo.save(NewsLike.builder()
+                .userId(userId)
+                .auctionId(auctionId)
+                .build());
+        auctionActivityRepo.addLike(auctionId, 1);
+    }
+
+    public void unlikeAuction(Long userId, Long auctionId) {
+        List<NewsLike> list = newsLikeRepo.findByUserIdAndAuctionId(userId, auctionId);
+        if (!list.isEmpty()) {
+            newsLikeRepo.deleteAll(list);
+            auctionActivityRepo.addLike(auctionId, -list.size());
+        }
+    }
 }
 }

+ 20 - 14
src/main/java/com/izouma/nineth/service/OrderCancelService.java

@@ -1,21 +1,11 @@
 package com.izouma.nineth.service;
 package com.izouma.nineth.service;
 
 
-import com.izouma.nineth.annotations.RedisLock;
 import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.config.GeneralProperties;
-import com.izouma.nineth.config.RedisKeys;
-import com.izouma.nineth.domain.GiftOrder;
-import com.izouma.nineth.domain.MintOrder;
 import com.izouma.nineth.domain.Order;
 import com.izouma.nineth.domain.Order;
 import com.izouma.nineth.domain.SysConfig;
 import com.izouma.nineth.domain.SysConfig;
-import com.izouma.nineth.dto.PayQuery;
-import com.izouma.nineth.enums.MintOrderStatus;
 import com.izouma.nineth.enums.OrderStatus;
 import com.izouma.nineth.enums.OrderStatus;
-import com.izouma.nineth.enums.PayStatus;
 import com.izouma.nineth.exception.BusinessException;
 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.repo.SysConfigRepo;
+import com.izouma.nineth.repo.*;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -25,10 +15,7 @@ import org.springframework.stereotype.Service;
 
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PostConstruct;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
-import java.util.Arrays;
 import java.util.List;
 import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
 
 
 @Service
 @Service
 @ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
 @ConditionalOnProperty(value = "general.notify-server", havingValue = "true")
@@ -45,6 +32,8 @@ public class OrderCancelService {
     private final GiftOrderService              giftOrderService;
     private final GiftOrderService              giftOrderService;
     private final OrderPayService               orderPayService;
     private final OrderPayService               orderPayService;
     private final RedisTemplate<String, Object> redisTemplate;
     private final RedisTemplate<String, Object> redisTemplate;
+    private final AuctionOrderRepo              auctionOrderRepo;
+    private final AuctionOrderService           auctionOrderService;
 
 
     private static int orderCancelInterval = 210;
     private static int orderCancelInterval = 210;
 
 
@@ -136,4 +125,21 @@ public class OrderCancelService {
         }
         }
         return true;
         return true;
     }
     }
+
+    @Scheduled(fixedRate = 30000)
+    public void batchCancelledAuctionOrder() {
+        List<AuctionOrder> orders = auctionOrderRepo
+                .findByStatusAndCreatedAtBeforeAndDelFalse(AuctionOrderStatus.NOT_PAID,
+                        LocalDateTime.now().minusSeconds(orderCancelInterval));
+        orders.parallelStream().forEach(o -> {
+            try {
+                AuctionOrder order = auctionOrderRepo.findById(o.getId()).orElseThrow(new BusinessException("订单不存在"));
+                if (order.getStatus() == AuctionOrderStatus.NOT_PAID) {
+                    auctionOrderService.cancel(order);
+                }
+            } catch (Exception e) {
+                log.error("取消拍卖订单错误 " + o.getId(), e);
+            }
+        });
+    }
 }
 }

+ 82 - 18
src/main/java/com/izouma/nineth/service/OrderPayService.java

@@ -6,6 +6,7 @@ import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.PayQuery;
 import com.izouma.nineth.dto.PayQuery;
 import com.izouma.nineth.dto.UserBankCard;
 import com.izouma.nineth.dto.UserBankCard;
+import com.izouma.nineth.enums.AuctionOrderStatus;
 import com.izouma.nineth.enums.MintOrderStatus;
 import com.izouma.nineth.enums.MintOrderStatus;
 import com.izouma.nineth.enums.OrderStatus;
 import com.izouma.nineth.enums.OrderStatus;
 import com.izouma.nineth.enums.PayMethod;
 import com.izouma.nineth.enums.PayMethod;
@@ -34,24 +35,26 @@ import java.util.stream.Stream;
 public class OrderPayService {
 public class OrderPayService {
     private static String PAY_CHANNEL = Constants.PayChannel.SAND;
     private static String PAY_CHANNEL = Constants.PayChannel.SAND;
 
 
-    private final OrderService       orderService;
-    private final OrderRepo          orderRepo;
-    private final MintOrderRepo      mintOrderRepo;
-    private final GiftOrderRepo      giftOrderRepo;
-    private final SandPayService     sandPayService;
-    private final HMPayService       hmPayService;
-    private final GeneralProperties  generalProperties;
-    private final UserBalanceService userBalanceService;
-    private final RocketMQTemplate   rocketMQTemplate;
-    private final GiftOrderService   giftOrderService;
-    private final MintOrderService   mintOrderService;
-    private final UserRepo           userRepo;
-    private final SnowflakeIdWorker  snowflakeIdWorker;
-    private final RechargeOrderRepo  rechargeOrderRepo;
-    private final SysConfigService   sysConfigService;
-    private final PasswordEncoder    passwordEncoder;
-    private final PayEaseService     payEaseService;
-    private final UserBankCardRepo   userBankCardRepo;
+    private final OrderService        orderService;
+    private final OrderRepo           orderRepo;
+    private final MintOrderRepo       mintOrderRepo;
+    private final GiftOrderRepo       giftOrderRepo;
+    private final SandPayService      sandPayService;
+    private final HMPayService        hmPayService;
+    private final GeneralProperties   generalProperties;
+    private final UserBalanceService  userBalanceService;
+    private final RocketMQTemplate    rocketMQTemplate;
+    private final GiftOrderService    giftOrderService;
+    private final MintOrderService    mintOrderService;
+    private final UserRepo            userRepo;
+    private final SnowflakeIdWorker   snowflakeIdWorker;
+    private final RechargeOrderRepo   rechargeOrderRepo;
+    private final SysConfigService    sysConfigService;
+    private final PasswordEncoder     passwordEncoder;
+    private final PayEaseService      payEaseService;
+    private final UserBankCardRepo    userBankCardRepo;
+    private final AuctionOrderRepo    auctionOrderRepo;
+    private final AuctionOrderService auctionOrderService;
 
 
     public static void setPayChannel(String payChannel) {
     public static void setPayChannel(String payChannel) {
         log.info("set pay channel {}", payChannel);
         log.info("set pay channel {}", payChannel);
@@ -389,4 +392,65 @@ public class OrderPayService {
         }
         }
         return Optional.ofNullable(query).orElse(PayQuery.builder().exist(false).build());
         return Optional.ofNullable(query).orElse(PayQuery.builder().exist(false).build());
     }
     }
+
+    @Cacheable(value = "payOrder", key = "'auctionOrder#'+#orderId")
+    public String payAuctionOrder(Long orderId) {
+        AuctionOrder order = auctionOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
+        if (order.getStatus() != AuctionOrderStatus.NOT_PAID) {
+            throw new BusinessException("订单状态错误");
+        }
+        switch (PAY_CHANNEL) {
+            case Constants.PayChannel.SAND:
+                return sandPayService.pay(orderId + "", "拍卖:" + order.getName(), order.getTotalPrice(),
+                        order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.AUCTION);
+            case Constants.PayChannel.HM:
+                return hmPayService.requestAlipay(orderId + "", order.getTotalPrice(),
+                        "拍卖:" + order.getName(), HMPayService.getTimeout(order.getCreatedAt(), 180),
+                        Constants.OrderNotifyType.AUCTION, generalProperties.getHost() + "/9th/home");
+        }
+        throw new BusinessException("绿洲宇宙冷却系统已启动,请稍后支付");
+    }
+
+    @Cacheable(value = "payOrder", key = "'auctionOrder#'+#orderId")
+    public String payAuctionQuick(Long orderId) {
+        AuctionOrder order = auctionOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
+        if (order.getStatus() != AuctionOrderStatus.NOT_PAID) {
+            throw new BusinessException("订单状态错误");
+        }
+        return sandPayService.payQuick(orderId + "", "拍卖:" + order.getName(),
+                order.getTotalPrice(), order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.AUCTION,
+                generalProperties.getHost() + "/9th/home");
+    }
+
+    public void payAuctionOrderBalance(Long orderId, Long userId, String tradeCode) {
+        AuctionOrder order = auctionOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
+        if (order.getStatus() != AuctionOrderStatus.NOT_PAID) {
+            throw new BusinessException("订单状态错误");
+        }
+        if (!Objects.equals(order.getUserId(), userId)) {
+            throw new BusinessException("订单不属于该用户");
+        }
+        if (!Objects.equals(userRepo.findTradeCode(userId), tradeCode)) {
+            throw new BusinessException("交易码错误");
+        }
+        BalanceRecord record = userBalanceService.balancePay(order.getUserId(), order.getTotalPrice(), orderId, "拍卖");
+        auctionOrderService.notify(orderId, PayMethod.BALANCE, record.getId().toString());
+    }
+
+    @Cacheable(value = "payOrder", key = "'auctionOrder#'+#orderId")
+    public Map<String, Object> payAuctionOrderAgreement(Long orderId, String bindCardId) {
+        AuctionOrder order = auctionOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
+        if (order.getStatus() != AuctionOrderStatus.NOT_PAID) {
+            throw new BusinessException("订单状态错误");
+        }
+        if (StringUtils.isEmpty(bindCardId)) {
+            bindCardId = userBankCardRepo.findByUserId(order.getUserId())
+                    .stream().map(UserBankCard::getBindCardId).findFirst().orElse(null);
+        }
+        if (StringUtils.isEmpty(bindCardId)) {
+            throw new BusinessException("请先绑定银行卡");
+        }
+        return payEaseService.pay("拍卖:" + order.getAuctionId(), orderId.toString(), order.getTotalPrice(),
+                order.getUserId().toString(), bindCardId, Constants.OrderNotifyType.AUCTION);
+    }
 }
 }

+ 1 - 2
src/main/java/com/izouma/nineth/service/OrderService.java

@@ -118,7 +118,7 @@ public class OrderService {
                         SmsService smsService, ErrorOrderRepo errorOrderRepo, ShowCollectionRepo showCollectionRepo,
                         SmsService smsService, ErrorOrderRepo errorOrderRepo, ShowCollectionRepo showCollectionRepo,
                         ShowroomService showroomService, CollectionPrivilegeRepo collectionPrivilegeRepo,
                         ShowroomService showroomService, CollectionPrivilegeRepo collectionPrivilegeRepo,
                         UserBankCardRepo userBankCardRepo, CacheService cacheService, UserPropertyRepo userPropertyRepo,
                         UserBankCardRepo userBankCardRepo, CacheService cacheService, UserPropertyRepo userPropertyRepo,
-                        UserBalanceService userBalanceService, ProxyManager<String> proxyManager) {
+                        UserBalanceService userBalanceService, ProxyManager<String> proxyManager,) {
         this.orderRepo = orderRepo;
         this.orderRepo = orderRepo;
         this.collectionRepo = collectionRepo;
         this.collectionRepo = collectionRepo;
         this.userAddressRepo = userAddressRepo;
         this.userAddressRepo = userAddressRepo;
@@ -716,7 +716,6 @@ public class OrderService {
                             smsService.sellOut(userRepo.findPhoneById(asset.getUserId()));
                             smsService.sellOut(userRepo.findPhoneById(asset.getUserId()));
                         }
                         }
 
 
-                        userBalanceService.realtimeSettleOrder(order);
                     } else {
                     } else {
                         orderRepo.save(order);
                         orderRepo.save(order);
                         //藏品其他信息/是否vip
                         //藏品其他信息/是否vip

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

@@ -9,6 +9,7 @@ import com.izouma.nineth.config.SandPayProperties;
 import com.izouma.nineth.dto.PayQuery;
 import com.izouma.nineth.dto.PayQuery;
 import com.izouma.nineth.enums.PayStatus;
 import com.izouma.nineth.enums.PayStatus;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.AuctionOrderRepo;
 import com.izouma.nineth.repo.GiftOrderRepo;
 import com.izouma.nineth.repo.GiftOrderRepo;
 import com.izouma.nineth.repo.MintOrderRepo;
 import com.izouma.nineth.repo.MintOrderRepo;
 import com.izouma.nineth.repo.OrderRepo;
 import com.izouma.nineth.repo.OrderRepo;
@@ -18,7 +19,6 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.data.redis.core.BoundSetOperations;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
@@ -35,7 +35,6 @@ import java.util.HashMap;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Optional;
-import java.util.concurrent.TimeUnit;
 
 
 @Service
 @Service
 @AllArgsConstructor
 @AllArgsConstructor
@@ -47,6 +46,7 @@ public class SandPayService {
     private final MintOrderRepo                 mintOrderRepo;
     private final MintOrderRepo                 mintOrderRepo;
     private final SnowflakeIdWorker             snowflakeIdWorker;
     private final SnowflakeIdWorker             snowflakeIdWorker;
     private final GeneralProperties             generalProperties;
     private final GeneralProperties             generalProperties;
+    private final AuctionOrderRepo              auctionOrderRepo;
     private final RedisTemplate<String, Object> redisTemplate;
     private final RedisTemplate<String, Object> redisTemplate;
 
 
     public static String paddingOrderId(String orderId) {
     public static String paddingOrderId(String orderId) {

+ 51 - 0
src/main/java/com/izouma/nineth/service/UserService.java

@@ -3,6 +3,7 @@ package com.izouma.nineth.service;
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
+import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.core.sym.NameN;
 import com.fasterxml.jackson.core.sym.NameN;
 import com.huifu.adapay.core.exception.BaseAdaPayException;
 import com.huifu.adapay.core.exception.BaseAdaPayException;
@@ -13,6 +14,8 @@ import com.izouma.nineth.config.RedisKeys;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.*;
 import com.izouma.nineth.dto.*;
+import com.izouma.nineth.dto.oasis.OasisLoginDTO;
+import com.izouma.nineth.enums.AssetStatus;
 import com.izouma.nineth.enums.AuthStatus;
 import com.izouma.nineth.enums.AuthStatus;
 import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.event.AccountCreatedEvent;
 import com.izouma.nineth.event.AccountCreatedEvent;
@@ -50,10 +53,12 @@ import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
+import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Predicate;
@@ -98,6 +103,8 @@ public class UserService {
     private UserBalanceRepo               userBalanceRepo;
     private UserBalanceRepo               userBalanceRepo;
     private ContentAuditService           contentAuditService;
     private ContentAuditService           contentAuditService;
     private OrderRepo                     orderRepo;
     private OrderRepo                     orderRepo;
+    private AuctionPassRecordRepo         auctionPassRecordRepo;
+    private AssetRepo                     assetRepo;
 
 
     public User update(User user) {
     public User update(User user) {
         if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN)) {
         if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN)) {
@@ -911,4 +918,48 @@ public class UserService {
         user.setWalletEnabled(true);
         user.setWalletEnabled(true);
         save(user);
         save(user);
     }
     }
+
+    public Map<String, Object> oasisInfo(Long userId) {
+        Map<String, Object> map = new HashMap<>();
+        User user = userRepo.findById(userId).orElseThrow(new BusinessException("未找到用户信息"));
+        map.put("nickName", user.getNickname());
+        List<Asset> assets = assetRepo.findAllByOwnerIdAndStatusAndOasisIdNotNull(userId, AssetStatus.NORMAL);
+        List<OasisLoginDTO> oasisLoginDTOS = new ArrayList<>();
+        assets.forEach(asset -> {
+            OasisLoginDTO oasisLoginDTO = new OasisLoginDTO();
+            oasisLoginDTO.setOasisId(asset.getOasisId());
+            oasisLoginDTO.setAssetId(asset.getId());
+            oasisLoginDTO.setSource(asset.getStatus().getDescription());
+            Collection collection = collectionRepo.findFirstByOnShelfAndAssetId(true, asset.getId());
+            if (collection != null) {
+                oasisLoginDTO.setUrl(generalProperties.getHost() + "/9th/productDetail/" + collection
+                        .getId() + "?id=" + collection.getId());
+            } else {
+                oasisLoginDTO.setUrl("未公开展示");
+            }
+            oasisLoginDTOS.add(oasisLoginDTO);
+        });
+        map.put("oasisInfo", oasisLoginDTOS);
+        map.put("avatar", SecurityUtils.getAuthenticatedUser().getAvatar());
+        return map;
+    }
+
+    /**
+     * 流拍5次直接删号处罚
+     */
+    @Scheduled(cron = "0 0/10 * * * ?")
+    public void delUser() {
+        List<Long> userIds = auctionPassRecordRepo.checkUserId();
+        if (CollUtil.isNotEmpty(userIds)) {
+            log.info("流拍处罚:{}", userIds);
+            userRepo.softDeleteIn(userIds);
+            //清缓存
+            userIds.forEach(id -> {
+                cacheService.clearUserMy(id);
+                cacheService.clearUser(id);
+            });
+
+        }
+
+    }
 }
 }

+ 77 - 0
src/main/java/com/izouma/nineth/web/AuctionActivityController.java

@@ -0,0 +1,77 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.AuctionActivity;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.auction.AuctionInputDTO;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.AuctionActivityRepo;
+import com.izouma.nineth.repo.NewsLikeRepo;
+import com.izouma.nineth.service.AuctionActivityService;
+import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/auctionActivity")
+@AllArgsConstructor
+public class AuctionActivityController extends BaseController {
+    private AuctionActivityService auctionActivityService;
+    private AuctionActivityRepo    auctionActivityRepo;
+    private NewsLikeRepo           newsLikeRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public AuctionActivity save(@RequestBody AuctionActivity record, @RequestParam(required = false) String code) {
+        if (record.getId() != null) {
+            AuctionActivity orig = auctionActivityRepo.findById(record.getId())
+                    .orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return auctionActivityService.save(orig, code);
+        }
+        return auctionActivityService.save(record, code);
+    }
+
+    @PostMapping("/create")
+    public AuctionActivity createFromAsset(@RequestBody AuctionInputDTO dto) {
+        return auctionActivityService.createFromAsset(dto);
+    }
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<AuctionActivity> all(@RequestBody PageQuery pageQuery) {
+        return auctionActivityService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public AuctionActivity get(@PathVariable Long id) {
+        AuctionActivity auctionActivity = auctionActivityRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+        if (SecurityUtils.getAuthenticatedUser() != null) {
+            if (newsLikeRepo.findByUserIdAndAuctionId(SecurityUtils.getAuthenticatedUser().getId(), id).size() > 0) {
+                auctionActivity.setLiked(true);
+                return auctionActivity;
+            }
+        }
+        auctionActivity.setLiked(false);
+        return auctionActivity;
+    }
+
+//    @PostMapping("/del/{id}")
+//    public void del(@PathVariable Long id) {
+//        auctionActivityRepo.softDelete(id);
+//    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<AuctionActivity> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 124 - 0
src/main/java/com/izouma/nineth/web/AuctionOrderController.java

@@ -0,0 +1,124 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.AuctionOrder;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.AuctionPaymentType;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.AuctionOrderRepo;
+import com.izouma.nineth.service.AuctionOrderService;
+import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/auctionOrder")
+@AllArgsConstructor
+public class AuctionOrderController extends BaseController {
+    private AuctionOrderService auctionOrderService;
+    private AuctionOrderRepo    auctionOrderRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public AuctionOrder save(@RequestBody AuctionOrder record) {
+        if (record.getId() != null) {
+            AuctionOrder orig = auctionOrderRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return auctionOrderRepo.save(orig);
+        }
+        return auctionOrderRepo.save(record);
+
+
+    }
+
+    @PostMapping("/create")
+    @ApiModelProperty(value = "创建拍卖订单(支付)")
+    public AuctionOrder create(Long userId, @RequestParam(required = false) Long auctionId,
+                               Long addressId, Long auctionRecordId, AuctionPaymentType type) {
+        return auctionOrderService.create(userId, auctionId, addressId, auctionRecordId, type);
+    }
+
+    @PostMapping("/createFixPrice")
+    @ApiModelProperty(value = "创建拍卖订单(一口价)")
+    public AuctionOrder createFixPrice(Long userId, @RequestParam(required = false) Long auctionId,
+                                       Long addressId, AuctionPaymentType type) {
+//        AuctionActivity auctionActivity = auctionActivityRepo.findById(auctionId)
+//                .orElseThrow(new BusinessException("暂无"));
+//        AuctionRecord auctionRecord = AuctionRecord.builder()
+//                .auctionId(auctionId)
+//                .type(AuctionRecordType.FIXEDPRICE)
+//                .bidderPrice(auctionActivity.getFixedPrice())
+//                .auctionPic(null)
+//                .userId(SecurityUtils.getAuthenticatedUser().getId())
+//                .avatar(SecurityUtils.getAuthenticatedUser().getAvatar())
+//                .name(auctionActivity.getName())
+//                .purchased(false)
+//                .build();
+//        AuctionRecord record = auctionRecordRepo.save(auctionRecord);
+        return auctionOrderService.create(userId, auctionId, addressId, null, type);
+    }
+
+    @PostMapping("/createDeposit")
+    @ApiModelProperty(value = "创建拍卖订单(保证金)")
+    public AuctionOrder createDeposit(Long userId, @RequestParam(required = false) Long auctionId,
+                                      Long addressId, AuctionPaymentType type) {
+
+//        AuctionActivity auctionActivity = auctionActivityRepo.findById(auctionId)
+//                .orElseThrow(new BusinessException("暂无"));
+//        AuctionRecord auctionRecord = AuctionRecord.builder()
+//                .auctionId(auctionId)
+//                .type(AuctionRecordType.DEPOSIT)
+//                .bidderPrice(auctionActivity.getDeposit())
+//                .auctionPic(null)
+//                .userId(SecurityUtils.getAuthenticatedUser().getId())
+//                .avatar(SecurityUtils.getAuthenticatedUser().getAvatar())
+//                .name(auctionActivity.getName())
+//                .purchased(false)
+//                .build();
+//        AuctionRecord record = auctionRecordRepo.save(auctionRecord);
+        return auctionOrderService.create(userId, auctionId, addressId, null, type);
+    }
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<AuctionOrder> all(@RequestBody PageQuery pageQuery) {
+        return auctionOrderService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public AuctionOrder get(@PathVariable Long id) {
+        return auctionOrderRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        auctionOrderRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<AuctionOrder> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @ApiOperation("订单完成")
+    @GetMapping("/finish/{id}")
+    public void finish(@PathVariable Long id) {
+        auctionOrderService.finish(id);
+    }
+
+    @ApiOperation("订单发货")
+    @GetMapping("/delivery")
+    public void delivery(@RequestParam Long id, @RequestParam String courierId) {
+        auctionOrderService.dispatch(id, courierId);
+    }
+}
+

+ 86 - 0
src/main/java/com/izouma/nineth/web/AuctionRecordController.java

@@ -0,0 +1,86 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.AuctionRecord;
+import com.izouma.nineth.dto.auction.AuctionRecordDTO;
+import com.izouma.nineth.service.AuctionRecordService;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.AuctionRecordRepo;
+import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.List;
+
+@RestController
+@RequestMapping("/auctionRecord")
+@AllArgsConstructor
+public class AuctionRecordController extends BaseController {
+    private AuctionRecordService auctionRecordService;
+    private AuctionRecordRepo    auctionRecordRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public AuctionRecord save(@RequestBody AuctionRecord record) {
+        if (record.getId() != null) {
+            AuctionRecord orig = auctionRecordRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return auctionRecordRepo.save(orig);
+        }
+        return auctionRecordRepo.save(record);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<AuctionRecord> all(@RequestBody PageQuery pageQuery) {
+        return auctionRecordService.all(pageQuery);
+    }
+
+    @PostMapping("/recordInfos")
+    public Page<AuctionRecordDTO> recordInfos(@RequestBody PageQuery pageQuery) {
+        return auctionRecordService.recordInfos(pageQuery);
+    }
+
+    @PostMapping("/userRecord")
+    public List<AuctionRecordDTO> userRecord(@RequestParam String type) {
+        return auctionRecordService.userRecord(SecurityUtils.getAuthenticatedUser().getId(), type);
+    }
+
+
+    @GetMapping("/get/{id}")
+    public AuctionRecord get(@PathVariable Long id) {
+        return auctionRecordRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        auctionRecordRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<AuctionRecord> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @GetMapping("/hasPayDeposit")
+    public AuctionRecord hasPayDeposit(Long auctionId) {
+        return auctionRecordRepo
+                .findTopByAuctionIdAndUserIdOrderByIdDesc(auctionId, SecurityUtils.getAuthenticatedUser()
+                        .getId());
+    }
+
+    @PostMapping("/create")
+    public AuctionRecord created(Long auctionId, BigDecimal amount) {
+        return auctionRecordService.create(SecurityUtils.getAuthenticatedUser().getId(), auctionId, amount);
+    }
+}
+

+ 18 - 0
src/main/java/com/izouma/nineth/web/AuthenticationController.java

@@ -35,6 +35,24 @@ public class AuthenticationController {
         return jwtTokenUtil.generateToken(JwtUserFactory.create(user));
         return jwtTokenUtil.generateToken(JwtUserFactory.create(user));
     }
     }
 
 
+    @PostMapping("/oasisLogin")
+    public Map<String, Object> oasisLogin(String phone, String password, Integer expiration) {
+        User user = userService.loginByPhonePwd(phone, password);
+        Map<String, Object> result = userService.oasisInfo(user.getId());
+        result.put("token", jwtTokenUtil.generateToken(JwtUserFactory.create(user)));
+        result.put("userId", user.getId());
+        return result;
+    }
+
+    @PostMapping("/oasisLoginPhone")
+    public Map<String, Object> oasisLogin(String phone, String code) {
+        User user = userService.loginByPhone(phone, code);
+        Map<String, Object> result = userService.oasisInfo(user.getId());
+        result.put("token", jwtTokenUtil.generateToken(JwtUserFactory.create(user)));
+        result.put("userId", user.getId());
+        return result;
+    }
+
     @PostMapping("/loginAdmin")
     @PostMapping("/loginAdmin")
     public String loginByUserPwdAdmin(String username, String password, Integer expiration) {
     public String loginByUserPwdAdmin(String username, String password, Integer expiration) {
         User user = userService.loginByUsernamePwd(username, password);
         User user = userService.loginByUsernamePwd(username, password);

+ 12 - 0
src/main/java/com/izouma/nineth/web/CollectionController.java

@@ -214,5 +214,17 @@ public class CollectionController extends BaseController {
         collection.setSalable(salable);
         collection.setSalable(salable);
         collectionRepo.save(collection);
         collectionRepo.save(collection);
     }
     }
+
+    @PreAuthorize("hasAnyRole('ADMIN','COMPANY')")
+    @PostMapping("/onShelfOasis")
+    public List<Collection> onShelfOasis(@RequestBody List<Long> oasisIds) {
+        return collectionService.setOasisOnShelf(oasisIds);
+    }
+
+    @PreAuthorize("hasAnyRole('ADMIN','COMPANY')")
+    @PostMapping("/setScancodeOasis")
+    public List<Collection> setScancodeOasis(@RequestBody List<Long> oasisIds) {
+        return collectionService.setOasisScancode(oasisIds);
+    }
 }
 }
 
 

+ 63 - 4
src/main/java/com/izouma/nineth/web/CompanyCollectionController.java

@@ -1,6 +1,8 @@
 package com.izouma.nineth.web;
 package com.izouma.nineth.web;
 
 
 import com.izouma.nineth.domain.CompanyCollection;
 import com.izouma.nineth.domain.CompanyCollection;
+import com.izouma.nineth.dto.oasis.OasisDistrictCollectionDTO;
+import com.izouma.nineth.dto.oasis.OasisDistrictDTO;
 import com.izouma.nineth.enums.CollectionStatus;
 import com.izouma.nineth.enums.CollectionStatus;
 import com.izouma.nineth.service.CompanyCollectionService;
 import com.izouma.nineth.service.CompanyCollectionService;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.PageQuery;
@@ -10,12 +12,14 @@ import com.izouma.nineth.utils.ObjUtils;
 import com.izouma.nineth.utils.SecurityUtils;
 import com.izouma.nineth.utils.SecurityUtils;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
+import org.springframework.beans.BeanUtils;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 
 
 @RestController
 @RestController
@@ -42,6 +46,65 @@ public class CompanyCollectionController extends BaseController {
         return companyCollectionRepo.save(record);
         return companyCollectionRepo.save(record);
     }
     }
 
 
+    //oasis创建保存地块接口
+    @PreAuthorize("hasAnyRole('ADMIN','COMPANY')")
+    @PostMapping("/saveDistrict")
+    public CompanyCollection saveDistrict(@RequestBody OasisDistrictDTO oasisDistrictDTO) {
+        CompanyCollection record = new CompanyCollection();
+        BeanUtils.copyProperties(oasisDistrictDTO, record);
+        record.setStatus(CollectionStatus.PENDING);
+        record.setCategory("地块");
+        record.setUserId(7958191L);
+        record.setMinter("oasis地块测试");
+        if (record.getId() != null) {
+            CompanyCollection orig = companyCollectionRepo.findById(record.getId())
+                    .orElseThrow(new BusinessException("无记录"));
+            if (CollectionStatus.SUCCESS.equals(orig.getStatus())) {
+                throw new BusinessException("已通过申请,不可编辑");
+            }
+
+            ObjUtils.merge(orig, record);
+            return companyCollectionRepo.save(orig);
+        }
+        record.setUserId(SecurityUtils.getAuthenticatedUser().getId());
+        return companyCollectionRepo.save(record);
+    }
+
+    //oasis创建保存地块接口
+    @PreAuthorize("hasAnyRole('ADMIN','COMPANY')")
+    @PostMapping("/multiDistrict")
+    public List<CompanyCollection> multiDistrict(@RequestBody List<OasisDistrictDTO> oasisDistrictDTOs) {
+        List<CompanyCollection> companyCollections = new ArrayList<>();
+        oasisDistrictDTOs.forEach(oasisDistrictDTO -> {
+            CompanyCollection record = new CompanyCollection();
+            BeanUtils.copyProperties(oasisDistrictDTO, record);
+            record.setStatus(CollectionStatus.PENDING);
+            record.setCategory("地块");
+            record.setUserId(7958191L);
+            record.setMinter("oasis地块测试");
+            if (record.getId() != null) {
+                CompanyCollection orig = companyCollectionRepo.findById(record.getId())
+                        .orElseThrow(new BusinessException("无记录"));
+                if (CollectionStatus.SUCCESS.equals(orig.getStatus())) {
+                    throw new BusinessException("已通过申请,不可编辑");
+                }
+
+                ObjUtils.merge(orig, record);
+                companyCollections.add(orig);
+            }
+            record.setUserId(SecurityUtils.getAuthenticatedUser().getId());
+            companyCollections.add(record);
+        });
+        return companyCollectionRepo.saveAll(companyCollections);
+    }
+
+    //oasis创建地块接口
+    @PreAuthorize("hasAnyRole('ADMIN','COMPANY')")
+    @PostMapping("/oasisSearch")
+    public List<OasisDistrictCollectionDTO> oasisSearch(@RequestBody List<Long> oasisIds) {
+        return companyCollectionService.oasisSearch(oasisIds);
+    }
+
 
 
     //@PreAuthorize("hasRole('ADMIN')")
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     @PostMapping("/all")
@@ -76,9 +139,5 @@ public class CompanyCollectionController extends BaseController {
         companyCollectionService.audit(id, CollectionStatus.FAIL, reason);
         companyCollectionService.audit(id, CollectionStatus.FAIL, reason);
     }
     }
 
 
-//    @PostMapping("/createDistrict")
-//    public void deny(@RequestParam Long id, String reason) {
-//        companyCollectionService.audit(id, CollectionStatus.FAIL, reason);
-//    }
 }
 }
 
 

+ 5 - 0
src/main/java/com/izouma/nineth/web/HmPayController.java

@@ -68,6 +68,11 @@ public class HmPayController extends BaseController {
                             new OrderNotifyEvent(id, PayMethod.SANDPAY, plat_trx_no,
                             new OrderNotifyEvent(id, PayMethod.SANDPAY, plat_trx_no,
                                     System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
                                     System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
                     break;
                     break;
+                case "auctionOrder":
+                    rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
+                            new OrderNotifyEvent(id, PayMethod.SANDPAY, plat_trx_no,
+                                    System.currentTimeMillis(), OrderNotifyEvent.TYPE_MINT_ORDER));
+                    break;
             }
             }
         }
         }
         return "SUCCESS";
         return "SUCCESS";

+ 14 - 1
src/main/java/com/izouma/nineth/web/NewsLikeController.java

@@ -1,4 +1,5 @@
 package com.izouma.nineth.web;
 package com.izouma.nineth.web;
+
 import com.izouma.nineth.domain.NewsLike;
 import com.izouma.nineth.domain.NewsLike;
 import com.izouma.nineth.service.NewsLikeService;
 import com.izouma.nineth.service.NewsLikeService;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.PageQuery;
@@ -23,7 +24,7 @@ import java.util.List;
 @AllArgsConstructor
 @AllArgsConstructor
 public class NewsLikeController extends BaseController {
 public class NewsLikeController extends BaseController {
     private NewsLikeService newsLikeService;
     private NewsLikeService newsLikeService;
-    private NewsLikeRepo newsLikeRepo;
+    private NewsLikeRepo    newsLikeRepo;
 
 
     //@PreAuthorize("hasRole('ADMIN')")
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
     @PostMapping("/save")
@@ -85,5 +86,17 @@ public class NewsLikeController extends BaseController {
     public void unlikeRoom(@PathVariable Long id) {
     public void unlikeRoom(@PathVariable Long id) {
         newsLikeService.unlikeRoom(SecurityUtils.getAuthenticatedUser().getId(), id);
         newsLikeService.unlikeRoom(SecurityUtils.getAuthenticatedUser().getId(), id);
     }
     }
+
+    @GetMapping("/{id}/likeAuction")
+    @ApiOperation("点赞拍卖")
+    public void likeAuction(@PathVariable Long id) {
+        newsLikeService.likeAuction(SecurityUtils.getAuthenticatedUser().getId(), id);
+    }
+
+    @GetMapping("/{id}/unlikeAuction")
+    @ApiOperation("取消点赞拍卖")
+    public void unlikeAuction(@PathVariable Long id) {
+        newsLikeService.unlikeAuction(SecurityUtils.getAuthenticatedUser().getId(), id);
+    }
 }
 }
 
 

+ 6 - 4
src/main/java/com/izouma/nineth/web/OrderPayController.java

@@ -30,7 +30,6 @@ import java.util.regex.Pattern;
 @AllArgsConstructor
 @AllArgsConstructor
 public class OrderPayController {
 public class OrderPayController {
     private final OrderService     orderService;
     private final OrderService     orderService;
-    private final AssetService     assetService;
     private final WxMpService      wxMpService;
     private final WxMpService      wxMpService;
     private final GiftOrderService giftOrderService;
     private final GiftOrderService giftOrderService;
     private final OrderRepo        orderRepo;
     private final OrderRepo        orderRepo;
@@ -96,7 +95,8 @@ public class OrderPayController {
     public String payOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
     public String payOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
         WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
         WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
         WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
         WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
-        WxPayMpOrderResult payParams = (WxPayMpOrderResult) orderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
+        WxPayMpOrderResult payParams = (WxPayMpOrderResult) orderService
+                .payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
         model.addAttribute("payParams", JSON.toJSONString(payParams));
         model.addAttribute("payParams", JSON.toJSONString(payParams));
         return "PayOrderPC";
         return "PayOrderPC";
     }
     }
@@ -162,7 +162,8 @@ public class OrderPayController {
     public String payGiftOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
     public String payGiftOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
         WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
         WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
         WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
         WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
-        WxPayMpOrderResult payParams = (WxPayMpOrderResult) giftOrderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
+        WxPayMpOrderResult payParams = (WxPayMpOrderResult) giftOrderService
+                .payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
         model.addAttribute("payParams", JSON.toJSONString(payParams));
         model.addAttribute("payParams", JSON.toJSONString(payParams));
         return "PayOrderPC";
         return "PayOrderPC";
     }
     }
@@ -213,7 +214,8 @@ public class OrderPayController {
     public String payMintOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
     public String payMintOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
         WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
         WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
         WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
         WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
-        WxPayMpOrderResult payParams = (WxPayMpOrderResult) mintOrderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
+        WxPayMpOrderResult payParams = (WxPayMpOrderResult) mintOrderService
+                .payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
         model.addAttribute("payParams", JSON.toJSONString(payParams));
         model.addAttribute("payParams", JSON.toJSONString(payParams));
         return "PayOrderPC";
         return "PayOrderPC";
     }
     }

+ 31 - 0
src/main/java/com/izouma/nineth/web/OrderPayControllerV2.java

@@ -164,4 +164,35 @@ public class OrderPayControllerV2 {
     public String payRechargeQuick(@RequestParam Long userId, @RequestParam BigDecimal amount) {
     public String payRechargeQuick(@RequestParam Long userId, @RequestParam BigDecimal amount) {
         return orderPayService.rechargeQuick(userId, amount);
         return orderPayService.rechargeQuick(userId, amount);
     }
     }
+
+    @RequestMapping(value = "/auction/alipay", method = RequestMethod.GET)
+    @ResponseBody
+    public String payAuctionOrderAlipayH5(Long id) {
+        return orderPayService.payAuctionOrder(id);
+    }
+
+    @RequestMapping(value = "/auction/alipay_wx", method = RequestMethod.GET)
+    public String payAuctionOrderAlipayWx(Long id, Model model) {
+        String payUrl = orderPayService.payAuctionOrder(id);
+        model.addAttribute("payUrl", payUrl);
+        model.addAttribute("orderId", id);
+        return "AlipayHtml";
+    }
+
+    @RequestMapping(value = "/auction/sandQuick", method = RequestMethod.GET, produces = "text/html")
+    @ResponseBody
+    public String payAuctionQuick(@RequestParam Long id) {
+        return orderPayService.payAuctionQuick(id);
+    }
+
+    @RequestMapping(value = "auction/balance", method = RequestMethod.GET)
+    public void payAuctionOrderBalance(@RequestParam Long id, @RequestParam String tradeCode) {
+        orderPayService.payAuctionOrderBalance(id, SecurityUtils.getAuthenticatedUser().getId(), tradeCode);
+    }
+
+    @RequestMapping(value = "/auction/agreement")
+    @ResponseBody
+    public Map<String, Object> payAuctionAgreement(@RequestParam Long id, String bindCardId) {
+        return orderPayService.payAuctionOrderAgreement(id, bindCardId);
+    }
 }
 }

+ 10 - 0
src/main/java/com/izouma/nineth/web/PayEaseController.java

@@ -5,6 +5,11 @@ import com.alibaba.fastjson15.JSONObject;
 import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.enums.PayMethod;
 import com.izouma.nineth.enums.PayMethod;
 import com.izouma.nineth.event.OrderNotifyEvent;
 import com.izouma.nineth.event.OrderNotifyEvent;
+import com.izouma.nineth.service.AuctionOrderService;
+import com.izouma.nineth.service.AuctionOrderService;
+import com.izouma.nineth.service.GiftOrderService;
+import com.izouma.nineth.service.MintOrderService;
+import com.izouma.nineth.service.UserBalanceService;
 import com.upay.sdk.CipherWrapper;
 import com.upay.sdk.CipherWrapper;
 import com.upay.sdk.onlinepay.executer.OnlinePayOrderExecuter;
 import com.upay.sdk.onlinepay.executer.OnlinePayOrderExecuter;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
@@ -53,6 +58,11 @@ public class PayEaseController {
                             new OrderNotifyEvent(id, PayMethod.SANDPAY, serialNumber,
                             new OrderNotifyEvent(id, PayMethod.SANDPAY, serialNumber,
                                     System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
                                     System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
                     break;
                     break;
+                case "auctionOrder":
+                    rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
+                            new OrderNotifyEvent(id, PayMethod.SANDPAY, serialNumber,
+                                    System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
+                    break;
             }
             }
         }
         }
         return "SUCCESS";
         return "SUCCESS";

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

@@ -75,6 +75,11 @@ public class SandPayController {
                                         new OrderNotifyEvent(id, PayMethod.SANDPAY, payOrderCode,
                                         new OrderNotifyEvent(id, PayMethod.SANDPAY, payOrderCode,
                                                 System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
                                                 System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
                                 break;
                                 break;
+                            case "auctionOrder":
+                                rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
+                                        new OrderNotifyEvent(id, PayMethod.SANDPAY, payOrderCode,
+                                                System.currentTimeMillis(), OrderNotifyEvent.TYPE_RECHARGE));
+                                break;
                         }
                         }
                     }
                     }
                     return "respCode=000000";
                     return "respCode=000000";

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

@@ -22,11 +22,11 @@ public class SmsController {
 
 
     @GetMapping("/sendVerify")
     @GetMapping("/sendVerify")
     public String sendVerify(@RequestParam String phone) {
     public String sendVerify(@RequestParam String phone) {
-        throw new BusinessException("此接口已停用,请重启APP或刷新网页");
-//        if (!Pattern.matches(Constants.Regex.PHONE, phone)) {
-//            throw new BusinessException("请输入正确的手机号");
-//        }
-//        return smsService.sendVerify(phone);
+//        throw new BusinessException("此接口已停用,请重启APP或刷新网页");
+        if (!Pattern.matches(Constants.Regex.PHONE, phone)) {
+            throw new BusinessException("请输入正确的手机号");
+        }
+        return smsService.sendVerify(phone);
     }
     }
 
 
     @GetMapping("/sendSecureVerify")
     @GetMapping("/sendSecureVerify")

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/main/resources/genjson/AuctionOrder.json


+ 69 - 0
src/main/vue/src/router.js

@@ -708,6 +708,75 @@ const router = new Router({
                         title: 'captcha'
                         title: 'captcha'
                     }
                     }
                 },
                 },
+                {
+                    path: '/auctionOrderEdit',
+                    name: 'AuctionOrderEdit',
+                    component: () => import(/* webpackChunkName: "auctionOrderEdit" */ '@/views/AuctionOrderEdit.vue'),
+                    meta: {
+                        title: '拍卖订单编辑'
+                    }
+                },
+                {
+                    path: '/auctionOrderList',
+                    name: 'AuctionOrderList',
+                    component: () => import(/* webpackChunkName: "auctionOrderList" */ '@/views/AuctionOrderList.vue'),
+                    meta: {
+                        title: '拍卖订单'
+                    }
+                },
+                {
+                    path: '/auctionOrderUsedList',
+                    name: 'AuctionOrderUsedList',
+                    component: () => import(/* webpackChunkName: "auctionOrderList" */ '@/views/AuctionOrderUsedList.vue'),
+                    meta: {
+                        title: '拍卖订单'
+                    }
+                },
+                {
+                    path: '/auctionActivityEdit',
+                    name: 'AuctionActivityEdit',
+                    component: () =>
+                        import(/* webpackChunkName: "auctionActivityEdit" */ '@/views/AuctionActivityEdit.vue'),
+                    meta: {
+                        title: '拍卖编辑'
+                    }
+                },
+                {
+                    path: '/auctionActivityList',
+                    name: 'AuctionActivityList',
+                    component: () =>
+                        import(/* webpackChunkName: "auctionActivityList" */ '@/views/AuctionActivityList.vue'),
+                    meta: {
+                        title: '拍卖'
+                    }
+                },
+                {
+                    path: '/auctionUsedList',
+                    name: 'AuctionUsedList',
+                    component: () =>
+                        import(/* webpackChunkName: "auctionUsedList" */ '@/views/AuctionUsedList.vue'),
+                    meta: {
+                        title: '拍卖'
+                    }
+                },
+                {
+                    path: '/auctionRecordEdit',
+                    name: 'AuctionRecordEdit',
+                    component: () =>
+                        import(/* webpackChunkName: "auctionRecordEdit" */ '@/views/AuctionRecordEdit.vue'),
+                    meta: {
+                        title: '拍卖纪录编辑'
+                    }
+                },
+                {
+                    path: '/auctionRecordList',
+                    name: 'AuctionRecordList',
+                    component: () =>
+                        import(/* webpackChunkName: "auctionRecordList" */ '@/views/AuctionRecordList.vue'),
+                    meta: {
+                        title: '拍卖纪录'
+                    }
+                },
                 {
                 {
                     path: '/tagEdit',
                     path: '/tagEdit',
                     name: 'TagEdit',
                     name: 'TagEdit',

+ 410 - 0
src/main/vue/src/views/AuctionActivityEdit.vue

@@ -0,0 +1,410 @@
+<template>
+    <div class="edit-view">
+        <page-title>
+            <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+            <!-- <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id"> 删除 </el-button> -->
+            <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
+        </page-title>
+        <div class="edit-view__content-wrapper">
+            <div class="edit-view__content-section">
+                <el-form
+                    :model="formData"
+                    :rules="rules"
+                    ref="form"
+                    label-width="110px"
+                    label-position="right"
+                    size="small"
+                    style="max-width: 750px"
+                >
+                    <el-form-item prop="name" label="拍卖名称">
+                        <el-input v-model="formData.name" style="width: 500px" :disabled="!canEdit"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="pic" label="图片">
+                        <object-upload
+                            v-model="formData.pic[0]"
+                            compress
+                            width="3000"
+                            height="3000"
+                            :disabled="!canEdit"
+                        ></object-upload>
+                        <div class="tip">支持JPG、PNG、GIF、MP4,推荐长宽比1:1</div>
+                    </el-form-item>
+                    <el-form-item prop="model3d" label="3D模型">
+                        <model-upload
+                            :limit="1"
+                            v-model="formData.model3d"
+                            :customUrl="customUrl"
+                            accept="application/zip"
+                            format="json"
+                            single
+                        ></model-upload>
+                        <div class="tip">请将FBX文件与贴图打包成zip压缩包上传</div>
+                    </el-form-item>
+                    <el-form-item label="相机距离" v-if="formData.model3d">
+                        <el-input-number v-model="scale" :min="0.1" :step="0.1"></el-input-number>
+                    </el-form-item>
+                    <el-form-item label="Y轴偏移" v-if="formData.model3d">
+                        <el-input-number v-model="yOffset"></el-input-number>
+                    </el-form-item>
+                    <div class="inline-wrapper">
+                        <el-form-item prop="sellerId" label="起拍者">
+                            <minter-select
+                                v-model="formData.sellerId"
+                                @detail="onMinterDetail"
+                                :disabled="!canEdit"
+                            ></minter-select>
+                        </el-form-item>
+                        <el-form-item prop="category" label="分类">
+                            <el-select v-model="formData.category" :disabled="!canEdit">
+                                <el-option
+                                    v-for="item in cateogories"
+                                    :label="item"
+                                    :value="item"
+                                    :key="item"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+                    </div>
+
+                    <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="auctionType" label="拍卖类型">
+                        <el-select
+                            v-model="formData.auctionType"
+                            clearable
+                            filterable
+                            placeholder="请选择"
+                            :disabled="!canEdit"
+                        >
+                            <el-option
+                                v-for="item in auctionTypeOptions"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            >
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <div class="inline-wrapper">
+                        <el-form-item prop="startingPrice" label="起拍价">
+                            <el-input-number
+                                type="number"
+                                v-model="formData.startingPrice"
+                                :disabled="!canEdit"
+                            ></el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="increment" label="加价幅度">
+                            <el-input-number
+                                type="number"
+                                v-model="formData.increment"
+                                :disabled="!canEdit"
+                            ></el-input-number>
+                        </el-form-item>
+                    </div>
+                    <div class="inline-wrapper">
+                        <el-form-item prop="deposit" label="保证金">
+                            <el-input-number
+                                type="number"
+                                v-model="formData.deposit"
+                                :disabled="!canEdit"
+                            ></el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="fixedPrice" label="一口价">
+                            <el-input-number
+                                type="number"
+                                v-model="formData.fixedPrice"
+                                :disabled="!canEdit"
+                            ></el-input-number>
+                        </el-form-item>
+                    </div>
+                    <div class="inline-wrapper">
+                        <el-form-item prop="royalties" label="版税(%)">
+                            <el-input-number v-model="formData.royalties" :min="0" :max="99" :disabled="!canEdit">
+                            </el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="serviceCharge" label="手续费(%)">
+                            <el-input-number v-model="formData.serviceCharge" :min="0" :max="99" :disabled="!canEdit">
+                            </el-input-number>
+                        </el-form-item>
+                    </div>
+                    <el-form-item prop="startTime" label="开始时间">
+                        <el-date-picker
+                            v-model="formData.startTime"
+                            type="datetime"
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            placeholder="选择日期时间"
+                        >
+                        </el-date-picker>
+                    </el-form-item>
+                    <el-form-item prop="endTime" label="截止时间">
+                        <el-date-picker
+                            v-model="formData.endTime"
+                            type="datetime"
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            placeholder="选择日期时间"
+                        >
+                        </el-date-picker>
+                    </el-form-item>
+
+                    <!-- <el-form-item prop="purchasePrice" label="出价">
+                        <el-input-number type="number" v-model="formData.purchasePrice"></el-input-number>
+                    </el-form-item> -->
+                    <!-- <el-form-item prop="purchaserId" label="买家id">
+                        <el-input-number type="number" v-model="formData.purchaserId"></el-input-number>
+                    </el-form-item>
+                    <el-form-item prop="purchaser" label="买家">
+                        <el-input v-model="formData.purchaser"></el-input>
+                    </el-form-item> -->
+                    <!-- <el-form-item prop="status" label="状态">
+                        <el-select v-model="formData.status" clearable filterable placeholder="请选择">
+                            <el-option
+                                v-for="item in statusOptions"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            >
+                            </el-option>
+                        </el-select>
+                    </el-form-item> -->
+                    <!-- <el-form-item prop="source" label="状态">
+                        <el-select v-model="formData.source" clearable filterable placeholder="请选择">
+                            <el-option
+                                v-for="item in sourceOptions"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            >
+                            </el-option>
+                        </el-select>
+                    </el-form-item> -->
+                    <el-form-item class="form-submit">
+                        <el-button @click="onSave" :loading="saving" type="primary"> 保存 </el-button>
+                        <!-- <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
+                            删除
+                        </el-button> -->
+                        <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+                    </el-form-item>
+                </el-form>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import resolveUrl from 'resolve-url';
+import ModelUpload from '../components/ModelUpload.vue';
+import { format, parse, isBefore } from 'date-fns';
+export default {
+    name: 'AuctionActivityEdit',
+    components: { ModelUpload },
+    created() {
+        if (this.$route.query.id) {
+            this.$http
+                .get('auctionActivity/get/' + this.$route.query.id)
+                .then(res => {
+                    this.formData = res;
+                    this.canEdit = res.source !== 'TRANSFER';
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        }
+    },
+    data() {
+        return {
+            saving: false,
+            formData: {
+                pic: [],
+                source: 'OFFICIAL'
+            },
+            rules: {
+                name: [
+                    {
+                        required: true,
+                        message: '请输入名称',
+                        trigger: 'blur'
+                    }
+                ],
+                pic: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (value) {
+                                if (!(value instanceof Array)) {
+                                    callback(new Error('请上传内容'));
+                                    return;
+                                } else {
+                                    for (let f of value) {
+                                        if (!f.url) {
+                                            callback(new Error('请上传内容'));
+                                            return;
+                                        }
+                                    }
+                                }
+                                callback();
+                            } else {
+                                callback(new Error('请上传内容'));
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                seller: [
+                    {
+                        required: true,
+                        message: '请输入铸造者',
+                        trigger: 'blur'
+                    }
+                ],
+                sellerId: [
+                    {
+                        required: true,
+                        message: '请输入铸造者ID',
+                        trigger: 'blur'
+                    }
+                ],
+                detail: [
+                    {
+                        required: true,
+                        message: '请输入详情',
+                        trigger: 'blur'
+                    }
+                ],
+                increment: [{ required: true, message: '请输入加价幅度' }],
+                royalties: [{ required: true, message: '请填写版税' }],
+                serviceCharge: [{ required: true, message: '请填手续费' }],
+                auctionType: [{ required: true, message: '请选择拍卖类型' }],
+                startTime: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (!value) {
+                                callback(new Error('请填写发布时间'));
+                                // } else if (isBefore(parse(value, 'yyyy-MM-dd HH:mm:ss', new Date()), new Date())) {
+                                //     callback(new Error('发布时间不能小于当前时间'));
+                            } else {
+                                callback();
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                endTime: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (!value) {
+                                callback(new Error('请填写结束时间'));
+                            } else if (isBefore(parse(value, 'yyyy-MM-dd HH:mm:ss', new Date()), new Date())) {
+                                callback(new Error('结束时间不能小于当前时间'));
+                            } else if (this.formData.scheduleSale) {
+                                if (
+                                    isBefore(
+                                        parse(value, 'yyyy-MM-dd HH:mm:ss', new Date()),
+                                        parse(this.formData.startTime, 'yyyy-MM-dd HH:mm:ss', new Date())
+                                    )
+                                ) {
+                                    callback(new Error('结束时间不能小于发布时间'));
+                                }
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ]
+            },
+            auctionTypeOptions: [
+                { label: '虚拟藏品', value: 'NFT' },
+                { label: '实物', value: 'ENTITY' }
+            ],
+            statusOptions: [
+                { label: '未开始', value: 'NOTSTARTED' },
+                { label: '进行中', value: 'ONGOING' },
+                { label: '成交', value: 'PURCHASED' },
+                { label: '一口价成交', value: 'FIXED_PRICE_PURCHASED' },
+                { label: '流拍', value: 'PASS' },
+                { label: '完成', value: 'FINISH' }
+            ],
+            sourceOptions: [
+                { label: '官方拍卖', value: 'OFFICIAL' },
+                { label: '转让拍卖', value: 'TRANSFER' }
+            ],
+            cateogories: ['勋章', '收藏品', '数字艺术', '门票', '游戏', '音乐', '使用', '其他'],
+            customUrl: resolveUrl(this.$baseUrl, 'upload/3dModel'),
+            canEdit: true
+        };
+    },
+    // computed: {
+    //     canEdit() {
+    //         // return !!!this.$route.query.id;
+    //         return this.formData.source === 'TRANSFER';
+    //     }
+    // },
+    methods: {
+        onSave() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.submit();
+                } else {
+                    return false;
+                }
+            });
+        },
+        submit() {
+            let data = { ...this.formData };
+            if (data.model3d) {
+                data.model3d.url = data.model3d.url + '?scale=' + this.scale + '&yOffset=' + this.yOffset;
+            }
+
+            this.saving = true;
+
+            this.$http
+                .post('/auctionActivity/save', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    this.$message.success('成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        },
+        onDelete() {
+            this.$confirm('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/auctionActivity/del/${this.formData.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        console.log(e);
+                        this.$message.error((e || {}).error || '删除失败');
+                    }
+                });
+        },
+        onMinterDetail(e) {
+            console.log(e);
+            this.$set(this.formData, 'minter', e.nickname);
+            this.$set(this.formData, 'minterAvatar', e.avatar);
+
+            this.$set(this.formData, 'sellerId', e.id);
+            this.$set(this.formData, 'seller', e.nickname);
+            this.$set(this.formData, 'sellerAvatar', e.avatar);
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.tip {
+    font-size: 12px;
+    color: @text3;
+    margin-top: 5px;
+}
+.inline-wrapper {
+    .el-form-item {
+        display: inline-block;
+    }
+}
+</style>

+ 259 - 0
src/main/vue/src/views/AuctionActivityList.vue

@@ -0,0 +1,259 @@
+<template>
+    <div class="list-view">
+        <page-title>
+            <el-button
+                @click="addRow"
+                type="primary"
+                icon="el-icon-plus"
+                :disabled="fetchingData || downloading"
+                class="filter-item"
+            >
+                新增
+            </el-button>
+            <!-- <el-button
+                @click="download"
+                icon="el-icon-upload2"
+                :loading="downloading"
+                :disabled="fetchingData"
+                class="filter-item"
+            >
+                导出
+            </el-button> -->
+        </page-title>
+        <div class="filters-container">
+            <el-input
+                placeholder="搜索拍卖名称..."
+                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>
+            <created-at-picker
+                v-model="endTime"
+                @input="getData"
+                name="拍卖结束"
+                class="filter-item"
+            ></created-at-picker>
+            <el-select v-model="status" clearable class="filter-item" placeholder="请选择状态" @change="getData">
+                <el-option
+                    v-for="item in statusOptions"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                ></el-option>
+            </el-select>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+            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="90"> </el-table-column>
+            <el-table-column prop="sellerId" label="起拍人ID"> </el-table-column>
+            <el-table-column prop="seller" label="起拍人昵称"> </el-table-column>
+            <!-- <el-table-column prop="sellerAvatar" label="起拍人头像"> </el-table-column> -->
+            <el-table-column prop="name" label="拍卖名称"> </el-table-column>
+            <el-table-column prop="auctionType" label="拍卖类型" :formatter="auctionTypeFormatter"> </el-table-column>
+            <!-- <el-table-column prop="minter" label="铸造者"> </el-table-column> -->
+            <el-table-column prop="pic" label="作品内容" width="90" align="center">
+                <template slot-scope="{ row }">
+                    <el-image
+                        style="width: 30px; height: 30px"
+                        :src="row.pic[0].thumb || row.pic[0].url"
+                        fit="cover"
+                        :preview-src-list="row.pic.map(i => i.thumb || i.url)"
+                    ></el-image>
+                </template>
+            </el-table-column>
+            <!-- <el-table-column prop="detail" label="详情"> </el-table-column> -->
+            <!-- <el-table-column prop="category" label="分类"> </el-table-column> -->
+            <el-table-column prop="startingPrice" label="起拍价"> </el-table-column>
+            <el-table-column prop="deposit" label="保证金"> </el-table-column>
+            <el-table-column prop="fixedPrice" label="一口价"> </el-table-column>
+            <el-table-column prop="startTime" label="开始时间"> </el-table-column>
+            <el-table-column prop="increment" label="加价幅度"> </el-table-column>
+            <el-table-column prop="endTime" label="截止时间"> </el-table-column>
+            <el-table-column prop="purchasePrice" label="成交价"> </el-table-column>
+            <el-table-column prop="purchaserId" label="买家id"> </el-table-column>
+            <el-table-column prop="purchaser" label="买家"> </el-table-column>
+            <el-table-column prop="status" label="状态" :formatter="statusFormatter"> </el-table-column>
+            <el-table-column prop="source" label="来源" :formatter="sourceFormatter"> </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="150">
+                <template slot-scope="{ row }">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
+                    <!-- <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button> -->
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+    name: 'AuctionActivityList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/auctionActivity/all',
+            downloading: false,
+            auctionTypeOptions: [
+                { label: '虚拟藏品', value: 'NFT' },
+                { label: '实物', value: 'ENTITY' }
+            ],
+            statusOptions: [
+                { label: '未开始', value: 'NOTSTARTED' },
+                { label: '进行中', value: 'ONGOING' },
+                { label: '成交', value: 'PURCHASED' },
+                { label: '一口价成交', value: 'FIXED_PRICE_PURCHASED' },
+                { label: '流拍', value: 'PASS' },
+                { label: '完成', value: 'FINISH' }
+            ],
+            sourceOptions: [
+                { label: '官方拍卖', value: 'OFFICIAL' },
+                { label: '转让拍卖', value: 'TRANSFER' }
+            ],
+            endTime: '',
+            status: ''
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        auctionTypeFormatter(row, column, cellValue, index) {
+            let selectedOption = this.auctionTypeOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        statusFormatter(row, column, cellValue, index) {
+            let selectedOption = this.statusOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        sourceFormatter(row, column, cellValue, index) {
+            let selectedOption = this.sourceOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            return {
+                search: this.search,
+                query: { del: false, endTime: this.endTime, status: this.status, source: 'OFFICIAL' }
+            };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/auctionActivityEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/auctionActivityEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/auctionActivity/excel', {
+                    responseType: 'blob',
+                    params: { size: 10000 }
+                })
+                .then(res => {
+                    console.log(res);
+                    this.downloading = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloading = false;
+                    this.$message.error(e.error);
+                });
+        },
+        operation1() {
+            this.$notify({
+                title: '提示',
+                message: this.selection
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        deleteRow(row) {
+            this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/auctionActivity/del/${row.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 270 - 0
src/main/vue/src/views/AuctionOrderEdit.vue

@@ -0,0 +1,270 @@
+<template>
+    <div class="edit-view">
+        <page-title>
+            <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+            <!-- <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id"> 删除 </el-button>
+            <el-button @click="onSave" :loading="saving" type="primary">保存</el-button> -->
+        </page-title>
+        <div class="edit-view__content-wrapper">
+            <div class="edit-view__content-section">
+                <el-form
+                    :model="formData"
+                    :rules="rules"
+                    ref="form"
+                    label-width="94px"
+                    label-position="right"
+                    size="small"
+                    style="max-width: 700px"
+                >
+                    <el-form-item prop="userId" label="用户信息">
+                        <el-input-number type="number" v-model="formData.userId" disabled></el-input-number>
+                        <el-input
+                            v-model="formData.nickname"
+                            disabled
+                            style="margin-left: 6px; width: 200px"
+                        ></el-input>
+                    </el-form-item>
+                    <el-form-item prop="auctionId" label="拍卖信息">
+                        <el-input-number type="number" v-model="formData.auctionId" disabled></el-input-number>
+                        <el-input v-model="formData.name" disabled style="margin-left: 6px; width: 200px"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="pic" label="">
+                        <object-upload :value="pic" disabled></object-upload>
+                    </el-form-item>
+                    <!-- <el-form-item prop="properties" label="特性">
+                        <el-input v-model="formData.properties"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="privileges" label="特权">
+                        <el-input v-model="formData.privileges"></el-input>
+                    </el-form-item> -->
+                    <div class="inline-wrapper">
+                        <el-form-item prop="royalties" label="版税(%)">
+                            <el-input-number v-model="formData.royalties" :min="0" :max="99" disabled>
+                            </el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="serviceCharge" label="手续费(%)">
+                            <el-input-number v-model="formData.serviceCharge" :min="0" :max="99" disabled>
+                            </el-input-number>
+                        </el-form-item>
+                    </div>
+                    <div class="inline-wrapper">
+                        <el-form-item prop="price" label="价格">
+                            <el-input-number type="number" v-model="formData.price" disabled></el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="totalPrice" label="总价">
+                            <el-input-number type="number" v-model="formData.totalPrice" disabled></el-input-number>
+                        </el-form-item>
+                    </div>
+                    <el-form-item prop="source" label="来源">
+                        <el-select v-model="formData.source" clearable filterable placeholder="请选择">
+                            <el-option
+                                v-for="item in sourceOptions"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            >
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="paymentType" label="支付类型">
+                        <el-select v-model="formData.paymentType" clearable filterable placeholder="请选择">
+                            <el-option
+                                v-for="item in paymentTypeOptions"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            >
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="status" label="状态">
+                        <el-select v-model="formData.status" clearable filterable placeholder="请选择">
+                            <el-option
+                                v-for="item in statusOptions"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            >
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <div v-if="formData.status != 'CANCELLED' && formData.status != 'NOT_PAID'">
+                        <el-form-item prop="transactionId" label="交易订单号">
+                            <el-input v-model="formData.transactionId" disabled></el-input>
+                        </el-form-item>
+                        <el-form-item prop="payMethod" label="支付信息">
+                            <el-select
+                                v-model="formData.payMethod"
+                                clearable
+                                filterable
+                                placeholder="支付方式"
+                                disabled
+                            >
+                                <el-option
+                                    v-for="item in payMethodOptions"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                >
+                                </el-option>
+                            </el-select>
+                            <el-date-picker
+                                v-model="formData.payAt"
+                                type="datetime"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="支付时间"
+                                style="margin-left: 6px"
+                                disabled
+                            >
+                            </el-date-picker>
+                        </el-form-item>
+                    </div>
+                    <el-form-item prop="payTime" label="支付时间">
+                        <el-date-picker
+                            v-model="formData.payTime"
+                            type="datetime"
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            placeholder="选择日期时间"
+                        >
+                        </el-date-picker>
+                    </el-form-item>
+                    <el-form-item prop="cancelTime" label="取消时间" v-if="formData.status == 'CANCELLED'">
+                        <el-date-picker
+                            v-model="formData.cancelTime"
+                            type="datetime"
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            placeholder="选择日期时间"
+                            disabled
+                        >
+                        </el-date-picker>
+                    </el-form-item>
+                    <el-form-item label="收货信息">
+                        <el-input v-model="formData.contactName" style="width: 180px; margin-right: 6px"></el-input>
+                        <el-input v-model="formData.contactPhone" style="width: 240px"></el-input>
+                        <el-input
+                            type="textarea"
+                            size="2"
+                            v-model="formData.address"
+                            style="margin-top: 6px"
+                        ></el-input>
+                    </el-form-item>
+                    <el-form-item class="form-submit">
+                        <!-- <el-button @click="onSave" :loading="saving" type="primary"> 保存 </el-button>
+                        <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
+                            删除
+                        </el-button> -->
+                        <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+                    </el-form-item>
+                </el-form>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+export default {
+    name: 'AuctionOrderEdit',
+    created() {
+        if (this.$route.query.id) {
+            this.$http
+                .get('auctionOrder/get/' + this.$route.query.id)
+                .then(res => {
+                    this.formData = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        }
+    },
+    data() {
+        return {
+            saving: false,
+            formData: {},
+            rules: {},
+            sourceOptions: [
+                { label: '官方拍卖', value: 'OFFICIAL' },
+                { label: '转让拍卖', value: 'TRANSFER' }
+            ],
+            paymentTypeOptions: [
+                { label: '保证金', value: 'DEPOSIT' },
+                { label: '成交金', value: 'PURCHASE_PRICE' },
+                { label: '一口价', value: 'FIXED_PRICE' }
+            ],
+            statusOptions: [
+                { label: '未支付', value: 'NOT_PAID' },
+                { label: '已完成', value: 'FINISH' },
+                { label: '已取消', value: 'CANCELLED' },
+                { label: '退款中', value: 'REFUNDING' },
+                { label: '已退款', value: 'REFUNDED' },
+                { label: '待发货', value: 'DELIVERY' },
+                { label: '待收货', value: 'RECEIVE' }
+            ],
+            payMethodOptions: [
+                { label: '微信', value: 'WEIXIN' },
+                { label: '支付宝', value: 'ALIPAY' },
+                { label: '无GAS费', value: 'FREE' },
+                { label: '衫德支付', value: 'SANDPAY' },
+                { label: '河马支付', value: 'HMPAY' },
+                { label: '首信易', value: 'PAYEASE' },
+                { label: '余额支付', value: 'BALANCE' }
+            ]
+        };
+    },
+    computed: {
+        pic() {
+            return (this.formData.pic || [])[0] || {};
+        }
+    },
+    methods: {
+        onSave() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.submit();
+                } else {
+                    return false;
+                }
+            });
+        },
+        submit() {
+            let data = { ...this.formData };
+
+            this.saving = true;
+            this.$http
+                .post('/auctionOrder/save', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    this.$message.success('成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        },
+        onDelete() {
+            this.$confirm('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/auctionOrder/del/${this.formData.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        console.log(e);
+                        this.$message.error((e || {}).error || '删除失败');
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.inline-wrapper {
+    .el-form-item {
+        display: inline-block;
+    }
+}
+</style>

+ 289 - 0
src/main/vue/src/views/AuctionOrderList.vue

@@ -0,0 +1,289 @@
+<template>
+    <div class="list-view">
+        <page-title> </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"
+                    :key="item.value"
+                    :value="item.value"
+                    :label="item.label"
+                ></el-option>
+            </el-select>
+            <el-input
+                placeholder="搜索拍卖名称"
+                v-model="name"
+                clearable
+                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-input>
+            <created-at-picker v-model="createdAt" @input="getData" name="下单" class="filter-item"></created-at-picker>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+            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="155"> </el-table-column>
+            <el-table-column prop="userId" label="用户ID"> </el-table-column>
+            <el-table-column prop="nickname" label="昵称"> </el-table-column>
+            <el-table-column prop="auctionId" label="拍卖ID"> </el-table-column>
+            <el-table-column prop="name" label="名称"> </el-table-column>
+            <el-table-column prop="pic" label="图片">
+                <template slot-scope="{ row }">
+                    <el-image
+                        style="width: 30px; height: 30px"
+                        :src="row.pic[0].thumb || row.pic[0].url"
+                        fit="cover"
+                        :preview-src-list="row.pic.map(i => i.thumb || i.url)"
+                    ></el-image>
+                </template>
+            </el-table-column>
+            <el-table-column prop="source" label="来源" :formatter="sourceFormatter"> </el-table-column>
+            <el-table-column prop="paymentType" label="支付类型" :formatter="paymentTypeFormatter"> </el-table-column>
+            <!-- <el-table-column prop="price" label="价格"> </el-table-column> -->
+            <!-- <el-table-column prop="gasPrice" label="gas费"> </el-table-column> -->
+            <el-table-column prop="totalPrice" label="总价"> </el-table-column>
+            <el-table-column prop="status" label="状态" :formatter="statusFormatter"> </el-table-column>
+            <el-table-column prop="payMethod" label="支付方式" :formatter="payMethodFormatter"> </el-table-column>
+            <el-table-column prop="transactionId" label="交易ID"> </el-table-column>
+            <el-table-column prop="createdAt" label="下单时间"> </el-table-column>
+            <el-table-column prop="payTime" label="支付时间"> </el-table-column>
+            <el-table-column prop="cancelTime" label="取消时间"> </el-table-column>
+            <el-table-column label="收件人信息" min-width="120" show-overflow-tooltip>
+                <template slot-scope="{ row }">
+                    <span>{{ row.contactName }}</span>
+                    <span style="margin-left: 10px">{{ row.contactPhone }}</span
+                    ><br />
+                    <span>{{ row.address }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="120">
+                <template slot-scope="{ row }">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>查看</el-button>
+                    <!-- <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button> -->
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+    name: 'AuctionOrderList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/auctionOrder/all',
+            downloading: false,
+            sourceOptions: [
+                { label: '官方拍卖', value: 'OFFICIAL' },
+                { label: '转让拍卖', value: 'TRANSFER' }
+            ],
+            paymentTypeOptions: [
+                { label: '保证金', value: 'DEPOSIT' },
+                { label: '成交金', value: 'PURCHASE_PRICE' },
+                { label: '一口价', value: 'FIXED_PRICE' }
+            ],
+            statusOptions: [
+                { label: '未支付', value: 'NOT_PAID' },
+                { label: '已完成', value: 'FINISH' },
+                { label: '已取消', value: 'CANCELLED' },
+                { label: '退款中', value: 'REFUNDING' },
+                { label: '已退款', value: 'REFUNDED' },
+                { label: '待发货', value: 'DELIVERY' },
+                { label: '待收货', value: 'RECEIVE' }
+            ],
+            payMethodOptions: [
+                { label: '微信', value: 'WEIXIN' },
+                { label: '支付宝', value: 'ALIPAY' },
+                { label: '无GAS费', value: 'FREE' },
+                { label: '衫德支付', value: 'SANDPAY' },
+                { label: '河马支付', value: 'HMPAY' },
+                { label: '首信易', value: 'PAYEASE' },
+                { label: '余额支付', value: 'BALANCE' }
+            ],
+            name: '',
+            userId: '',
+            status: '',
+            createdAt: ''
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        typeFormatter(row, column, cellValue, index) {
+            let selectedOption = this.typeOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        sourceFormatter(row, column, cellValue, index) {
+            let selectedOption = this.sourceOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        paymentTypeFormatter(row, column, cellValue, index) {
+            let selectedOption = this.paymentTypeOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        statusFormatter(row, column, cellValue, index) {
+            let selectedOption = this.statusOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        payMethodFormatter(row, column, cellValue, index) {
+            let selectedOption = this.payMethodOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            return {
+                search: this.search,
+                query: {
+                    del: false,
+                    source: 'OFFICIAL',
+                    name: this.name,
+                    userId: this.userId,
+                    status: this.status,
+                    createdAt: this.createdAt
+                }
+            };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/auctionOrderEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/auctionOrderEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/auctionOrder/excel', {
+                    responseType: 'blob',
+                    params: { size: 10000 }
+                })
+                .then(res => {
+                    console.log(res);
+                    this.downloading = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloading = false;
+                    this.$message.error(e.error);
+                });
+        },
+        operation1() {
+            this.$notify({
+                title: '提示',
+                message: this.selection
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        deleteRow(row) {
+            this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/auctionOrder/del/${row.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 289 - 0
src/main/vue/src/views/AuctionOrderUsedList.vue

@@ -0,0 +1,289 @@
+<template>
+    <div class="list-view">
+        <page-title> </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"
+                    :key="item.value"
+                    :value="item.value"
+                    :label="item.label"
+                ></el-option>
+            </el-select>
+            <el-input
+                placeholder="搜索拍卖名称"
+                v-model="name"
+                clearable
+                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-input>
+            <created-at-picker v-model="createdAt" @input="getData" name="下单" class="filter-item"></created-at-picker>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+            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="155"> </el-table-column>
+            <el-table-column prop="userId" label="用户ID"> </el-table-column>
+            <el-table-column prop="nickname" label="昵称"> </el-table-column>
+            <el-table-column prop="auctionId" label="拍卖ID"> </el-table-column>
+            <el-table-column prop="name" label="名称"> </el-table-column>
+            <el-table-column prop="pic" label="图片">
+                <template slot-scope="{ row }">
+                    <el-image
+                        style="width: 30px; height: 30px"
+                        :src="row.pic[0].thumb || row.pic[0].url"
+                        fit="cover"
+                        :preview-src-list="row.pic.map(i => i.thumb || i.url)"
+                    ></el-image>
+                </template>
+            </el-table-column>
+            <el-table-column prop="source" label="来源" :formatter="sourceFormatter"> </el-table-column>
+            <el-table-column prop="paymentType" label="支付类型" :formatter="paymentTypeFormatter"> </el-table-column>
+            <!-- <el-table-column prop="price" label="价格"> </el-table-column> -->
+            <!-- <el-table-column prop="gasPrice" label="gas费"> </el-table-column> -->
+            <el-table-column prop="totalPrice" label="总价"> </el-table-column>
+            <el-table-column prop="status" label="状态" :formatter="statusFormatter"> </el-table-column>
+            <el-table-column prop="payMethod" label="支付方式" :formatter="payMethodFormatter"> </el-table-column>
+            <el-table-column prop="transactionId" label="交易ID"> </el-table-column>
+            <el-table-column prop="createdAt" label="下单时间"> </el-table-column>
+            <el-table-column prop="payTime" label="支付时间"> </el-table-column>
+            <el-table-column prop="cancelTime" label="取消时间"> </el-table-column>
+            <el-table-column label="收件人信息" min-width="120" show-overflow-tooltip>
+                <template slot-scope="{ row }">
+                    <span>{{ row.contactName }}</span>
+                    <span style="margin-left: 10px">{{ row.contactPhone }}</span
+                    ><br />
+                    <span>{{ row.address }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="120">
+                <template slot-scope="{ row }">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>查看</el-button>
+                    <!-- <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button> -->
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+    name: 'AuctionOrderList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/auctionOrder/all',
+            downloading: false,
+            sourceOptions: [
+                { label: '官方拍卖', value: 'OFFICIAL' },
+                { label: '转让拍卖', value: 'TRANSFER' }
+            ],
+            paymentTypeOptions: [
+                { label: '保证金', value: 'DEPOSIT' },
+                { label: '成交金', value: 'PURCHASE_PRICE' },
+                { label: '一口价', value: 'FIXED_PRICE' }
+            ],
+            statusOptions: [
+                { label: '未支付', value: 'NOT_PAID' },
+                { label: '已完成', value: 'FINISH' },
+                { label: '已取消', value: 'CANCELLED' },
+                { label: '退款中', value: 'REFUNDING' },
+                { label: '已退款', value: 'REFUNDED' },
+                { label: '待发货', value: 'DELIVERY' },
+                { label: '待收货', value: 'RECEIVE' }
+            ],
+            payMethodOptions: [
+                { label: '微信', value: 'WEIXIN' },
+                { label: '支付宝', value: 'ALIPAY' },
+                { label: '无GAS费', value: 'FREE' },
+                { label: '衫德支付', value: 'SANDPAY' },
+                { label: '河马支付', value: 'HMPAY' },
+                { label: '首信易', value: 'PAYEASE' },
+                { label: '余额支付', value: 'BALANCE' }
+            ],
+            name: '',
+            userId: '',
+            status: '',
+            createdAt: ''
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        typeFormatter(row, column, cellValue, index) {
+            let selectedOption = this.typeOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        sourceFormatter(row, column, cellValue, index) {
+            let selectedOption = this.sourceOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        paymentTypeFormatter(row, column, cellValue, index) {
+            let selectedOption = this.paymentTypeOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        statusFormatter(row, column, cellValue, index) {
+            let selectedOption = this.statusOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        payMethodFormatter(row, column, cellValue, index) {
+            let selectedOption = this.payMethodOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            return {
+                search: this.search,
+                query: {
+                    del: false,
+                    source: 'TRANSFER',
+                    name: this.name,
+                    userId: this.userId,
+                    status: this.status,
+                    createdAt: this.createdAt
+                }
+            };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/auctionOrderEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/auctionOrderEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/auctionOrder/excel', {
+                    responseType: 'blob',
+                    params: { size: 10000 }
+                })
+                .then(res => {
+                    console.log(res);
+                    this.downloading = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloading = false;
+                    this.$message.error(e.error);
+                });
+        },
+        operation1() {
+            this.$notify({
+                title: '提示',
+                message: this.selection
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        deleteRow(row) {
+            this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/auctionOrder/del/${row.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 132 - 0
src/main/vue/src/views/AuctionRecordEdit.vue

@@ -0,0 +1,132 @@
+<template>
+    <div class="edit-view">
+        <page-title>
+            <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+            <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
+                删除
+            </el-button>
+            <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
+        </page-title>
+        <div class="edit-view__content-wrapper">
+            <div class="edit-view__content-section">
+                <el-form :model="formData" :rules="rules" ref="form" label-width="108px" label-position="right"
+                         size="small"
+                         style="max-width: 500px;">
+                        <el-form-item prop="userId" label="用户ID">
+                                    <el-input-number type="number" v-model="formData.userId"></el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="avatar" label="用户头像">
+                                    <el-input v-model="formData.avatar"></el-input>
+                        </el-form-item>
+                        <el-form-item prop="user" label="用户昵称">
+                                    <el-input v-model="formData.user"></el-input>
+                        </el-form-item>
+                        <el-form-item prop="auctionId" label="拍卖活动ID">
+                                    <el-input-number type="number" v-model="formData.auctionId"></el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="name" label="拍卖活动">
+                                    <el-input-number type="number" v-model="formData.name"></el-input-number>
+                        </el-form-item>
+                        <el-form-item prop="auctionPic" label="拍卖活动图片">
+                                    <el-input v-model="formData.auctionPic"></el-input>
+                        </el-form-item>
+                        <el-form-item prop="type" label="类型">
+                                    <el-select v-model="formData.type" clearable filterable placeholder="请选择">
+                                        <el-option
+                                                v-for="item in typeOptions"
+                                                :key="item.value"
+                                                :label="item.label"
+                                                :value="item.value">
+                                        </el-option>
+                                    </el-select>
+                        </el-form-item>
+                        <el-form-item prop="purchased" label="是否竞得">
+                                    <el-input v-model="formData.purchased"></el-input>
+                        </el-form-item>
+                        <el-form-item prop="bidderPrice" label="出价">
+                                    <el-input-number type="number" v-model="formData.bidderPrice"></el-input-number>
+                        </el-form-item>
+                    <el-form-item class="form-submit">
+                        <el-button @click="onSave" :loading="saving" type="primary">
+                            保存
+                        </el-button>
+                        <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
+                            删除
+                        </el-button>
+                        <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+                    </el-form-item>
+                </el-form>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+    export default {
+        name: 'AuctionRecordEdit',
+        created() {
+            if (this.$route.query.id) {
+                this.$http
+                    .get('auctionRecord/get/' + this.$route.query.id)
+                    .then(res => {
+                        this.formData = res;
+                    })
+                    .catch(e => {
+                        console.log(e);
+                        this.$message.error(e.error);
+                    });
+            }
+        },
+        data() {
+            return {
+                saving: false,
+                formData: {
+                },
+                rules: {
+                },
+                typeOptions: [{"label":"保证金","value":"DEPOSIT"},{"label":"竞拍","value":"BIDDER"},{"label":"一口价","value":"FIXEDPRICE"}],
+            }
+        },
+        methods: {
+            onSave() {
+                this.$refs.form.validate((valid) => {
+                    if (valid) {
+                        this.submit();
+                    } else {
+                        return false;
+                    }
+                });
+            },
+            submit() {
+                let data = {...this.formData};
+
+                this.saving = true;
+                this.$http
+                    .post('/auctionRecord/save', data, {body: 'json'})
+                    .then(res => {
+                        this.saving = false;
+                        this.$message.success('成功');
+                        this.$router.go(-1);
+                    })
+                    .catch(e => {
+                        console.log(e);
+                        this.saving = false;
+                        this.$message.error(e.error);
+                    });
+            },
+            onDelete() {
+                this.$confirm('删除将无法恢复,确认要删除么?', '警告', {type: 'error'}).then(() => {
+                    return this.$http.post(`/auctionRecord/del/${this.formData.id}`)
+                }).then(() => {
+                    this.$message.success('删除成功');
+                    this.$router.go(-1);
+                }).catch(e => {
+                    if (e !== 'cancel') {
+                        console.log(e);
+                        this.$message.error((e || {}).error || '删除失败');
+                    }
+                })
+            },
+        }
+    }
+</script>
+<style lang="less" scoped></style>

+ 196 - 0
src/main/vue/src/views/AuctionRecordList.vue

@@ -0,0 +1,196 @@
+<template>
+    <div  class="list-view">
+        <page-title>
+            <el-button @click="addRow" type="primary" icon="el-icon-plus" :disabled="fetchingData || downloading" class="filter-item">
+                新增
+            </el-button>
+            <el-button @click="download" icon="el-icon-upload2" :loading="downloading" :disabled="fetchingData" class="filter-item">
+                导出
+            </el-button>
+        </page-title>
+        <div class="filters-container">
+            <el-input
+                    placeholder="搜索..."
+                    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>
+        </div>
+        <el-table :data="tableData" row-key="id" ref="table"
+                  header-row-class-name="table-header-row"
+                  header-cell-class-name="table-header-cell"
+                  row-class-name="table-row" cell-class-name="table-cell"
+                  :height="tableHeight" 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">
+            </el-table-column>
+                                <el-table-column prop="userId" label="用户ID"
+>
+                    </el-table-column>
+                    <el-table-column prop="avatar" label="用户头像"
+>
+                    </el-table-column>
+                    <el-table-column prop="user" label="用户昵称"
+>
+                    </el-table-column>
+                    <el-table-column prop="auctionId" label="拍卖活动ID"
+>
+                    </el-table-column>
+                    <el-table-column prop="name" label="拍卖活动"
+>
+                    </el-table-column>
+                    <el-table-column prop="auctionPic" label="拍卖活动图片"
+>
+                    </el-table-column>
+                    <el-table-column prop="type" label="类型"
+                            :formatter="typeFormatter"
+                        >
+                    </el-table-column>
+                    <el-table-column prop="purchased" label="是否竞得"
+>
+                    </el-table-column>
+                    <el-table-column prop="bidderPrice" label="出价"
+>
+                    </el-table-column>
+            <el-table-column
+                    label="操作"
+                    align="center"
+                    fixed="right"
+                    width="150">
+                <template slot-scope="{row}">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
+                    <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination background @size-change="onSizeChange"
+                           @current-change="onCurrentChange" :current-page="page"
+                           :page-sizes="[10, 20, 30, 40, 50]" :page-size="pageSize"
+                           layout="total, sizes, prev, pager, next, jumper"
+                           :total="totalElements">
+            </el-pagination>
+        </div>
+
+    </div>
+</template>
+<script>
+    import { mapState } from "vuex";
+    import pageableTable from "@/mixins/pageableTable";
+
+    export default {
+        name: 'AuctionRecordList',
+        mixins: [pageableTable],
+        data() {
+            return {
+                multipleMode: false,
+                search: "",
+                url: "/auctionRecord/all",
+                downloading: false,
+                        typeOptions:[{"label":"保证金","value":"DEPOSIT"},{"label":"竞拍","value":"BIDDER"},{"label":"一口价","value":"FIXEDPRICE"}],
+            }
+        },
+        computed: {
+            selection() {
+                return this.$refs.table.selection.map(i => i.id);
+            }
+        },
+        methods: {
+                    typeFormatter(row, column, cellValue, index) {
+                        let selectedOption = this.typeOptions.find(i => i.value === cellValue);
+                        if (selectedOption) {
+                            return selectedOption.label;
+                        }
+                        return '';
+                    },
+            beforeGetData() {
+                return { search: this.search, query: { del: false } };
+            },
+            toggleMultipleMode(multipleMode) {
+                this.multipleMode = multipleMode;
+                if (!multipleMode) {
+                    this.$refs.table.clearSelection();
+                }
+            },
+            addRow() {
+                this.$router.push({
+                    path: "/auctionRecordEdit",
+                    query: {
+                        ...this.$route.query
+                    }
+                });
+            },
+            editRow(row) {
+                this.$router.push({
+                    path: "/auctionRecordEdit",
+                    query: {
+                    id: row.id
+                    }
+                });
+            },
+            download() {
+                this.downloading = true;
+                this.$axios
+                    .get("/auctionRecord/excel", { 
+                        responseType: "blob",
+                        params: { size: 10000 }
+                    })
+                    .then(res => {
+                        console.log(res);
+                        this.downloading = false;
+                        const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                        const link = document.createElement("a");
+                        link.href = downloadUrl;
+                        link.setAttribute(
+                            "download",
+                            res.headers["content-disposition"].split("filename=")[1]
+                        );
+                        document.body.appendChild(link);
+                        link.click();
+                        link.remove();
+                    })
+                    .catch(e => {
+                        console.log(e);
+                        this.downloading = false;
+                        this.$message.error(e.error);
+                    });
+            },
+            operation1() {
+                this.$notify({
+                    title: '提示',
+                    message: this.selection
+                });
+            },
+            operation2() {
+                this.$message('操作2');
+            },
+            deleteRow(row) {
+                this.$alert('删除将无法恢复,确认要删除么?', '警告', {type: 'error'}).then(() => {
+                    return this.$http.post(`/auctionRecord/del/${row.id}`)
+                }).then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                }).catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                })
+            },
+        }
+    }
+</script>
+<style lang="less" scoped>
+</style>

+ 260 - 0
src/main/vue/src/views/AuctionUsedList.vue

@@ -0,0 +1,260 @@
+<template>
+    <div class="list-view">
+        <page-title>
+            <!-- <el-button
+                @click="addRow"
+                type="primary"
+                icon="el-icon-plus"
+                :disabled="fetchingData || downloading"
+                class="filter-item"
+            >
+                新增
+            </el-button> -->
+            <!-- <el-button
+                @click="download"
+                icon="el-icon-upload2"
+                :loading="downloading"
+                :disabled="fetchingData"
+                class="filter-item"
+            >
+                导出
+            </el-button> -->
+        </page-title>
+        <div class="filters-container">
+            <el-input
+                placeholder="搜索拍卖名称..."
+                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>
+            <created-at-picker
+                v-model="endTime"
+                @input="getData"
+                name="拍卖结束"
+                class="filter-item"
+            ></created-at-picker>
+            <el-select v-model="status" clearable class="filter-item" placeholder="请选择状态" @change="getData">
+                <el-option
+                    v-for="item in statusOptions"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                ></el-option>
+            </el-select>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+            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="90"> </el-table-column>
+            <el-table-column prop="sellerId" label="起拍人ID"> </el-table-column>
+            <el-table-column prop="seller" label="起拍人昵称"> </el-table-column>
+            <!-- <el-table-column prop="sellerAvatar" label="起拍人头像"> </el-table-column> -->
+            <el-table-column prop="name" label="拍卖名称"> </el-table-column>
+            <el-table-column prop="auctionType" label="拍卖类型" :formatter="auctionTypeFormatter"> </el-table-column>
+            <el-table-column prop="minter" label="铸造者"> </el-table-column>
+            <el-table-column prop="assetId" label="藏品ID"> </el-table-column>
+            <el-table-column prop="pic" label="作品内容" width="90" align="center">
+                <template slot-scope="{ row }">
+                    <el-image
+                        style="width: 30px; height: 30px"
+                        :src="row.pic[0].thumb || row.pic[0].url"
+                        fit="cover"
+                        :preview-src-list="row.pic.map(i => i.thumb || i.url)"
+                    ></el-image>
+                </template>
+            </el-table-column>
+            <!-- <el-table-column prop="detail" label="详情"> </el-table-column> -->
+            <!-- <el-table-column prop="category" label="分类"> </el-table-column> -->
+            <el-table-column prop="startingPrice" label="起拍价"> </el-table-column>
+            <el-table-column prop="deposit" label="保证金"> </el-table-column>
+            <el-table-column prop="fixedPrice" label="一口价"> </el-table-column>
+            <el-table-column prop="startTime" label="开始时间"> </el-table-column>
+            <el-table-column prop="increment" label="加价幅度"> </el-table-column>
+            <el-table-column prop="endTime" label="截止时间"> </el-table-column>
+            <el-table-column prop="purchasePrice" label="成交价"> </el-table-column>
+            <el-table-column prop="purchaserId" label="买家id"> </el-table-column>
+            <el-table-column prop="purchaser" label="买家"> </el-table-column>
+            <el-table-column prop="status" label="状态" :formatter="statusFormatter"> </el-table-column>
+            <el-table-column prop="source" label="来源" :formatter="sourceFormatter"> </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="150">
+                <template slot-scope="{ row }">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
+                    <!-- <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button> -->
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+    name: 'AuctionActivityList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/auctionActivity/all',
+            downloading: false,
+            auctionTypeOptions: [
+                { label: '虚拟藏品', value: 'NFT' },
+                { label: '实物', value: 'ENTITY' }
+            ],
+            statusOptions: [
+                { label: '未开始', value: 'NOTSTARTED' },
+                { label: '进行中', value: 'ONGOING' },
+                { label: '成交', value: 'PURCHASED' },
+                { label: '一口价成交', value: 'FIXED_PRICE_PURCHASED' },
+                { label: '流拍', value: 'PASS' },
+                { label: '完成', value: 'FINISH' }
+            ],
+            sourceOptions: [
+                { label: '官方拍卖', value: 'OFFICIAL' },
+                { label: '转让拍卖', value: 'TRANSFER' }
+            ],
+            endTime: '',
+            status: ''
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        auctionTypeFormatter(row, column, cellValue, index) {
+            let selectedOption = this.auctionTypeOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        statusFormatter(row, column, cellValue, index) {
+            let selectedOption = this.statusOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        sourceFormatter(row, column, cellValue, index) {
+            let selectedOption = this.sourceOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            return {
+                search: this.search,
+                query: { del: false, endTime: this.endTime, status: this.status, source: 'TRANSFER' }
+            };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/auctionActivityEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/auctionActivityEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/auctionActivity/excel', {
+                    responseType: 'blob',
+                    params: { size: 10000 }
+                })
+                .then(res => {
+                    console.log(res);
+                    this.downloading = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloading = false;
+                    this.$message.error(e.error);
+                });
+        },
+        operation1() {
+            this.$notify({
+                title: '提示',
+                message: this.selection
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        deleteRow(row) {
+            this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/auctionActivity/del/${row.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 2 - 0
src/main/vue/src/views/BannerEdit.vue

@@ -156,6 +156,7 @@ export default {
                 { label: '首页', value: 'HOME' },
                 { label: '首页', value: 'HOME' },
                 { label: '发现页', value: 'DISCOVER' },
                 { label: '发现页', value: 'DISCOVER' },
                 { label: '铸造者', value: 'MINTER' },
                 { label: '铸造者', value: 'MINTER' },
+                { label: '拍卖', value: 'AUCTION' },
                 { label: '二手市场', value: 'MARKET' },
                 { label: '二手市场', value: 'MARKET' },
                 { label: 'PC官方活动', value: 'PC_ACT' },
                 { label: 'PC官方活动', value: 'PC_ACT' },
                 { label: 'PC首页大图', value: 'PC_TITLE' }
                 { label: 'PC首页大图', value: 'PC_TITLE' }
@@ -164,6 +165,7 @@ export default {
                 { label: '藏品/盲盒', value: 'collection' },
                 { label: '藏品/盲盒', value: 'collection' },
                 { label: '铸造者', value: 'user' },
                 { label: '铸造者', value: 'user' },
                 { label: '活动', value: 'activity' },
                 { label: '活动', value: 'activity' },
+                { label: '拍卖', value: 'auctionActivity' },
                 { label: '多个藏品', value: 'collections' },
                 { label: '多个藏品', value: 'collections' },
                 { label: '指定链接', value: 'hyperlink' }
                 { label: '指定链接', value: 'hyperlink' }
             ],
             ],

+ 1 - 0
src/main/vue/src/views/BannerList.vue

@@ -111,6 +111,7 @@ export default {
                 { label: '首页', value: 'HOME' },
                 { label: '首页', value: 'HOME' },
                 { label: '发现页', value: 'DISCOVER' },
                 { label: '发现页', value: 'DISCOVER' },
                 { label: '铸造者', value: 'MINTER' },
                 { label: '铸造者', value: 'MINTER' },
+                { label: '拍卖', value: 'AUCTION' },
                 { label: '二手市场', value: 'MARKET' },
                 { label: '二手市场', value: 'MARKET' },
                 { label: 'PC官方活动', value: 'PC_ACT' },
                 { label: 'PC官方活动', value: 'PC_ACT' },
                 { label: 'PC首页大图', value: 'PC_TITLE' }
                 { label: 'PC首页大图', value: 'PC_TITLE' }

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

@@ -23,7 +23,7 @@
         <div class="filters-container">
         <div class="filters-container">
             <created-at-picker v-model="createdAt" @input="getData" name="支付" class="filter-item"></created-at-picker>
             <created-at-picker v-model="createdAt" @input="getData" name="支付" class="filter-item"></created-at-picker>
             <el-input
             <el-input
-                placeholder="搜索..."
+                placeholder="搜索手机号..."
                 v-model="search"
                 v-model="search"
                 clearable
                 clearable
                 class="filter-item search"
                 class="filter-item search"

+ 18 - 0
src/test/java/com/izouma/nineth/repo/AuctionRecordRepoTest.java

@@ -0,0 +1,18 @@
+package com.izouma.nineth.repo;
+
+
+import com.izouma.nineth.ApplicationTests;
+import com.izouma.nineth.enums.AuctionType;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class AuctionRecordRepoTest extends ApplicationTests {
+    @Autowired
+    private AuctionRecordRepo auctionRecordRepo;
+
+    @Test
+    public void test() {
+        auctionRecordRepo.findByUserId(9972L, AuctionType.NFT.toString());
+    }
+
+}

+ 24 - 73
src/test/java/com/izouma/nineth/repo/UserPropertyRepoTest.java

@@ -8,6 +8,7 @@ import com.izouma.nineth.domain.UserProperty;
 import com.izouma.nineth.dto.AirDropExcelDTO;
 import com.izouma.nineth.dto.AirDropExcelDTO;
 import com.izouma.nineth.enums.AssetStatus;
 import com.izouma.nineth.enums.AssetStatus;
 import com.izouma.nineth.utils.excel.UploadDataListener;
 import com.izouma.nineth.utils.excel.UploadDataListener;
+import org.apache.commons.lang3.ObjectUtils;
 import org.junit.Test;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 
 
@@ -169,18 +170,22 @@ public class UserPropertyRepoTest extends ApplicationTests {
 
 
     @Test
     @Test
     public void setById() {
     public void setById() {
-        userPropertyRepo.deleteAll();
+//        userPropertyRepo.deleteAll();
         File file = new File("/Users/sunnianwen/Desktop/all1.xlsx");
         File file = new File("/Users/sunnianwen/Desktop/all1.xlsx");
+        File file2 = new File("/Users/sunnianwen/Desktop/123.xlsx");
+
         UploadDataListener<AirDropExcelDTO> listener = new UploadDataListener<>();
         UploadDataListener<AirDropExcelDTO> listener = new UploadDataListener<>();
         List<AirDropExcelDTO> dtos = EasyExcel.read(file, AirDropExcelDTO.class, listener)
         List<AirDropExcelDTO> dtos = EasyExcel.read(file, AirDropExcelDTO.class, listener)
                 .sheet()
                 .sheet()
                 .doReadSync();
                 .doReadSync();
+        List<AirDropExcelDTO> dtos2 = EasyExcel.read(file2, AirDropExcelDTO.class, listener)
+                .sheet()
+                .doReadSync();
 //        Set<String> userIds = dtos.stream()
 //        Set<String> userIds = dtos.stream()
 //                .map(AirDropExcelDTO::getPhone)
 //                .map(AirDropExcelDTO::getPhone)
 //                .collect(Collectors.toSet());
 //                .collect(Collectors.toSet());
 //        System.out.println(userIds);
 //        System.out.println(userIds);
         dtos.forEach(id -> {
         dtos.forEach(id -> {
-
             UserProperty userProperty = userPropertyRepo.findById(Long.parseLong(id.getPhone()))
             UserProperty userProperty = userPropertyRepo.findById(Long.parseLong(id.getPhone()))
                     .orElse(new UserProperty(Long.parseLong(id.getPhone()), 0));
                     .orElse(new UserProperty(Long.parseLong(id.getPhone()), 0));
             userProperty.setMaxCount(Integer.parseInt(id.getName()));
             userProperty.setMaxCount(Integer.parseInt(id.getName()));
@@ -189,6 +194,18 @@ public class UserPropertyRepoTest extends ApplicationTests {
 //            }
 //            }
             userPropertyRepo.save(userProperty);
             userPropertyRepo.save(userProperty);
         });
         });
+        dtos2.forEach(id -> {
+
+            UserProperty userProperty = userPropertyRepo.findById(Long.parseLong(id.getPhone()))
+                    .orElse(null);
+            if (ObjectUtils.isEmpty(userProperty)) {
+                userProperty = new UserProperty(Long.parseLong(id.getPhone()), Integer.parseInt(id.getName()));
+            } else {
+                userProperty.setMaxCount(userProperty.getMaxCount() + 1);
+            }
+
+            userPropertyRepo.save(userProperty);
+        });
     }
     }
 
 
     @Test
     @Test
@@ -226,80 +243,14 @@ public class UserPropertyRepoTest extends ApplicationTests {
     }
     }
 
 
     @Test
     @Test
-    public void test() {
+    public void test(){
         Iterable<UserProperty> all = userPropertyRepo.findAll();
         Iterable<UserProperty> all = userPropertyRepo.findAll();
-//        System.out.println(all);
-        AtomicInteger sum = new AtomicInteger();
         all.forEach(p -> {
         all.forEach(p -> {
-            sum.getAndIncrement();
+            if (p.getMaxCount() > 1) {
+                p.setMaxCount(p.getMaxCount() - 1);
+                userPropertyRepo.save(p);
+            }
         });
         });
-        System.out.println(sum.get());
-    }
-
-    @Test
-    public void heji() {
-        Map<String, Integer> map = new HashMap<>();
-        UploadDataListener<AirDropExcelDTO> listener = new UploadDataListener<>();
-
-//        File fileLei = new File("/Users/sunnianwen/Desktop/lei.xlsx");
-//        List<AirDropExcelDTO> leis = EasyExcel.read(fileLei, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        leis.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-//
-//        File fileTuan = new File("/Users/sunnianwen/Desktop/tuan.xlsx");
-//        List<AirDropExcelDTO> tuans = EasyExcel.read(fileTuan, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        tuans.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-//
-//        File fileDi = new File("/Users/sunnianwen/Desktop/di.xlsx");
-//        List<AirDropExcelDTO> dis = EasyExcel.read(fileDi, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        dis.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-//
-//        File fileTop1 = new File("/Users/sunnianwen/Desktop/top20_1.xlsx");
-//        List<AirDropExcelDTO> top1s = EasyExcel.read(fileTop1, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        top1s.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-//
-//        File fileTop2 = new File("/Users/sunnianwen/Desktop/top20_2.xlsx");
-//        List<AirDropExcelDTO> top2s = EasyExcel.read(fileTop2, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        top2s.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-//
-//        File vipLou = new File("/Users/sunnianwen/Desktop/vip_man_lou.xlsx");
-//        List<AirDropExcelDTO> lou1s = EasyExcel.read(vipLou, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        lou1s.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-//
-//        File baiLou = new File("/Users/sunnianwen/Desktop/bai_lou.xlsx");
-//        List<AirDropExcelDTO> lou2s = EasyExcel.read(baiLou, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        lou2s.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-//
-//        File vip = new File("/Users/sunnianwen/Desktop/vip.xlsx");
-//        List<AirDropExcelDTO> vips = EasyExcel.read(vip, AirDropExcelDTO.class, listener)
-//                .sheet()
-//                .doReadSync();
-//        vips.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-
-        File all = new File("/Users/sunnianwen/Desktop/all1.xlsx");
-        List<AirDropExcelDTO> alls = EasyExcel.read(all, AirDropExcelDTO.class, listener)
-                .sheet()
-                .doReadSync();
-        alls.forEach(dto -> map.merge(dto.getPhone(), Integer.parseInt(dto.getName()), Integer::sum));
-
-        map.forEach((key, value) -> System.out.println(key + "," + value));
-        AtomicInteger sum = new AtomicInteger();
-        map.forEach((key, value) -> sum.addAndGet(value));
-        System.out.println(sum.get());
     }
     }
 
 
-
 }
 }

+ 10 - 4
src/test/java/com/izouma/nineth/repo/UserRepoTest.java

@@ -9,6 +9,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.context.junit4.SpringRunner;
 
 
 import java.time.LocalDate;
 import java.time.LocalDate;
@@ -18,7 +19,10 @@ import java.util.*;
 @SpringBootTest
 @SpringBootTest
 public class UserRepoTest {
 public class UserRepoTest {
     @Autowired
     @Autowired
-    private UserRepo userRepo;
+    private UserRepo        userRepo;
+    @Autowired
+    private PasswordEncoder passwordEncoder;
+
 
 
     @Test
     @Test
     public void testUser() {
     public void testUser() {
@@ -66,8 +70,10 @@ public class UserRepoTest {
 
 
     @Test
     @Test
     public void test1() {
     public void test1() {
-        List<Long> userIds = userRepo.findInvitorByCollectionId(3460186L, 2);
-        System.out.println(userIds.size());
-        userRepo.updateAllByInvitor(userIds);
+//        List<Long> userIds = userRepo.findInvitorByCollectionId(3460186L, 2);
+//        System.out.println(userIds.size());
+//        userRepo.updateAllByInvitor(userIds);
+        User user = userRepo.findById(9972L).orElse(null);
+        System.out.println(passwordEncoder.matches("123456", user.getTradeCode()));
     }
     }
 }
 }

+ 44 - 0
src/test/java/com/izouma/nineth/service/AuctionActivityServiceTest.java

@@ -0,0 +1,44 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.ApplicationTests;
+import com.izouma.nineth.domain.AuctionActivity;
+import com.izouma.nineth.dto.auction.AuctionInputDTO;
+import com.izouma.nineth.repo.AuctionActivityRepo;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+
+public class AuctionActivityServiceTest extends ApplicationTests {
+
+    @Autowired
+    private AuctionActivityService auctionActivityService;
+    @Autowired
+    private AuctionActivityRepo    auctionActivityRepo;
+
+    @Test
+    public void test() {
+        auctionActivityService.init();
+    }
+
+    @Test
+    public void test1() {
+        AuctionActivity activity = auctionActivityRepo.findById(2652491L).orElse(null);
+
+        auctionActivityService.offShelfTask(activity);
+    }
+
+    @Test
+    public void test2() {
+        AuctionInputDTO dto = new AuctionInputDTO();
+        dto.setAssetId(206885L);
+        dto.setDeposit(new BigDecimal("0.1"));
+        dto.setStartTime(LocalDateTime.now());
+        dto.setFixedPrice(new BigDecimal("0.01"));
+        dto.setIncrement(new BigDecimal("0.01"));
+        dto.setTradeCode("123456");
+        auctionActivityService.createFromAsset(dto);
+
+    }
+}

+ 16 - 0
src/test/java/com/izouma/nineth/service/AuctionOrderServiceTest.java

@@ -0,0 +1,16 @@
+package com.izouma.nineth.service;
+
+
+import com.izouma.nineth.ApplicationTests;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class AuctionOrderServiceTest extends ApplicationTests {
+    @Autowired
+    private AuctionOrderService auctionOrderService;
+
+    @Test
+    public void test() {
+        auctionOrderService.passOverTimeAuction();
+    }
+}

+ 17 - 0
src/test/java/com/izouma/nineth/service/AuctionRecordServiceTest.java

@@ -0,0 +1,17 @@
+package com.izouma.nineth.service;
+
+
+import com.izouma.nineth.ApplicationTests;
+import com.izouma.nineth.dto.PageQuery;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class AuctionRecordServiceTest extends ApplicationTests {
+    @Autowired
+    private AuctionRecordService auctionRecordService;
+
+    @Test
+    public void test() {
+    }
+
+}

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

@@ -261,7 +261,7 @@ public class OrderServiceTest extends ApplicationTests {
 
 
     @Test
     @Test
     public void test1() {
     public void test1() {
-        orderService.queryCreateOrder("945378720611303424");
+        orderService.queryCreateOrder("1234");
     }
     }
 
 
     @Test
     @Test

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott