فهرست منبع

Merge remote-tracking branch 'origin/master' into master_加密

wangqifan 3 سال پیش
والد
کامیت
e2e187e118
80فایلهای تغییر یافته به همراه3974 افزوده شده و 151 حذف شده
  1. 3 0
      src/main/java/com/izouma/nineth/config/CacheConfig.java
  2. 54 0
      src/main/java/com/izouma/nineth/domain/MetaAtomTask.java
  3. 62 0
      src/main/java/com/izouma/nineth/domain/MetaStore.java
  4. 35 0
      src/main/java/com/izouma/nineth/domain/MetaStorePurchaseRecord.java
  5. 6 12
      src/main/java/com/izouma/nineth/domain/MetaTask.java
  6. 38 0
      src/main/java/com/izouma/nineth/domain/MetaTaskBind.java
  7. 63 0
      src/main/java/com/izouma/nineth/domain/MetaTaskNew.java
  8. 10 10
      src/main/java/com/izouma/nineth/domain/MetaTaskToUser.java
  9. 83 0
      src/main/java/com/izouma/nineth/domain/MetaTaskToUserNew.java
  10. 3 3
      src/main/java/com/izouma/nineth/domain/MetaUserTaskProgress.java
  11. 48 0
      src/main/java/com/izouma/nineth/domain/MetaUserTaskProgressNew.java
  12. 2 5
      src/main/java/com/izouma/nineth/domain/Rice.java
  13. 4 4
      src/main/java/com/izouma/nineth/domain/RiceInvite.java
  14. 35 0
      src/main/java/com/izouma/nineth/domain/nftdomain/Cart.java
  15. 21 0
      src/main/java/com/izouma/nineth/dto/MetaResourcesLikeDTO.java
  16. 13 0
      src/main/java/com/izouma/nineth/dto/nftdomain/DomainResult.java
  17. 19 0
      src/main/java/com/izouma/nineth/enums/MetaStoreCommodityType.java
  18. 0 22
      src/main/java/com/izouma/nineth/enums/MetaTaskClassification.java
  19. 21 0
      src/main/java/com/izouma/nineth/enums/MetaTaskTarget.java
  20. 4 7
      src/main/java/com/izouma/nineth/enums/MetaTaskType.java
  21. 3 0
      src/main/java/com/izouma/nineth/repo/AssetRepo.java
  22. 21 0
      src/main/java/com/izouma/nineth/repo/MetaAtomTaskRepo.java
  23. 13 0
      src/main/java/com/izouma/nineth/repo/MetaStorePurchaseRecordRepo.java
  24. 26 0
      src/main/java/com/izouma/nineth/repo/MetaStoreRepo.java
  25. 28 0
      src/main/java/com/izouma/nineth/repo/MetaTaskBindRepo.java
  26. 26 0
      src/main/java/com/izouma/nineth/repo/MetaTaskNewRepo.java
  27. 23 0
      src/main/java/com/izouma/nineth/repo/MetaTaskToUserNewRepo.java
  28. 18 0
      src/main/java/com/izouma/nineth/repo/MetaUserTaskProgressNewRepo.java
  29. 3 0
      src/main/java/com/izouma/nineth/repo/OrderRepo.java
  30. 8 2
      src/main/java/com/izouma/nineth/repo/RiceInviteRepo.java
  31. 9 0
      src/main/java/com/izouma/nineth/repo/RiceRepo.java
  32. 20 0
      src/main/java/com/izouma/nineth/repo/nftdomain/CartRepo.java
  33. 11 0
      src/main/java/com/izouma/nineth/service/DomainOrderService.java
  34. 20 0
      src/main/java/com/izouma/nineth/service/MetaAtomTaskService.java
  35. 20 0
      src/main/java/com/izouma/nineth/service/MetaStorePurchaseRecordService.java
  36. 127 0
      src/main/java/com/izouma/nineth/service/MetaStoreService.java
  37. 67 0
      src/main/java/com/izouma/nineth/service/MetaTaskNewService.java
  38. 276 0
      src/main/java/com/izouma/nineth/service/MetaTaskToUserNewService.java
  39. 8 0
      src/main/java/com/izouma/nineth/service/MetaUserGoldService.java
  40. 3 3
      src/main/java/com/izouma/nineth/service/MetaUserTaskAwardReceivedRecordService.java
  41. 181 0
      src/main/java/com/izouma/nineth/service/MetaUserTaskProgressNewService.java
  42. 5 5
      src/main/java/com/izouma/nineth/service/MetaUserTaskProgressService.java
  43. 96 1
      src/main/java/com/izouma/nineth/service/RiceService.java
  44. 2 2
      src/main/java/com/izouma/nineth/service/StatisticService.java
  45. 59 0
      src/main/java/com/izouma/nineth/service/nftdomain/CartService.java
  46. 43 0
      src/main/java/com/izouma/nineth/utils/MetaTaskTargetConverter.java
  47. 1 0
      src/main/java/com/izouma/nineth/utils/excel/ExcelUtils.java
  48. 10 0
      src/main/java/com/izouma/nineth/web/AssetController.java
  49. 9 2
      src/main/java/com/izouma/nineth/web/DomainOrderController.java
  50. 65 0
      src/main/java/com/izouma/nineth/web/MetaAtomTaskController.java
  51. 20 0
      src/main/java/com/izouma/nineth/web/MetaResourcesController.java
  52. 135 0
      src/main/java/com/izouma/nineth/web/MetaStoreController.java
  53. 33 0
      src/main/java/com/izouma/nineth/web/MetaStorePurchaseRecordController.java
  54. 2 2
      src/main/java/com/izouma/nineth/web/MetaTaskController.java
  55. 87 0
      src/main/java/com/izouma/nineth/web/MetaTaskNewController.java
  56. 64 0
      src/main/java/com/izouma/nineth/web/MetaTaskToUserNewController.java
  57. 51 0
      src/main/java/com/izouma/nineth/web/MetaUserTaskProgressNewController.java
  58. 72 4
      src/main/java/com/izouma/nineth/web/RiceController.java
  59. 100 29
      src/main/java/com/izouma/nineth/web/RiceInviteController.java
  60. 12 4
      src/main/java/com/izouma/nineth/web/RiceOperationRecordController.java
  61. 13 4
      src/main/java/com/izouma/nineth/web/RiceUserWaterDropRecordController.java
  62. 2 0
      src/main/java/com/izouma/nineth/web/StatisticController.java
  63. 74 0
      src/main/java/com/izouma/nineth/web/nftdomain/CartController.java
  64. 1 0
      src/main/resources/genjson/MetaAtomTask.json
  65. 0 0
      src/main/resources/genjson/MetaStore.json
  66. 1 0
      src/main/resources/genjson/MetaTaskNew.json
  67. 1 1
      src/main/vue/.env.development
  68. 57 1
      src/main/vue/src/router.js
  69. 225 0
      src/main/vue/src/views/MetaAtomTaskEdit.vue
  70. 190 0
      src/main/vue/src/views/MetaAtomTaskList.vue
  71. 281 0
      src/main/vue/src/views/MetaStoreEdit.vue
  72. 214 0
      src/main/vue/src/views/MetaStoreList.vue
  73. 84 0
      src/main/vue/src/views/MetaStorePurchaseRecordList.vue
  74. 1 21
      src/main/vue/src/views/MetaTaskEdit.vue
  75. 0 2
      src/main/vue/src/views/MetaTaskList.vue
  76. 355 0
      src/main/vue/src/views/MetaTaskNewEdit.vue
  77. 168 0
      src/main/vue/src/views/MetaTaskNewList.vue
  78. 0 2
      src/main/vue/src/views/MetaTaskToUserList.vue
  79. 0 2
      src/main/vue/src/views/MetaUserTaskProgressList.vue
  80. 6 1
      src/main/vue/src/widgets/Detail.vue

+ 3 - 0
src/main/java/com/izouma/nineth/config/CacheConfig.java

@@ -165,6 +165,9 @@ public class CacheConfig {
         cacheNamesConfigurationMap.put("newestDomain", RedisCacheConfiguration.defaultCacheConfig()
                 .entryTtl(Duration.ofHours(3))
                 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer())));
+        cacheNamesConfigurationMap.put("newestOrder", RedisCacheConfiguration.defaultCacheConfig()
+                .entryTtl(Duration.ofMinutes(15))
+                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer())));
         RedisCacheManager redisCacheManager = RedisCacheManager.builder()
                 .cacheWriter(RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory()))
                 .withInitialCacheConfigurations(cacheNamesConfigurationMap)

+ 54 - 0
src/main/java/com/izouma/nineth/domain/MetaAtomTask.java

@@ -0,0 +1,54 @@
+package com.izouma.nineth.domain;
+
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.annotations.Searchable;
+import com.izouma.nineth.enums.MetaAwardTypeEnum;
+import com.izouma.nineth.enums.MetaTaskTarget;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙原子任务")
+public class MetaAtomTask extends BaseEntity {
+
+    @Searchable
+    @ApiModelProperty("任务名称")
+    @ExcelProperty("任务名称")
+    private String name;
+
+    @ApiModelProperty("任务详情")
+    @ExcelProperty("任务详情")
+    @Column(columnDefinition = "TEXT")
+    private String detail;
+
+    @ApiModelProperty("任务目标")
+    @ExcelProperty("任务目标")
+    @Enumerated(EnumType.STRING)
+    private MetaTaskTarget targetType;
+
+    @ApiModelProperty("目标配置")
+    @ExcelProperty("目标配置")
+    private String targetConfig;
+
+    @ApiModelProperty("奖励类型")
+    @ExcelProperty("奖励类型")
+    @Enumerated(EnumType.STRING)
+    private MetaAwardTypeEnum awardType;
+
+    @ApiModelProperty("奖励配置")
+    @ExcelProperty("奖励配置")
+    private String awardConfig;
+
+}

+ 62 - 0
src/main/java/com/izouma/nineth/domain/MetaStore.java

@@ -0,0 +1,62 @@
+package com.izouma.nineth.domain;
+
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.enums.MetaStoreCommodityType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙商店")
+public class MetaStore extends BaseEntity {
+
+    @ApiModelProperty("商品名称")
+    @ExcelProperty("商品名称")
+    private String name;
+
+    @ApiModelProperty("商品类型")
+    @ExcelProperty("商品类型")
+    @Enumerated(EnumType.STRING)
+    private MetaStoreCommodityType commodityType;
+
+    @ApiModelProperty("商品图片")
+    @ExcelProperty("商品图片")
+    private String pic;
+
+    @ApiModelProperty("商品介绍")
+    @ExcelProperty("商品介绍")
+    private String introduction;
+
+    @ApiModelProperty("金币价格")
+    @ExcelProperty("金币价格")
+    private int price;
+
+    @ApiModelProperty("道具id")
+    @ExcelProperty("道具id")
+    private Long metaPropId;
+
+    @ApiModelProperty("库存数量")
+    @ExcelProperty("库存数量")
+    private int stockNum;
+
+    @ApiModelProperty("限购数量")
+    @ExcelProperty("限购数量")
+    private int purchaseLimitNum;
+
+    @ApiModelProperty("是否上架")
+    @ExcelProperty("是否上架")
+    @Column(columnDefinition = "tinyint unsigned")
+    private boolean onShelf;
+
+    @Transient
+    private boolean canPurchase = true;
+
+}

+ 35 - 0
src/main/java/com/izouma/nineth/domain/MetaStorePurchaseRecord.java

@@ -0,0 +1,35 @@
+package com.izouma.nineth.domain;
+
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.annotations.Searchable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙商店购买记录")
+public class MetaStorePurchaseRecord extends BaseEntity {
+
+    @ApiModelProperty("商品id")
+    @ExcelProperty("商品id")
+    @Searchable
+    private Long metaStoreId;
+
+    @ApiModelProperty("用户id")
+    @ExcelProperty("用户id")
+    @Searchable
+    private Long userId;
+
+    @ApiModelProperty("购买时间")
+    @ExcelProperty("购买时间")
+    private LocalDateTime purchaseTime;
+}

+ 6 - 12
src/main/java/com/izouma/nineth/domain/MetaTask.java

@@ -5,8 +5,7 @@ import com.alibaba.excel.annotation.ExcelIgnore;
 import com.alibaba.excel.annotation.ExcelProperty;
 import com.izouma.nineth.annotations.Searchable;
 import com.izouma.nineth.enums.MetaAwardTypeEnum;
-import com.izouma.nineth.enums.MetaTaskClassification;
-import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.enums.MetaTaskTarget;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -35,12 +34,7 @@ public class MetaTask extends BaseEntity {
     @ApiModelProperty("任务类型")
     @Enumerated(EnumType.STRING)
     @ExcelProperty("任务类型")
-    private MetaTaskType type;
-
-    @ApiModelProperty("任务分类")
-    @Enumerated(EnumType.STRING)
-    @ExcelProperty("任务分类")
-    private MetaTaskClassification classification;
+    private MetaTaskTarget type;
 
     @ApiModelProperty("参数配置")
     @ExcelProperty("参数")
@@ -75,12 +69,12 @@ public class MetaTask extends BaseEntity {
     @ExcelProperty("是否自动领取")
     private boolean autoReceive;
 
-    @ApiModelProperty("道id")
-    @ExcelProperty("道id")
+    @ApiModelProperty("道id")
+    @ExcelProperty("道id")
     private Long metaPropId;
 
-    @ApiModelProperty("道id")
-    @ExcelProperty("道id")
+    @ApiModelProperty("道id")
+    @ExcelProperty("道id")
     @Searchable
     private Long channelId;
 

+ 38 - 0
src/main/java/com/izouma/nineth/domain/MetaTaskBind.java

@@ -0,0 +1,38 @@
+package com.izouma.nineth.domain;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.enums.MetaTaskType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙主线任务绑定")
+public class MetaTaskBind extends BaseEntity {
+
+    @ApiModelProperty("任务id")
+    @ExcelProperty("任务id")
+    private Long taskId;
+
+    @ApiModelProperty("原子任务id")
+    @ExcelProperty("原子任务id")
+    private Long atomTaskId;
+
+    @ApiModelProperty("原子任务下标")
+    @ExcelProperty("原子任务下标")
+    private int atomTaskIndex;
+
+    @ApiModelProperty("任务分类")
+    @ExcelProperty("任务分类")
+    @Enumerated(EnumType.STRING)
+    private MetaTaskType type;
+}

+ 63 - 0
src/main/java/com/izouma/nineth/domain/MetaTaskNew.java

@@ -0,0 +1,63 @@
+package com.izouma.nineth.domain;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.annotations.Searchable;
+import com.izouma.nineth.enums.MetaTaskType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙任务")
+public class MetaTaskNew extends BaseEntity {
+
+    @ApiModelProperty("任务名称")
+    @Searchable
+    @ExcelProperty("任务名称")
+    private String name;
+
+    @ApiModelProperty("任务详情")
+    @Column(columnDefinition = "TEXT")
+    @ExcelProperty("任务详情")
+    private String detail;
+
+    @ApiModelProperty("任务分类")
+    @ExcelProperty("任务分类")
+    @Enumerated(EnumType.STRING)
+    private MetaTaskType type;
+
+    @ApiModelProperty("是否发布")
+    @ExcelProperty("是否发布")
+    private boolean publish;
+
+    @ApiModelProperty("是否自动领取")
+    @ExcelProperty("是否自动领取")
+    private boolean autoReceive;
+
+    @Searchable
+    @ApiModelProperty("频道id")
+    @ExcelProperty("频道id")
+    private Long channelId;
+
+    @ApiModelProperty("是否结束")
+    @ExcelProperty("是否结束")
+    private boolean finish;
+
+    @Transient
+    private List<MetaTaskBind> metaNodeTask;
+
+    @Transient
+    private List<MetaTaskBind> metaBranchLineTask;
+
+    @Transient
+    private List<MetaTaskBind> metaDailyTask;
+
+}

+ 10 - 10
src/main/java/com/izouma/nineth/domain/MetaTaskToUser.java

@@ -5,7 +5,7 @@ import com.alibaba.excel.annotation.ExcelProperty;
 import com.izouma.nineth.annotations.Searchable;
 import com.izouma.nineth.enums.MetaAwardTypeEnum;
 import com.izouma.nineth.enums.MetaTaskStatus;
-import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.enums.MetaTaskTarget;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -48,7 +48,7 @@ public class MetaTaskToUser extends BaseEntity {
     @ApiModelProperty("任务类型")
     @Enumerated(EnumType.STRING)
     @ExcelProperty("任务类型")
-    private MetaTaskType taskType;
+    private MetaTaskTarget taskType;
 
     @ApiModelProperty("奖励类型")
     @ExcelProperty("奖励类型")
@@ -64,6 +64,14 @@ public class MetaTaskToUser extends BaseEntity {
     @ExcelProperty("奖励图片地址")
     private String awardPic;
 
+    @ApiModelProperty("金币奖励数量")
+    @ExcelProperty("金币奖励数量")
+    private int goldNum;
+
+    @ApiModelProperty("道具id")
+    @ExcelProperty("道具id")
+    private Long metaPropId;
+
     @ApiModelProperty("当前状态")
     @ExcelProperty("当前状态")
     @Enumerated(EnumType.STRING)
@@ -79,14 +87,6 @@ public class MetaTaskToUser extends BaseEntity {
     @ExcelIgnore
     private String process;
 
-    @ApiModelProperty("金币奖励数量")
-    @ExcelProperty("金币奖励数量")
-    private int goldNum;
-
-    @ApiModelProperty("道具id")
-    @ExcelProperty("道具id")
-    private Long metaPropId;
-
     @Transient
     private MetaProp metaProp;
 }

+ 83 - 0
src/main/java/com/izouma/nineth/domain/MetaTaskToUserNew.java

@@ -0,0 +1,83 @@
+package com.izouma.nineth.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.annotations.Searchable;
+import com.izouma.nineth.enums.MetaTaskStatus;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Transient;
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙玩家领取任务情况-新")
+public class MetaTaskToUserNew extends BaseEntity {
+
+    @Searchable
+    @ApiModelProperty("用户id")
+    @ExcelProperty("用户id")
+    private Long userId;
+
+    @ApiModelProperty("领取时间")
+    @ExcelProperty("领取时间")
+    private LocalDateTime getTime;
+
+    @ApiModelProperty("完成时间")
+    @ExcelProperty("完成时间")
+    private LocalDateTime finishTime;
+
+    @Searchable
+    @ApiModelProperty("任务id")
+    @ExcelProperty("任务id")
+    private Long taskId;
+
+    @Searchable
+    @ApiModelProperty("原子任务id")
+    @ExcelProperty("原子任务id")
+    private Long atomTaskId;
+
+    @ApiModelProperty("当前状态")
+    @ExcelProperty("当前状态")
+    @Enumerated(EnumType.STRING)
+    private MetaTaskStatus status;
+
+    @Searchable
+    @ApiModelProperty("频道id")
+    @ExcelProperty("频道id")
+    private Long channelId;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("进度")
+    private String process;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("基础任务进度")
+    private String atomTaskProcess;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("任务详情")
+    private MetaTaskNew metaTaskNew;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("原子任务详情")
+    private MetaAtomTask metaAtomTask;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("道具详情")
+    private MetaProp metaProp;
+}

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

@@ -1,7 +1,7 @@
 package com.izouma.nineth.domain;
 
 import com.alibaba.excel.annotation.ExcelProperty;
-import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.enums.MetaTaskTarget;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -17,7 +17,7 @@ import javax.persistence.Enumerated;
 @NoArgsConstructor
 @Entity
 @ApiModel("元宇宙玩家任务进度")
-public class MetaUserTaskProgress extends BaseEntity{
+public class MetaUserTaskProgress extends BaseEntity {
 
     @ApiModelProperty("元宇宙玩家领取任务记录id")
     @ExcelProperty("玩家领取任务记录id")
@@ -30,7 +30,7 @@ public class MetaUserTaskProgress extends BaseEntity{
     @ApiModelProperty("任务类型")
     @ExcelProperty("任务类型")
     @Enumerated(EnumType.STRING)
-    private MetaTaskType taskType;
+    private MetaTaskTarget taskType;
 
     @ApiModelProperty("任务名称")
     @ExcelProperty("任务名称")

+ 48 - 0
src/main/java/com/izouma/nineth/domain/MetaUserTaskProgressNew.java

@@ -0,0 +1,48 @@
+package com.izouma.nineth.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.annotations.Searchable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙玩家任务进度")
+public class MetaUserTaskProgressNew extends BaseEntity {
+
+    @Searchable
+    @ApiModelProperty("用户id")
+    @ExcelProperty("用户id")
+    private Long userId;
+
+    @ApiModelProperty("元宇宙玩家领取任务记录id")
+    @ExcelProperty("玩家领取任务记录id")
+    private Long metaTaskToUserNewId;
+
+    @ApiModelProperty("备注")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @ApiModelProperty("备注参数是否唯一,例如收集彩蛋的任务每个备注(彩蛋id)不允许重复完成")
+    @ExcelProperty("备注参数是否唯一")
+    private boolean remarkOnly;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("任务详情")
+    private MetaTaskNew metaTaskNew;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("原子任务详情")
+    private MetaAtomTask metaAtomTask;
+}

+ 2 - 5
src/main/java/com/izouma/nineth/domain/Rice.java

@@ -41,20 +41,17 @@ public class Rice extends BaseEntity {
     @ApiModelProperty("上次签到时间")
     private Long lastSignInTime;
 
-
     @ApiModelProperty("当前用户积分")
     private Long selfScore;
 
     @ApiModelProperty("当前用户活动积分")
     private Long selfActivityScore;
 
-
-
     @ApiModelProperty("经验值")
-    private Long EmpiricalValue;
+    private Long empiricalValue;
 
     @Column(name = "exchange_count", columnDefinition = "int(11) DEFAULT 0 COMMENT '今日已兑换次数'")
-    private Integer exchangeCount;
+    private Integer exchangeCount=0;
 
     @Column(name = "Invite_count", columnDefinition = "int(11) DEFAULT 0 COMMENT '今日已邀请次数'")
     private Integer InviteCount = 0;

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

@@ -18,11 +18,11 @@ import javax.persistence.Entity;
 public class RiceInvite  extends BaseEntity {
 
 
-    @ApiModelProperty("邀请人id")
-    private Long inviterId;
+    @ApiModelProperty("被助力者id")
+    private Long helpeeId;
 
-    @ApiModelProperty("被邀请人id")
-    private Long inviteeId;
+    @ApiModelProperty("助力者id")
+    private Long helperId;
 
     @ApiModelProperty("时间")
     private Long createTime;

+ 35 - 0
src/main/java/com/izouma/nineth/domain/nftdomain/Cart.java

@@ -0,0 +1,35 @@
+package com.izouma.nineth.domain.nftdomain;
+
+import com.izouma.nineth.domain.BaseEntity;
+import com.izouma.nineth.enums.CollectionType;
+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.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.math.BigDecimal;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel("系列活动")
+public class Cart extends BaseEntity {
+    private Long           userId;
+    private Long           collectionId;
+    private String         collectionName;
+    private String         pic;
+    private BigDecimal     price;
+    private boolean        enabled = false;
+    @ApiModelProperty("类型")
+    @Enumerated(EnumType.STRING)
+    @Column(length = 20)
+    private CollectionType type;
+}

+ 21 - 0
src/main/java/com/izouma/nineth/dto/MetaResourcesLikeDTO.java

@@ -0,0 +1,21 @@
+package com.izouma.nineth.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@ApiModel("资源点赞")
+public class MetaResourcesLikeDTO {
+
+    @ApiModelProperty("点赞数量")
+    private int num;
+
+    @ApiModelProperty("当日是否点赞")
+    private boolean like;
+
+}

+ 13 - 0
src/main/java/com/izouma/nineth/dto/nftdomain/DomainResult.java

@@ -0,0 +1,13 @@
+package com.izouma.nineth.dto.nftdomain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DomainResult {
+    private String domainName;
+    private String nickName;
+}

+ 19 - 0
src/main/java/com/izouma/nineth/enums/MetaStoreCommodityType.java

@@ -0,0 +1,19 @@
+package com.izouma.nineth.enums;
+
+public enum MetaStoreCommodityType {
+
+    NFT("NFT"),
+
+    META_PROP("元宇宙道具");
+
+    private final String description;
+
+    MetaStoreCommodityType(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}
+

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

@@ -1,22 +0,0 @@
-package com.izouma.nineth.enums;
-
-public enum MetaTaskClassification {
-
-    MAIN_LINE("主线任务"),
-
-    BRANCH_LINE("支线任务"),
-
-    NODE("节点任务"),
-
-    DAILY("日常任务");
-
-    private final String description;
-
-    MetaTaskClassification(String description) {
-        this.description = description;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-}

+ 21 - 0
src/main/java/com/izouma/nineth/enums/MetaTaskTarget.java

@@ -0,0 +1,21 @@
+package com.izouma.nineth.enums;
+
+
+public enum MetaTaskTarget {
+
+    COLLECT_COLLECTION("收集藏品"),
+
+    ON_LINE_TIME_DAILY("每日在线时长"),
+
+    ACCUMULATE("累计");
+
+    private final String description;
+
+    MetaTaskTarget(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 4 - 7
src/main/java/com/izouma/nineth/enums/MetaTaskType.java

@@ -1,17 +1,14 @@
 package com.izouma.nineth.enums;
 
-
 public enum MetaTaskType {
 
-//    SIGN_IN_SINGLE_DAY("单日签到"),
-//
-//    SIGN_IN_CONTINUOUS("连续多日签到"),
+    MAIN_LINE("主线任务"),
 
-    COLLECT_COLLECTION("收集藏品"),
+    NODE("节点任务"),
 
-    ON_LINE_TIME_DAILY("每日在线时长"),
+    BRANCH_LINE("支线任务"),
 
-    ACCUMULATE("累计");
+    DAILY("日常任务");
 
     private final String description;
 

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

@@ -2,6 +2,7 @@ package com.izouma.nineth.repo;
 
 import com.izouma.nineth.domain.Asset;
 import com.izouma.nineth.dto.FuAssetDTO;
+import com.izouma.nineth.dto.MetaRestResult;
 import com.izouma.nineth.enums.AssetSource;
 import com.izouma.nineth.enums.AssetStatus;
 import com.izouma.nineth.enums.CollectionType;
@@ -174,4 +175,6 @@ public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationE
     void openTrade(String name);
 
     Asset findFirstByNameAndStatus(String name, AssetStatus status);
+
+    Asset findByNameAndStatusAndCategoryAndDel(String name, AssetStatus status, String categroy,boolean del);
 }

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

@@ -0,0 +1,21 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaAtomTask;
+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 MetaAtomTaskRepo extends JpaRepository<MetaAtomTask, Long>, JpaSpecificationExecutor<MetaAtomTask> {
+    @Query("update MetaAtomTask t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    List<MetaAtomTask> findAllByDel(boolean del);
+
+    MetaAtomTask findByIdAndDel(Long id, boolean del);
+}

+ 13 - 0
src/main/java/com/izouma/nineth/repo/MetaStorePurchaseRecordRepo.java

@@ -0,0 +1,13 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaStorePurchaseRecord;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.util.List;
+
+
+public interface MetaStorePurchaseRecordRepo extends JpaRepository<MetaStorePurchaseRecord, Long>, JpaSpecificationExecutor<MetaStorePurchaseRecord> {
+
+    List<MetaStorePurchaseRecord> findAllByMetaStoreIdAndUserId(Long metaStoreId, Long userId);
+}

+ 26 - 0
src/main/java/com/izouma/nineth/repo/MetaStoreRepo.java

@@ -0,0 +1,26 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaStore;
+import com.izouma.nineth.enums.MetaStoreCommodityType;
+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 MetaStoreRepo extends JpaRepository<MetaStore, Long>, JpaSpecificationExecutor<MetaStore> {
+    @Query("update MetaStore t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    MetaStore findByCommodityTypeAndMetaPropIdAndDel(MetaStoreCommodityType commodityType, Long metaPropId, boolean del);
+
+    MetaStore findByCommodityTypeAndNameAndDel(MetaStoreCommodityType commodityType, String name, boolean del);
+
+    MetaStore findByIdAndDel(Long id, boolean del);
+
+    List<MetaStore> findAllByCommodityTypeAndOnShelfAndDel(MetaStoreCommodityType commodityType,boolean onShelf, boolean del);
+}

+ 28 - 0
src/main/java/com/izouma/nineth/repo/MetaTaskBindRepo.java

@@ -0,0 +1,28 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaTaskBind;
+import com.izouma.nineth.enums.MetaTaskType;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+
+public interface MetaTaskBindRepo extends JpaRepository<MetaTaskBind, Long>, JpaSpecificationExecutor<MetaTaskBind> {
+
+    List<MetaTaskBind> findByTaskIdAndTypeAndDel(Long taskId, MetaTaskType type, boolean del);
+
+    @Query("select m.atomTaskId from MetaTaskBind m where m.taskId = ?1 and m.type = ?2 and m.del = false order by m.atomTaskIndex asc")
+    Long findAtomTaskId(Long taskId, MetaTaskType type);
+
+    List<MetaTaskBind> findAllByTaskIdAndDel(Long taskId, boolean del);
+
+    @Query("select m.atomTaskId from MetaTaskBind m where m.taskId = ?1 and m.del = false")
+    List<Long> findAtomTaskIds(Long taskId);
+
+    MetaTaskBind findByTaskIdAndAtomTaskIdAndDel(Long taskId, Long atomTaskId, boolean del);
+
+    @Query(value = "select m.atom_task_id from meta_task_bind m where m.task_id = ?1 and m.type = 'NODE' and m.del = false and m.atom_task_index > ?2 order by m.atom_task_index asc limit 1", nativeQuery = true)
+    Long findNextAtomTaskId(Long taskId, int atomTaskIndex);
+
+}

+ 26 - 0
src/main/java/com/izouma/nineth/repo/MetaTaskNewRepo.java

@@ -0,0 +1,26 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaTaskNew;
+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 MetaTaskNewRepo extends JpaRepository<MetaTaskNew, Long>, JpaSpecificationExecutor<MetaTaskNew> {
+    @Query("update MetaTaskNew t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    MetaTaskNew findByIdAndDel(Long id, boolean del);
+
+    List<MetaTaskNew> findAllByDel(boolean del);
+
+    List<MetaTaskNew> findAllByPublishAndFinishAndDel(boolean publish, boolean finish, boolean del);
+
+    @Query(value = "select * from meta_task_new where finish = false and del = false and publish = true and channel_id = ?2 and id not in (select task_id from meta_task_to_user where user_id = ?1)", nativeQuery = true)
+    List<MetaTaskNew> canGet(Long userId, Long channelId);
+}

+ 23 - 0
src/main/java/com/izouma/nineth/repo/MetaTaskToUserNewRepo.java

@@ -0,0 +1,23 @@
+package com.izouma.nineth.repo;
+
+
+import com.izouma.nineth.domain.MetaTaskToUserNew;
+import com.izouma.nineth.enums.MetaTaskStatus;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.util.List;
+
+public interface MetaTaskToUserNewRepo extends JpaRepository<MetaTaskToUserNew, Long>, JpaSpecificationExecutor<MetaTaskToUserNew> {
+
+    MetaTaskToUserNew findByUserIdAndTaskIdAndAtomTaskIdAndDel(Long userId, Long taskId, Long atomTaskId, boolean del);
+
+    MetaTaskToUserNew findByUserIdAndTaskIdAndDel(Long userId, Long taskId, boolean del);
+
+    List<MetaTaskToUserNew> findAllByUserIdAndStatusAndDelAndAtomTaskIdIn(Long userId, MetaTaskStatus status, boolean del, List<Long> atomTaskIds);
+
+    MetaTaskToUserNew findByIdAndDel(Long id, boolean del);
+
+    List<MetaTaskToUserNew> findAllByUserIdAndChannelIdAndStatusAndDel(Long userId, Long channelId, MetaTaskStatus status, boolean del);
+
+}

+ 18 - 0
src/main/java/com/izouma/nineth/repo/MetaUserTaskProgressNewRepo.java

@@ -0,0 +1,18 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaUserTaskProgressNew;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+public interface MetaUserTaskProgressNewRepo extends JpaRepository<MetaUserTaskProgressNew, Long>, JpaSpecificationExecutor<MetaUserTaskProgressNew> {
+
+    List<MetaUserTaskProgressNew> findAllByMetaTaskToUserNewIdAndDel(Long metaTaskToUserNewId, boolean del);
+
+    MetaUserTaskProgressNew findByMetaTaskToUserNewIdAndDelAndCreatedAtAfter(Long metaTaskToUserNewId, boolean del, LocalDateTime createdAt);
+
+    MetaUserTaskProgressNew findByMetaTaskToUserNewIdAndRemarkAndDel(Long metaTaskToUserNewId, String remark, boolean del);
+
+}

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

@@ -121,4 +121,7 @@ public interface OrderRepo extends JpaRepository<Order, Long>, JpaSpecificationE
 
     @Query("select sum(totalPrice) from Order  where status = 'FINISH' and createdAt <= ?2 and createdAt >= ?1 and companyId <> 1")
     BigDecimal sumSaas(LocalDateTime start, LocalDateTime end);
+
+    @Query(nativeQuery = true, value = "select O.`name` domainName,u.nickname nickname from order_info o inner join asset a on o.asset_id = a.id inner join user u on u.id = o.user_id where o.status = 'FINISH' and (a.prefix_name = 'RID3' or prefix_name = 'RIDN3') order by o.pay_time desc LIMIT 50")
+    List<Map<String,Object>> newestDomainOrder();
 }

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

@@ -18,7 +18,13 @@ public interface RiceInviteRepo extends JpaRepository<RiceInvite, Long>, JpaSpec
 
 
 
-    Optional<RiceInvite> findByInviterIdAndInviteeId(Long inviterId, Long inviteeId);
+    Optional<RiceInvite>  findByHelperIdAndHelpeeId(Long helperId, Long helpeeId);
 
-    Optional<RiceInvite> findByInviteeId(Long inviteeId);
+    Optional<RiceInvite> findByHelpeeIdAndDelIsFalse(Long helpeeId);
+
+    Optional<RiceInvite> findByHelperIdAndHelpeeIdAndCreateTimeBetween(Long helperId, Long helpeeId, Long todayStartTime, Long todayEndTime);
+
+    Optional<RiceInvite> findByHelperIdAndCreateTimeBetween(Long helperId, Long todayStartTime, Long todayEndTime);
+
+    Optional<RiceInvite> findByHelpeeIdAndDelIsFalseAndCreateTimeBetween(Long helpeeId, Long todayStartTime, Long todayEndTime);
 }

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

@@ -33,4 +33,13 @@ public interface RiceRepo extends JpaRepository<Rice, Long>, JpaSpecificationExe
     Integer findRankByScore(@Param("score") Long score);
 
     List<Rice> findTop100ByOrderBySelfScoreDesc();
+
+    List<Rice> findByOrderBySelfScoreDesc();
+
+    /**
+     *
+     * @return
+     */
+    @Query(value = "SELECT * FROM rice r ORDER BY r.empirical_value DESC;", nativeQuery = true)
+    List<Rice> findTop100OrderByEmpiricalValueDesc();
 }

+ 20 - 0
src/main/java/com/izouma/nineth/repo/nftdomain/CartRepo.java

@@ -0,0 +1,20 @@
+package com.izouma.nineth.repo.nftdomain;
+
+import com.izouma.nineth.domain.nftdomain.Cart;
+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;
+
+public interface CartRepo extends JpaRepository<Cart, Long>, JpaSpecificationExecutor<Cart> {
+    @Query("update Cart t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    Long countAllByUserIdAndCollectionIdAndDel(Long userId, Long collectionId, boolean del);
+
+    Long countAllByUserIdAndDel(Long userId, boolean del);
+}

+ 11 - 0
src/main/java/com/izouma/nineth/service/DomainOrderService.java

@@ -11,11 +11,13 @@ import com.izouma.nineth.domain.FileObject;
 import com.izouma.nineth.domain.User;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.excel.DomainCountDTO;
+import com.izouma.nineth.dto.nftdomain.DomainResult;
 import com.izouma.nineth.enums.*;
 import com.izouma.nineth.event.OrderNotifyEvent;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.AssetRepo;
 import com.izouma.nineth.repo.DomainOrderRepo;
+import com.izouma.nineth.repo.OrderRepo;
 import com.izouma.nineth.repo.UserRepo;
 import com.izouma.nineth.service.storage.StorageService;
 import com.izouma.nineth.utils.ImageUtils;
@@ -72,6 +74,7 @@ public class DomainOrderService {
     private UserBalanceService            userBalanceService;
     private GeneralProperties             generalProperties;
     private RocketMQTemplate              rocketMQTemplate;
+    private OrderRepo                     orderRepo;
 
     public Page<DomainOrder> all(PageQuery pageQuery) {
         return domainOrderRepo
@@ -591,4 +594,12 @@ public class DomainOrderService {
         });
     }
 
+
+    public List<DomainResult> newestOrder() {
+        List<Map<String, Object>> map = orderRepo.newestDomainOrder();
+        JSONArray jsonArray = new JSONArray();
+        jsonArray.addAll(map);
+        return jsonArray.toJavaList(DomainResult.class);
+
+    }
 }

+ 20 - 0
src/main/java/com/izouma/nineth/service/MetaAtomTaskService.java

@@ -0,0 +1,20 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.MetaAtomTask;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.MetaAtomTaskRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class MetaAtomTaskService {
+
+    private MetaAtomTaskRepo metaAtomTaskRepo;
+
+    public Page<MetaAtomTask> all(PageQuery pageQuery) {
+        return metaAtomTaskRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaAtomTask.class), JpaUtils.toPageRequest(pageQuery));
+    }
+}

+ 20 - 0
src/main/java/com/izouma/nineth/service/MetaStorePurchaseRecordService.java

@@ -0,0 +1,20 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.MetaStorePurchaseRecord;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.MetaStorePurchaseRecordRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class MetaStorePurchaseRecordService {
+
+    private MetaStorePurchaseRecordRepo metaStorePurchaseRecordRepo;
+
+    public Page<MetaStorePurchaseRecord> all(PageQuery pageQuery) {
+        return metaStorePurchaseRecordRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaStorePurchaseRecord.class), JpaUtils.toPageRequest(pageQuery));
+    }
+}

+ 127 - 0
src/main/java/com/izouma/nineth/service/MetaStoreService.java

@@ -0,0 +1,127 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.annotations.RedisLock;
+import com.izouma.nineth.config.Constants;
+import com.izouma.nineth.domain.*;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaPropOperationType;
+import com.izouma.nineth.enums.MetaPropUsedType;
+import com.izouma.nineth.enums.MetaStoreCommodityType;
+import com.izouma.nineth.repo.MetaPropRepo;
+import com.izouma.nineth.repo.MetaStorePurchaseRecordRepo;
+import com.izouma.nineth.repo.MetaStoreRepo;
+import com.izouma.nineth.repo.MetaUserPropRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import lombok.AllArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Objects;
+
+@Service
+@AllArgsConstructor
+public class MetaStoreService {
+
+    private MetaStoreRepo metaStoreRepo;
+
+    private MetaPropRepo metaPropRepo;
+
+    private MetaUserPropRepo metaUserPropRepo;
+
+    private MetaUserGoldService metaUserGoldService;
+
+    private MetaUserPropRecordService metaUserPropRecordService;
+
+    private MetaStorePurchaseRecordRepo metaStorePurchaseRecordRepo;
+
+    public Page<MetaStore> all(PageQuery pageQuery) {
+        return metaStoreRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaStore.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    @Transactional
+    public MetaRestResult<Void> purchase(Long id) {
+        MetaStore metaStore = metaStoreRepo.findByIdAndDel(id, false);
+        if (Objects.isNull(metaStore)) {
+            return MetaRestResult.returnError("商品不存在");
+        }
+        if (!metaStore.isOnShelf()) {
+            return MetaRestResult.returnError("商品未上架");
+        }
+        Long userId = SecurityUtils.getAuthenticatedUser().getId();
+        if (MetaStoreCommodityType.META_PROP.equals(metaStore.getCommodityType())) {
+            return purchaseProp(metaStore, userId);
+        }
+        return purchaseNFT(metaStore, userId);
+    }
+
+    @RedisLock("#userId")
+    @Transactional
+    public MetaRestResult<Void> purchaseNFT(MetaStore metaStore, Long userId) {
+        int price = metaStore.getPrice();
+        if (0 >= metaStore.getPrice()) {
+            return MetaRestResult.returnError("购买失败,道具价格不合法");
+        }
+        if (metaStore.getStockNum() <= 0) {
+            return MetaRestResult.returnError("购买失败,库存不足");
+        }
+        // 限购
+        List<MetaStorePurchaseRecord> metaStorePurchaseRecords = metaStorePurchaseRecordRepo.findAllByMetaStoreIdAndUserId(metaStore.getId(), userId);
+        if (CollectionUtils.isNotEmpty(metaStorePurchaseRecords) && metaStorePurchaseRecords.size() >= metaStore.getPurchaseLimitNum()) {
+            return MetaRestResult.returnError(String.format("购买失败,当前商品限购[%S]个", metaStore.getPurchaseLimitNum()));
+        }
+        // 扣减金币
+        MetaRestResult<MetaUserGold> restResult = metaUserGoldService.changeNum(userId, -price, String.format("购买NFT:[%S],消耗金币[%s]", metaStore.getName(), price));
+        if (restResult.getCode() != Constants.MetaRestCode.success) {
+            return MetaRestResult.returnError(restResult.getMessage());
+        }
+        // 保存购买记录
+        metaStorePurchaseRecordRepo.save(new MetaStorePurchaseRecord(metaStore.getId(), userId, LocalDateTime.now()));
+        // 商品库存减1
+        metaStore.setStockNum(metaStore.getStockNum() - 1);
+        metaStoreRepo.save(metaStore);
+        return MetaRestResult.returnSuccess("购买成功!");
+    }
+
+    @Transactional
+    public MetaRestResult<Void> purchaseProp(MetaStore metaStore, Long userId) {
+        int price = metaStore.getPrice();
+        if (0 >= metaStore.getPrice()) {
+            return MetaRestResult.returnError("道具价格不合法");
+        }
+        MetaProp metaProp = metaPropRepo.findByIdAndDel(metaStore.getMetaPropId(), false);
+        if (Objects.isNull(metaProp)) {
+            return MetaRestResult.returnError("道具信息为空");
+        }
+        MetaUserProp dbMetaUserProp = metaUserPropRepo.findByUserIdAndMetaPropIdAndDel(userId, metaProp.getId(), false);
+        if (Objects.isNull(dbMetaUserProp)) {
+            dbMetaUserProp = MetaUserProp.create(userId, metaProp, 1);
+            MetaRestResult<MetaUserGold> restResult = metaUserGoldService.changeNum(userId, -price, String.format("购买道具:[%S],消耗金币[%s]", metaProp.getId(), price));
+            if (restResult.getCode() != Constants.MetaRestCode.success) {
+                return MetaRestResult.returnError(restResult.getMessage());
+            }
+            metaUserPropRepo.save(dbMetaUserProp);
+            metaUserPropRecordService.save(userId, metaProp, MetaPropOperationType.RECEIVE, 1);
+            metaStorePurchaseRecordRepo.save(new MetaStorePurchaseRecord(metaStore.getId(), userId, LocalDateTime.now()));
+            return MetaRestResult.returnSuccess("购买成功!");
+        }
+        if (MetaPropUsedType.PERMANENT.equals(metaProp.getUsedType()) && dbMetaUserProp.getNum() >= 1) {
+            return MetaRestResult.returnError("已拥有永久道具,不可购买");
+        }
+        MetaRestResult<MetaUserGold> restResult = metaUserGoldService.changeNum(userId, -price, String.format("购买道具:[%S],消耗金币[%s]", metaProp.getId(), price));
+        if (restResult.getCode() != Constants.MetaRestCode.success) {
+            return MetaRestResult.returnError(restResult.getMessage());
+        }
+        dbMetaUserProp.setNum(dbMetaUserProp.getNum() + 1);
+        metaUserPropRepo.save(dbMetaUserProp);
+        metaUserPropRecordService.save(userId, metaProp, MetaPropOperationType.RECEIVE, 1);
+        metaStorePurchaseRecordRepo.save(new MetaStorePurchaseRecord(metaStore.getId(), userId, LocalDateTime.now()));
+        return MetaRestResult.returnSuccess("购买成功!");
+
+    }
+}

+ 67 - 0
src/main/java/com/izouma/nineth/service/MetaTaskNewService.java

@@ -0,0 +1,67 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.MetaTaskNew;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaTaskBindRepo;
+import com.izouma.nineth.repo.MetaTaskNewRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import com.izouma.nineth.utils.ObjUtils;
+import lombok.AllArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class MetaTaskNewService {
+
+    private MetaTaskNewRepo metaTaskNewRepo;
+
+    private MetaTaskBindRepo metaTaskBindRepo;
+
+    public MetaTaskNew save(MetaTaskNew record) {
+        if (record.getId() != null) {
+            MetaTaskNew orig = metaTaskNewRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            MetaTaskNew save = metaTaskNewRepo.save(orig);
+            saveMetaTaskBind(save.getId(), record);
+            return save;
+        }
+        MetaTaskNew save = metaTaskNewRepo.save(record);
+        saveMetaTaskBind(save.getId(), record);
+        return save;
+    }
+
+    private void saveMetaTaskBind(Long taskId, MetaTaskNew record) {
+        // 节点任务
+        if (CollectionUtils.isNotEmpty(record.getMetaNodeTask())) {
+            record.getMetaNodeTask().forEach(metaTaskBind -> {
+                metaTaskBind.setTaskId(taskId);
+                metaTaskBind.setType(MetaTaskType.NODE);
+            });
+            metaTaskBindRepo.saveAll(record.getMetaNodeTask());
+        }
+        // 支线任务
+        if (CollectionUtils.isNotEmpty(record.getMetaBranchLineTask())) {
+            record.getMetaBranchLineTask().forEach(metaTaskBind -> {
+                metaTaskBind.setTaskId(taskId);
+                metaTaskBind.setType(MetaTaskType.BRANCH_LINE);
+            });
+            metaTaskBindRepo.saveAll(record.getMetaBranchLineTask());
+        }
+        // 日常任务
+        if (CollectionUtils.isNotEmpty(record.getMetaDailyTask())) {
+            record.getMetaDailyTask().forEach(metaTaskBind -> {
+                metaTaskBind.setTaskId(taskId);
+                metaTaskBind.setType(MetaTaskType.DAILY);
+            });
+            metaTaskBindRepo.saveAll(record.getMetaDailyTask());
+        }
+    }
+
+    public Page<MetaTaskNew> all(PageQuery pageQuery) {
+        return metaTaskNewRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaTaskNew.class), JpaUtils.toPageRequest(pageQuery));
+    }
+}

+ 276 - 0
src/main/java/com/izouma/nineth/service/MetaTaskToUserNewService.java

@@ -0,0 +1,276 @@
+package com.izouma.nineth.service;
+
+import com.alibaba.excel.util.CollectionUtils;
+import com.izouma.nineth.config.Constants;
+import com.izouma.nineth.domain.*;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.MetaServiceResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaAwardTypeEnum;
+import com.izouma.nineth.enums.MetaTaskStatus;
+import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.*;
+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.StringUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@Service
+@AllArgsConstructor
+@Slf4j
+public class MetaTaskToUserNewService {
+
+    private MetaTaskToUserNewRepo metaTaskToUserNewRepo;
+
+    private MetaAtomTaskRepo metaAtomTaskRepo;
+
+    private MetaTaskNewRepo metaTaskNewRepo;
+
+    private MetaPropRepo metaPropRepo;
+
+    private MetaTaskBindRepo metaTaskBindRepo;
+
+    private MetaUserTaskProgressNewRepo metaUserTaskProgressNewRepo;
+
+    private final String PREFIX = "0/";
+
+    public Page<MetaTaskToUserNew> all(PageQuery pageQuery) {
+        return metaTaskToUserNewRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaTaskToUserNew.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    @Transactional
+    public MetaRestResult<Void> autoReceiveTask() {
+        Long userId = SecurityUtils.getAuthenticatedUser().getId();
+        List<MetaTaskNew> metaTaskNews = metaTaskNewRepo.findAllByDel(false);
+        AtomicBoolean exist = new AtomicBoolean(false);
+        metaTaskNews.forEach(metaTaskNew -> {
+            MetaTaskToUserNew metaTaskToUserNew = metaTaskToUserNewRepo.findByUserIdAndTaskIdAndDel(userId, metaTaskNew.getId(), false);
+            if (Objects.isNull(metaTaskToUserNew)) {
+                exist.set(true);
+                metaTaskToUserNew = new MetaTaskToUserNew();
+                metaTaskToUserNew.setUserId(userId);
+                metaTaskToUserNew.setTaskId(metaTaskNew.getId());
+                // 设置主动领取第一个索引的基础任务
+                if (MetaTaskType.MAIN_LINE.equals(metaTaskNew.getType())) {
+                    Long atomTaskId = metaTaskBindRepo.findAtomTaskId(metaTaskNew.getId(), MetaTaskType.NODE);
+                    if (Objects.nonNull(atomTaskId)) {
+                        metaTaskToUserNew.setAtomTaskId(atomTaskId);
+                    }
+                }
+                if (MetaTaskType.BRANCH_LINE.equals(metaTaskNew.getType())) {
+                    Long atomTaskId = metaTaskBindRepo.findAtomTaskId(metaTaskNew.getId(), MetaTaskType.BRANCH_LINE);
+                    if (Objects.nonNull(atomTaskId)) {
+                        metaTaskToUserNew.setAtomTaskId(atomTaskId);
+                    }
+                }
+                if (MetaTaskType.DAILY.equals(metaTaskNew.getType())) {
+                    Long atomTaskId = metaTaskBindRepo.findAtomTaskId(metaTaskNew.getId(), MetaTaskType.DAILY);
+                    if (Objects.nonNull(atomTaskId)) {
+                        metaTaskToUserNew.setAtomTaskId(atomTaskId);
+                    }
+                }
+                MetaRestResult<MetaTaskToUserNew> result = receiveTask(metaTaskToUserNew, false);
+                if (Constants.MetaRestCode.success != result.getCode()) {
+                    throw new BusinessException(result.getMessage());
+                }
+            }
+        });
+        if (exist.get()) {
+            return MetaRestResult.returnSuccess("主动任务领取成功");
+        }
+        return MetaRestResult.returnSuccess("玩家主动领取任务已经全部领取");
+    }
+
+    @Transactional
+    public MetaRestResult<MetaTaskToUserNew> receiveTask(MetaTaskToUserNew metaTaskToUserNew, boolean progress) {
+        if (Objects.isNull(metaTaskToUserNew.getUserId())) {
+            return MetaRestResult.returnError("Illegal parameter : userId can not be null");
+        }
+        if (Objects.isNull(metaTaskToUserNew.getTaskId())) {
+            return MetaRestResult.returnError("Illegal parameter : taskId can not be null");
+        }
+        if (Objects.isNull(metaTaskToUserNew.getAtomTaskId())) {
+            return MetaRestResult.returnError("Illegal parameter : atomTaskId can not be null");
+        }
+        MetaTaskNew metaTaskNew = metaTaskNewRepo.findByIdAndDel(metaTaskToUserNew.getTaskId(), false);
+        MetaServiceResult checkMetaTaskNewResult = checkMetaTaskNew(metaTaskNew);
+        if (!checkMetaTaskNewResult.isSuccess()) {
+            return MetaRestResult.returnError(checkMetaTaskNewResult.getMessage());
+        }
+        MetaAtomTask metaAtomTask = metaAtomTaskRepo.findByIdAndDel(metaTaskToUserNew.getAtomTaskId(), false);
+        MetaServiceResult checkMetaAtomTaskResult = checkMetaAtomTask(metaAtomTask);
+        if (!checkMetaAtomTaskResult.isSuccess()) {
+            return MetaRestResult.returnError(checkMetaAtomTaskResult.getMessage());
+        }
+        // 判断当前玩家是否领取过基础任务
+        MetaTaskToUserNew dbMetaTaskToUserNew = metaTaskToUserNewRepo.findByUserIdAndTaskIdAndAtomTaskIdAndDel(metaTaskToUserNew.getUserId(), metaTaskToUserNew.getTaskId(), metaTaskToUserNew.getAtomTaskId(), false);
+        if (Objects.nonNull(dbMetaTaskToUserNew)) {
+            return MetaRestResult.returnError(String.format("当前用户已在[%S]领取过该任务", dbMetaTaskToUserNew.getGetTime()));
+        }
+        metaTaskToUserNew.setGetTime(LocalDateTime.now());
+        metaTaskToUserNew.setStatus(MetaTaskStatus.PROGRESS);
+        metaTaskToUserNew.setChannelId(metaTaskNew.getChannelId());
+        if (MetaAwardTypeEnum.META_PROP.equals(metaAtomTask.getAwardType())) {
+            MetaProp metaProp = metaPropRepo.findByIdAndDel(Long.parseLong(metaAtomTask.getAwardConfig()), false);
+            if (Objects.isNull(metaProp)) {
+                return MetaRestResult.returnError(String.format("基础任务[%S]奖励配置的道具不存在", metaTaskToUserNew.getAtomTaskId()));
+            }
+            metaTaskToUserNew.setMetaProp(metaProp);
+        }
+        metaTaskToUserNew.setMetaTaskNew(metaTaskNew);
+        metaTaskToUserNew.setMetaAtomTask(metaAtomTask);
+        MetaTaskToUserNew save = metaTaskToUserNewRepo.save(metaTaskToUserNew);
+        if (progress) {
+            setProgress(save, metaAtomTask);
+        }
+        return MetaRestResult.returnSuccess(save);
+    }
+
+    public MetaRestResult<List<MetaTaskToUserNew>> findByStatus(Long userId, Long channelId, MetaTaskStatus status) {
+        List<MetaTaskToUserNew> metaTaskToUsers = metaTaskToUserNewRepo.findAllByUserIdAndChannelIdAndStatusAndDel(userId, channelId, status, false);
+        metaTaskToUsers.forEach(this::setSingleProgress);
+        return MetaRestResult.returnSuccess(metaTaskToUsers);
+    }
+
+    public MetaRestResult<MetaTaskToUserNew> setSingleProgress(MetaTaskToUserNew metaTaskToUserNew) {
+        MetaAtomTask metaAtomTask = metaAtomTaskRepo.findByIdAndDel(metaTaskToUserNew.getAtomTaskId(), false);
+        MetaServiceResult result = checkMetaAtomTask(metaAtomTask);
+        if (!result.isSuccess()) {
+            return MetaRestResult.returnError(result.getMessage());
+        }
+        setProgress(metaTaskToUserNew, metaAtomTask);
+        return MetaRestResult.returnSuccess(metaTaskToUserNew);
+    }
+
+    /**
+     * 设置任务进度
+     *
+     * @param metaTaskToUserNew 任务领取信息
+     * @param metaAtomTask      基础任务信息
+     */
+    private void setProgress(MetaTaskToUserNew metaTaskToUserNew, MetaAtomTask metaAtomTask) {
+        List<Long> atomTaskIds = metaTaskBindRepo.findAtomTaskIds(metaTaskToUserNew.getTaskId());
+        List<MetaTaskToUserNew> completed = metaTaskToUserNewRepo.findAllByUserIdAndStatusAndDelAndAtomTaskIdIn(metaTaskToUserNew.getUserId(), MetaTaskStatus.COMPLETION, false, atomTaskIds);
+        metaTaskToUserNew.setProcess(String.valueOf(completed.size()).concat("/").concat(String.valueOf(atomTaskIds.size())));
+        String value = metaAtomTask.getTargetConfig();
+        switch (metaAtomTask.getTargetType()) {
+            case COLLECT_COLLECTION:
+                if (StringUtils.isBlank(value)) {
+                    String errMsg = "任务进度显示异常,缺少藏品id配置";
+                    log.error(errMsg);
+                    metaTaskToUserNew.setAtomTaskProcess(errMsg);
+                    break;
+                }
+                String[] split = value.split(" ");
+                List<MetaUserTaskProgressNew> collectCollection = metaUserTaskProgressNewRepo.findAllByMetaTaskToUserNewIdAndDel(metaTaskToUserNew.getId(), false);
+                if (CollectionUtils.isEmpty(collectCollection)) {
+                    metaTaskToUserNew.setAtomTaskProcess(PREFIX.concat(String.valueOf(split.length)));
+                    break;
+                }
+                metaTaskToUserNew.setAtomTaskProcess(String.valueOf(collectCollection.size()).concat("/").concat(String.valueOf(split.length)));
+                break;
+            case ON_LINE_TIME_DAILY:
+                if (StringUtils.isBlank(value)) {
+                    String errMsg = "任务进度显示异常,缺少在线时长配置";
+                    log.error(errMsg);
+                    metaTaskToUserNew.setAtomTaskProcess(errMsg);
+                    break;
+                }
+                MetaUserTaskProgressNew onLineTimeDaily = metaUserTaskProgressNewRepo.findByMetaTaskToUserNewIdAndDelAndCreatedAtAfter(metaTaskToUserNew.getId(), false, LocalDateTime.now().withHour(0).withMinute(0).withSecond(0));
+                if (Objects.isNull(onLineTimeDaily)) {
+                    metaTaskToUserNew.setAtomTaskProcess("0");
+                    break;
+                }
+                metaTaskToUserNew.setAtomTaskProcess(onLineTimeDaily.getRemark().concat("/").concat(value));
+                break;
+            case ACCUMULATE:
+                if (StringUtils.isBlank(value)) {
+                    String errMsg = "任务进度显示异常,缺少累计任务的数量配置";
+                    log.error(errMsg);
+                    metaTaskToUserNew.setAtomTaskProcess(errMsg);
+                    break;
+                }
+                List<MetaUserTaskProgressNew> accumulate = metaUserTaskProgressNewRepo.findAllByMetaTaskToUserNewIdAndDel(metaTaskToUserNew.getId(), false);
+                if (CollectionUtils.isEmpty(accumulate)) {
+                    metaTaskToUserNew.setAtomTaskProcess(PREFIX.concat(value));
+                    break;
+                }
+                metaTaskToUserNew.setAtomTaskProcess(String.valueOf(accumulate.size()).concat("/").concat(value));
+                break;
+            default:
+                String errMsg = "不存在的任务类型";
+                log.error(errMsg);
+                metaTaskToUserNew.setAtomTaskProcess(errMsg);
+                break;
+        }
+    }
+
+    /**
+     * 校验基础任务
+     *
+     * @param metaAtomTask 基础任务
+     * @return result
+     */
+    private MetaServiceResult checkMetaAtomTask(MetaAtomTask metaAtomTask) {
+        if (Objects.isNull(metaAtomTask)) {
+            return MetaServiceResult.returnError("基础任务不存在");
+        }
+        if (StringUtils.isBlank(metaAtomTask.getName())) {
+            return MetaServiceResult.returnError(String.format("基础任务[%S]缺少任务名称", metaAtomTask.getId()));
+        }
+        if (Objects.isNull(metaAtomTask.getDetail())) {
+            return MetaServiceResult.returnError(String.format("基础任务[%S]缺少任务详情", metaAtomTask.getId()));
+        }
+        if (Objects.isNull(metaAtomTask.getTargetType())) {
+            return MetaServiceResult.returnError(String.format("基础任务[%S]缺少目标", metaAtomTask.getId()));
+        }
+        if (StringUtils.isBlank(metaAtomTask.getTargetConfig())) {
+            return MetaServiceResult.returnError(String.format("基础任务[%S]缺少目标配置", metaAtomTask.getId()));
+        }
+        if (Objects.isNull(metaAtomTask.getAwardType())) {
+            return MetaServiceResult.returnError(String.format("基础任务[%S]缺少奖励类型", metaAtomTask.getId()));
+        }
+        if (StringUtils.isBlank(metaAtomTask.getAwardConfig())) {
+            return MetaServiceResult.returnError(String.format("基础任务[%S]缺少奖励配置", metaAtomTask.getId()));
+        }
+        return MetaServiceResult.returnSuccess();
+    }
+
+    /**
+     * 校验任务
+     *
+     * @param metaTaskNew 任务信息
+     * @return result
+     */
+    private MetaServiceResult checkMetaTaskNew(MetaTaskNew metaTaskNew) {
+        if (Objects.isNull(metaTaskNew)) {
+            return MetaServiceResult.returnError("任务不存在");
+        }
+        if (!metaTaskNew.isPublish()) {
+            return MetaServiceResult.returnError("status error : task has not been published");
+        }
+        if (metaTaskNew.isFinish()) {
+            return MetaServiceResult.returnError("status error : task has been finished");
+        }
+        if (StringUtils.isBlank(metaTaskNew.getName())) {
+            return MetaServiceResult.returnError(String.format("任务[%S]缺少任务名称", metaTaskNew.getId()));
+        }
+        if (Objects.isNull(metaTaskNew.getDetail())) {
+            return MetaServiceResult.returnError(String.format("任务[%S]缺少任务详情", metaTaskNew.getId()));
+        }
+        if (Objects.isNull(metaTaskNew.getType())) {
+            return MetaServiceResult.returnError(String.format("任务[%S]缺少任务类型", metaTaskNew.getId()));
+        }
+        return MetaServiceResult.returnSuccess();
+    }
+}

+ 8 - 0
src/main/java/com/izouma/nineth/service/MetaUserGoldService.java

@@ -66,6 +66,14 @@ public class MetaUserGoldService {
         }
     }
 
+    /**
+     * 操作金币
+     *
+     * @param userId 玩家id
+     * @param num    操作数量(负数代表扣减)
+     * @param remark 备注信息
+     * @return result
+     */
     @Transactional
     public MetaRestResult<MetaUserGold> changeNum(Long userId, int num, String remark) {
         MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false);

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

@@ -7,7 +7,7 @@ import com.izouma.nineth.dto.MetaAwardReceiveDTO;
 import com.izouma.nineth.dto.MetaRestResult;
 import com.izouma.nineth.dto.MetaServiceResult;
 import com.izouma.nineth.enums.MetaTaskStatus;
-import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.enums.MetaTaskTarget;
 import com.izouma.nineth.repo.MetaTaskRepo;
 import com.izouma.nineth.repo.MetaTaskToUserRepo;
 import com.izouma.nineth.repo.MetaUserTaskAwardReceivedRecordRepo;
@@ -45,13 +45,13 @@ public class MetaUserTaskAwardReceivedRecordService {
         if (MetaTaskStatus.PROGRESS.equals(metaTaskToUser.getStatus()) || MetaTaskStatus.FINISH.equals(metaTaskToUser.getStatus())) {
             return MetaRestResult.returnError(String.format("奖励领取失败:当前任务状态为[%S]", metaTaskToUser.getStatus().getDescription()));
         }
-        if (MetaTaskType.ON_LINE_TIME_DAILY.equals(metaTask.getType())) {
+        if (MetaTaskTarget.ON_LINE_TIME_DAILY.equals(metaTask.getType())) {
             MetaUserTaskAwardReceivedRecord metaUserTaskAwardReceivedRecord = metaUserTaskAwardReceivedRecordRepo.findByUserIdAndMetaTaskIdAndDelAndCreatedAtAfter(userId, metaTaskId, false, LocalDateTime.now().withHour(0).withMinute(0).withSecond(0));
             if (Objects.nonNull(metaUserTaskAwardReceivedRecord)) {
                 return MetaRestResult.returnError("奖励领取失败:用户今天已经领取过该任务奖励,不可重复领取!");
             }
         }
-        if (!MetaTaskType.ON_LINE_TIME_DAILY.equals(metaTask.getType())) {
+        if (!MetaTaskTarget.ON_LINE_TIME_DAILY.equals(metaTask.getType())) {
             MetaUserTaskAwardReceivedRecord metaUserTaskAwardReceivedRecord = metaUserTaskAwardReceivedRecordRepo.findByUserIdAndMetaTaskIdAndDel(userId, metaTaskId, false);
             if (Objects.nonNull(metaUserTaskAwardReceivedRecord)) {
                 return MetaRestResult.returnError("奖励领取失败:用户已经领取过该任务奖励,不可重复领取!");

+ 181 - 0
src/main/java/com/izouma/nineth/service/MetaUserTaskProgressNewService.java

@@ -0,0 +1,181 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.*;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.MetaServiceResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaTaskStatus;
+import com.izouma.nineth.enums.MetaTaskTarget;
+import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.*;
+import com.izouma.nineth.utils.JpaUtils;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@Service
+@AllArgsConstructor
+public class MetaUserTaskProgressNewService {
+
+    private MetaUserTaskProgressNewRepo metaUserTaskProgressNewRepo;
+
+    private MetaTaskToUserNewRepo metaTaskToUserNewRepo;
+
+    private MetaAtomTaskRepo metaAtomTaskRepo;
+
+    private MetaTaskToUserNewService metaTaskToUserNewService;
+
+    private MetaTaskBindRepo metaTaskBindRepo;
+
+    public Page<MetaUserTaskProgressNew> all(PageQuery pageQuery) {
+        return metaUserTaskProgressNewRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaUserTaskProgressNew.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    @Transactional
+    public MetaRestResult<Boolean> metaSave(MetaUserTaskProgressNew metaUserTaskProgressNew) {
+        // 校验参数
+        MetaServiceResult result = checkParams(metaUserTaskProgressNew);
+        if (!result.isSuccess()) {
+            return MetaRestResult.returnError(result.getMessage());
+        }
+        // 任务领取记录
+        MetaTaskToUserNew metaTaskToUserNew = metaTaskToUserNewRepo.findByIdAndDel(metaUserTaskProgressNew.getMetaTaskToUserNewId(), false);
+        if (Objects.isNull(metaTaskToUserNew)) {
+            return MetaRestResult.returnError("无用户领取任务记录");
+        }
+        if (!metaTaskToUserNew.getStatus().equals(MetaTaskStatus.PROGRESS)) {
+            return MetaRestResult.returnError(String.format("状态错误:当前任务状态为[%S]", metaTaskToUserNew.getStatus().getDescription()));
+        }
+        // 基础任务
+        MetaAtomTask metaAtomTask = metaAtomTaskRepo.findByIdAndDel(metaTaskToUserNew.getAtomTaskId(), false);
+        if (Objects.isNull(metaAtomTask)) {
+            return MetaRestResult.returnError("基础任务信息为空");
+        }
+        // 收集藏品类型任务 remark为藏品id 不可为空
+        if (metaAtomTask.getTargetType().equals(MetaTaskTarget.COLLECT_COLLECTION)) {
+            if (StringUtils.isBlank(metaUserTaskProgressNew.getRemark())) {
+                return MetaRestResult.returnError(String.format("类型[%S]的任务 remark不可为空", metaAtomTask.getTargetType().getDescription()));
+            }
+        }
+        String value = metaAtomTask.getTargetConfig();
+        // 收集藏品任务
+        if (metaAtomTask.getTargetType().equals(MetaTaskTarget.COLLECT_COLLECTION)) {
+            if (StringUtils.isBlank(value)) {
+                return MetaRestResult.returnError("该任务未配置藏品id");
+            }
+            String[] split = value.split(" ");
+            List<String> all = Arrays.asList(split);
+            if (!all.contains(metaUserTaskProgressNew.getRemark())) {
+                return MetaRestResult.returnError("不在任务规定藏品内");
+            }
+        }
+        // 累计任务
+        if (metaAtomTask.getTargetType().equals(MetaTaskTarget.ACCUMULATE)) {
+            if (StringUtils.isBlank(value)) {
+                return MetaRestResult.returnError("该任务未配置达标次数");
+            }
+        }
+        // 在线时长任务 如记录存在则更新remark(每日在线时长) 如不存在则每日首次触发该任务
+        if (metaAtomTask.getTargetType().equals(MetaTaskTarget.ON_LINE_TIME_DAILY)) {
+            MetaUserTaskProgressNew dbMetaUserTaskProgressNew = metaUserTaskProgressNewRepo.findByMetaTaskToUserNewIdAndDelAndCreatedAtAfter(metaUserTaskProgressNew.getMetaTaskToUserNewId(), false, LocalDateTime.now().withHour(0).withMinute(0).withSecond(0));
+            if (Objects.isNull(dbMetaUserTaskProgressNew)) {
+                metaUserTaskProgressNewRepo.save(metaUserTaskProgressNew);
+                // 该类型任务不存在完成
+                return MetaRestResult.returnSuccess(false);
+            }
+            int remark = Integer.parseInt(metaUserTaskProgressNew.getRemark()) + Integer.parseInt(dbMetaUserTaskProgressNew.getRemark());
+            dbMetaUserTaskProgressNew.setRemark(String.valueOf(remark));
+            metaUserTaskProgressNewRepo.save(dbMetaUserTaskProgressNew);
+            return MetaRestResult.returnSuccess(false);
+        }
+        // 保存进度
+        metaUserTaskProgressNewRepo.save(metaUserTaskProgressNew);
+        List<MetaUserTaskProgressNew> metaUserTaskProgressNews = metaUserTaskProgressNewRepo.findAllByMetaTaskToUserNewIdAndDel(metaUserTaskProgressNew.getMetaTaskToUserNewId(), false);
+        // 是否完成任务
+        switch (metaAtomTask.getTargetType()) {
+            case COLLECT_COLLECTION:
+                String[] split = value.split(" ");
+                List<String> all = Arrays.asList(split);
+                List<String> completed = metaUserTaskProgressNews.stream().map(MetaUserTaskProgressNew::getRemark).collect(Collectors.toList());
+                if (new HashSet<>(completed).containsAll(all)) {
+                    completeTask(metaTaskToUserNew);
+                    return MetaRestResult.returnSuccess(true);
+                }
+                return MetaRestResult.returnSuccess(false);
+            case ACCUMULATE:
+                if (metaUserTaskProgressNews.size() >= Integer.parseInt(value)) {
+                    completeTask(metaTaskToUserNew);
+                    return MetaRestResult.returnSuccess(true);
+                }
+                return MetaRestResult.returnSuccess(false);
+            default:
+                throw new BusinessException(String.format("不存在的任务类型[%S]", metaAtomTask.getTargetType()));
+        }
+    }
+
+
+    /**
+     * 完成任务
+     *
+     * @param metaTaskToUserNew 任务领取记录
+     */
+    private void completeTask(MetaTaskToUserNew metaTaskToUserNew) {
+        metaTaskToUserNew.setFinishTime(LocalDateTime.now());
+        metaTaskToUserNew.setStatus(MetaTaskStatus.COMPLETION);
+        metaTaskToUserNewRepo.save(metaTaskToUserNew);
+        MetaTaskBind metaTaskBind = metaTaskBindRepo.findByTaskIdAndAtomTaskIdAndDel(metaTaskToUserNew.getTaskId(), metaTaskToUserNew.getAtomTaskId(), false);
+        // 节点任务完成自动领取下一个节点任务
+        if (MetaTaskType.NODE.equals(metaTaskBind.getType())) {
+            // 下一个节点任务id
+            Long nextAtomTaskId = metaTaskBindRepo.findNextAtomTaskId(metaTaskToUserNew.getTaskId(), metaTaskBind.getAtomTaskIndex());
+            if (Objects.isNull(nextAtomTaskId)) {
+                return;
+            }
+            MetaTaskToUserNew next = new MetaTaskToUserNew();
+            next.setTaskId(metaTaskToUserNew.getTaskId());
+            next.setAtomTaskId(nextAtomTaskId);
+            next.setUserId(metaTaskToUserNew.getUserId());
+            metaTaskToUserNewService.receiveTask(next, true);
+        }
+
+    }
+
+    /**
+     * 参数校验
+     *
+     * @param metaUserTaskProgressNew 待校验参数
+     * @return 校验结果
+     */
+    private MetaServiceResult checkParams(MetaUserTaskProgressNew metaUserTaskProgressNew) {
+        if (Objects.nonNull(metaUserTaskProgressNew.getId())) {
+            return MetaServiceResult.returnError("Illegal parameter : id must be null");
+        }
+        if (Objects.isNull(metaUserTaskProgressNew.getMetaTaskToUserNewId())) {
+            return MetaServiceResult.returnError("Illegal parameter : metaTaskToUserNewId can not be null");
+        }
+        if (Objects.isNull(metaUserTaskProgressNew.getUserId())) {
+            return MetaServiceResult.returnError("Illegal parameter : userId can not be null");
+        }
+        // 指定备注唯一,校验是否重复
+        if (metaUserTaskProgressNew.isRemarkOnly()) {
+            if (StringUtils.isBlank(metaUserTaskProgressNew.getRemark())) {
+                return MetaServiceResult.returnError("Illegal parameter : remark can not be null");
+            }
+            MetaUserTaskProgressNew dbMetaUserTaskProgressNew = metaUserTaskProgressNewRepo.findByMetaTaskToUserNewIdAndRemarkAndDel(metaUserTaskProgressNew.getMetaTaskToUserNewId(), metaUserTaskProgressNew.getRemark(), false);
+            if (Objects.nonNull(dbMetaUserTaskProgressNew)) {
+                return MetaServiceResult.returnError("重复触发");
+            }
+        }
+        return MetaServiceResult.returnSuccess();
+    }
+}

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

@@ -6,7 +6,7 @@ import com.izouma.nineth.domain.MetaUserTaskProgress;
 import com.izouma.nineth.dto.MetaRestResult;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.enums.MetaTaskStatus;
-import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.enums.MetaTaskTarget;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.MetaTaskRepo;
 import com.izouma.nineth.repo.MetaTaskToUserRepo;
@@ -69,7 +69,7 @@ public class MetaUserTaskProgressService {
             return MetaRestResult.returnError(String.format("状态错误:当前任务状态为[%S]", metaTaskToUser.getStatus().getDescription()));
         }
         // 收集藏品类型任务 remark为藏品id 不可为空
-        if (metaTaskToUser.getTaskType().equals(MetaTaskType.COLLECT_COLLECTION)) {
+        if (metaTaskToUser.getTaskType().equals(MetaTaskTarget.COLLECT_COLLECTION)) {
             if (StringUtils.isBlank(metaUserTaskProgress.getRemark())) {
                 return MetaRestResult.returnError(String.format("类型[%S]的任务状态 remark不可为空", metaTaskToUser.getTaskType().getDescription()));
             }
@@ -77,7 +77,7 @@ public class MetaUserTaskProgressService {
         MetaTask metaTask = metaTaskRepo.findByIdAndDel(metaTaskToUser.getTaskId(), false);
         String value = metaTask.getValue();
         // 收集藏品任务
-        if (metaTaskToUser.getTaskType().equals(MetaTaskType.COLLECT_COLLECTION)) {
+        if (metaTaskToUser.getTaskType().equals(MetaTaskTarget.COLLECT_COLLECTION)) {
             if (StringUtils.isBlank(value)) {
                 return MetaRestResult.returnError("该任务未配置藏品id");
             }
@@ -88,7 +88,7 @@ public class MetaUserTaskProgressService {
             }
         }
         // 累计任务
-        if (metaTaskToUser.getTaskType().equals(MetaTaskType.ACCUMULATE)) {
+        if (metaTaskToUser.getTaskType().equals(MetaTaskTarget.ACCUMULATE)) {
             if (StringUtils.isBlank(value)) {
                 return MetaRestResult.returnError("该任务未配置达标次数");
             }
@@ -109,7 +109,7 @@ public class MetaUserTaskProgressService {
 //            }
 //        }
         // 在线时长任务 如记录存在则更新remark(每日在线时长) 如不存在则每日首次触发该任务
-        if (metaTaskToUser.getTaskType().equals(MetaTaskType.ON_LINE_TIME_DAILY)) {
+        if (metaTaskToUser.getTaskType().equals(MetaTaskTarget.ON_LINE_TIME_DAILY)) {
             MetaUserTaskProgress dbMetaUserTaskProgress = metaUserTaskProgressRepo.findByMetaTaskToUserIdAndDelAndCreatedAtAfter(metaTaskToUser.getId(), false, LocalDateTime.now().withHour(0).withMinute(0).withSecond(0));
             if (Objects.isNull(dbMetaUserTaskProgress)) {
                 save(metaUserTaskProgress, metaTaskToUser);

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

@@ -1,5 +1,6 @@
 package com.izouma.nineth.service;
 
+import com.alipay.mychain.sdk.vm.abi.datatype.Int;
 import com.izouma.nineth.domain.Rice;
 import com.izouma.nineth.domain.RiceOperationRecord;
 import com.izouma.nineth.domain.RiceUserWaterDropRecord;
@@ -23,6 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 
 import javax.json.Json;
 import javax.json.JsonArray;
@@ -73,6 +76,7 @@ public class RiceService {
             rice.setWaterDropCount(0L);
             rice.setSignCount(0L);
             rice.setSelfScore(0L);
+            rice.setSelfActivityScore(0L);
             rice.setEmpiricalValue(0L);
             riceRepo.save(rice);
             return rice;
@@ -208,7 +212,7 @@ public class RiceService {
 
 
     public List<RiceDTO> getTop100(Long userId) {
-        List<Rice> top100Rices = riceRepo.findTop100ByOrderBySelfScoreDesc();
+        List<Rice> top100Rices = riceRepo.findTop100OrderByEmpiricalValueDesc();
         List<RiceDTO> result = new ArrayList<>();
 
         // 计算自己的排名
@@ -247,6 +251,61 @@ public class RiceService {
         return result;
     }
 
+
+    //计算自己排名
+    public R<RiceDTO> getRiceUserRank(Long userId) {
+        Optional<Rice> rice1 = riceRepo.findByUserId(userId);
+        if (!rice1.isPresent()) {
+            return R.error("用户不存在");
+        }
+        List<Rice> top100Rices = riceRepo.findByOrderBySelfScoreDesc();
+        List<RiceDTO> result = new ArrayList<>();
+        RiceDTO dto = new RiceDTO();
+        // 计算自己的排名
+        int selfRank = 0;
+        for (int i = 0; i < top100Rices.size(); i++) {
+            if (top100Rices.get(i).getUserId().equals(userId)) {
+                selfRank = i + 1;
+                break;
+            }
+        }
+
+        for (int i = 0; i < top100Rices.size(); i++) {
+            Rice rice = top100Rices.get(i);
+            RiceDTO riceDTO = new RiceDTO();
+            BeanUtils.copyProperties(rice, riceDTO);
+            riceDTO.setScoreRank(i + 1);
+            // 判断是否上榜
+            if (i < 100) {
+                riceDTO.setOnTop100(true);
+            } else {
+                riceDTO.setOnTop100(false);
+            }
+            // 如果是自己,则设置自己的头像、昵称、等级和离上榜还差多少名
+            if (rice.getUserId().equals(userId)) {
+                riceDTO.setAvatar(rice.getAvatar());
+                riceDTO.setNickname(rice.getNickname());
+                riceDTO.setLevel(rice.getLevel());
+                if (i < 100) {
+                    riceDTO.setRankGap(0);
+                } else {
+                    riceDTO.setRankGap(i + 1 - 100);
+                }
+
+                BeanUtils.copyProperties(riceDTO, dto);
+
+
+            }
+
+        }
+
+        if (dto == null) {
+            return R.error("用户不存在");
+        }
+
+        return R.success(dto);
+    }
+
     //浇水
     public R<? extends Object> watering() {
         // 获取当前用户 ID,
@@ -368,6 +427,9 @@ public class RiceService {
             int maxExchangeCount = 10;
 
             // 计算当前可兑换的次数和消耗的积分
+            if(rice.getExchangeCount()==null){
+               rice.setExchangeCount(0);
+            }
             int exchangeCount = Math.min((int) (selfScore / exchangeScore), maxExchangeCount-rice.getExchangeCount());
             int totalScore = exchangeCount * exchangeScore;
 
@@ -400,4 +462,37 @@ public class RiceService {
     }
 
 
+    //活动积分兑换水滴,无上限.
+    public R<?> exchangeActivityScoreForWaterDrop(User authenticatedUser) {
+
+
+            // 检查用户活动积分是否足够
+            Optional<Rice> optionalRice = riceRepo.findById(authenticatedUser.getId());
+            if (!optionalRice.isPresent()) {
+                return R.error("未找到用户信息");
+            }
+            Rice rice = optionalRice.get();
+            Long currentActivityPoints = rice.getSelfActivityScore();
+        Long beforeWaterDropCount = rice.getWaterDropCount();
+
+        // 计算兑换的水滴数量
+        Long exchangedWaterDropCount = (long) Math.floor(currentActivityPoints / 2.0);
+        if (exchangedWaterDropCount <= 0) {
+                return R.error("活动积分不足以兑换水滴").add("times",exchangedWaterDropCount);
+            }
+
+            // 更新用户活动积分和水滴数
+            rice.setSelfActivityScore(currentActivityPoints - (Long) exchangedWaterDropCount*2);
+            rice.setWaterDropCount(rice.getWaterDropCount() + exchangedWaterDropCount);
+            riceRepo.save(rice);
+
+            // 记录水滴操作记录
+            createRiceOperationRecord(authenticatedUser.getId(), RiceOperationType.WATER_DROP, exchangedWaterDropCount, beforeWaterDropCount, rice.getWaterDropCount());
+            createRiceOperationRecord(authenticatedUser.getId(), RiceOperationType.SELF_ACTIVITY_SCORE, (Long) exchangedWaterDropCount*2, currentActivityPoints, rice.getSelfActivityScore());
+
+            return R.success("兑换成功").add("times", exchangedWaterDropCount);
+
+
+
+    }
 }

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

@@ -402,11 +402,11 @@ public class StatisticService {
         LocalDateTime lastStart = LocalDate.now().atStartOfDay().minusDays(1);
         LocalDateTime lastEnd = LocalDate.now().atTime(LocalTime.MAX).minusDays(1);
         Map<String, Object> last = statisticDetail(lastStart, lastEnd);
-        result.put("last", last);
+        result.put("yesterday", last);
         LocalDateTime yesterStart = LocalDate.now().atStartOfDay().minusDays(2);
         LocalDateTime yesterEnd = LocalDate.now().atTime(LocalTime.MAX).minusDays(2);
         Map<String, Object> yesterday = statisticDetail(yesterStart, yesterEnd);
-        result.put("yesterday", yesterday);
+        result.put("last", yesterday);
         return result;
     }
 

+ 59 - 0
src/main/java/com/izouma/nineth/service/nftdomain/CartService.java

@@ -0,0 +1,59 @@
+package com.izouma.nineth.service.nftdomain;
+
+import com.alibaba.druid.sql.visitor.functions.If;
+import com.izouma.nineth.domain.Collection;
+import com.izouma.nineth.domain.nftdomain.Cart;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.CollectionRepo;
+import com.izouma.nineth.repo.nftdomain.CartRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+@AllArgsConstructor
+public class CartService {
+
+    private CartRepo       cartRepo;
+    private CollectionRepo collectionRepo;
+
+    public Page<Cart> all(PageQuery pageQuery) {
+        return cartRepo.findAll(JpaUtils.toSpecification(pageQuery, Cart.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    public Cart create(Long collectionId) {
+        Long userId = SecurityUtils.getAuthenticatedUser().getId();
+        if (inCart(collectionId, userId)) {
+            throw new BusinessException("已经加入购物车");
+        }
+        Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("未找到该藏品"));
+        Cart cart = new Cart();
+        cart.setEnabled(true);
+        cart.setUserId(userId);
+        cart.setCollectionName(collection.getName());
+        cart.setPrice(collection.getPrice());
+        cart.setPic(collection.getPic().get(1).getUrl());
+        cart.setCollectionId(collectionId);
+        cart.setType(collection.getType());
+        return cartRepo.save(cart);
+    }
+
+    public boolean inCart(Long collectionId, Long userId) {
+        return cartRepo.countAllByUserIdAndCollectionIdAndDel(userId, collectionId, false) > 0;
+    }
+
+    public Map<String, Object> collectionCartStatus(Long collectionId) {
+        Long userId = SecurityUtils.getAuthenticatedUser().getId();
+        Long count = cartRepo.countAllByUserIdAndDel(userId, false);
+        Map<String, Object> result = new HashMap<>();
+        result.put("count", count);
+        result.put("inCart", inCart(collectionId, userId));
+        return result;
+    }
+}

+ 43 - 0
src/main/java/com/izouma/nineth/utils/MetaTaskTargetConverter.java

@@ -0,0 +1,43 @@
+package com.izouma.nineth.utils;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import com.izouma.nineth.enums.MetaTaskTarget;
+
+public class MetaTaskTargetConverter implements Converter<MetaTaskTarget> {
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaTaskTarget.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaTaskTarget convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaTaskTarget value : MetaTaskTarget.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaTaskTarget value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}
+

+ 1 - 0
src/main/java/com/izouma/nineth/utils/excel/ExcelUtils.java

@@ -23,6 +23,7 @@ public class ExcelUtils<T> {
                 .registerConverter(new OrderStatusConverter())
                 .registerConverter(new PayMethodConverter())
                 .registerConverter(new MetaTaskTypeConverter())
+                .registerConverter(new MetaTaskTypeConverter())
                 .registerConverter(new MetaTaskStatusConverter())
                 .registerConverter(new CoordinateDTOConverter())
                 .registerConverter(new EntryModelTypeConverter())

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

@@ -8,6 +8,7 @@ import com.izouma.nineth.domain.Asset;
 import com.izouma.nineth.domain.DomainOrder;
 import com.izouma.nineth.domain.GiftOrder;
 import com.izouma.nineth.dto.*;
+import com.izouma.nineth.enums.AssetStatus;
 import com.izouma.nineth.enums.CollectionType;
 import com.izouma.nineth.enums.OperationSource;
 import com.izouma.nineth.enums.OrderStatus;
@@ -310,6 +311,15 @@ public class AssetController extends BaseController {
         assetRepo.openTrade(name);
         collectionRepo.openTrade(name);
     }
+
+    @GetMapping("/getId/{name}")
+    public MetaRestResult<Long> getId(@PathVariable String name) {
+        Asset asset = assetRepo.findByNameAndStatusAndCategoryAndDel("RID元宇宙域名 ".concat(name).concat(".nft"), AssetStatus.NORMAL,"元域名",false);
+        if (Objects.isNull(asset)) {
+            return MetaRestResult.returnError("该域名不存在");
+        }
+        return MetaRestResult.returnSuccess("查询成功", asset.getUserId());
+    }
 }
 
 

+ 9 - 2
src/main/java/com/izouma/nineth/web/DomainOrderController.java

@@ -2,6 +2,7 @@ package com.izouma.nineth.web;
 
 import com.izouma.nineth.domain.DomainOrder;
 import com.izouma.nineth.dto.excel.DomainCountDTO;
+import com.izouma.nineth.dto.nftdomain.DomainResult;
 import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.service.DomainOrderService;
 import com.izouma.nineth.dto.PageQuery;
@@ -87,13 +88,19 @@ public class DomainOrderController extends BaseController {
     @PostMapping("/pass")
     @PreAuthorize("hasRole('ADMIN')")
     public void pass(Long id) {
-         domainOrderService.pass(id);
+        domainOrderService.pass(id);
     }
 
     @PostMapping("/deny")
     @PreAuthorize("hasRole('ADMIN')")
     public void deny(Long id) {
-        domainOrderService.deny(id,"系统审核不通过");
+        domainOrderService.deny(id, "系统审核不通过");
+    }
+
+    @PostMapping("/newestOrder")
+    @Cacheable(value = "newestOrder")
+    public List<DomainResult> newestOrder() {
+        return domainOrderService.newestOrder();
     }
 }
 

+ 65 - 0
src/main/java/com/izouma/nineth/web/MetaAtomTaskController.java

@@ -0,0 +1,65 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaAtomTask;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaAtomTaskRepo;
+import com.izouma.nineth.service.MetaAtomTaskService;
+import com.izouma.nineth.utils.ObjUtils;
+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("/metaAtomTask")
+@AllArgsConstructor
+public class MetaAtomTaskController extends BaseController {
+    private MetaAtomTaskService metaAtomTaskService;
+    private MetaAtomTaskRepo metaAtomTaskRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public MetaAtomTask save(@RequestBody MetaAtomTask record) {
+        if (record.getId() != null) {
+            MetaAtomTask orig = metaAtomTaskRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return metaAtomTaskRepo.save(orig);
+        }
+        return metaAtomTaskRepo.save(record);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<MetaAtomTask> all(@RequestBody PageQuery pageQuery) {
+        return metaAtomTaskService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public MetaAtomTask get(@PathVariable Long id) {
+        return metaAtomTaskRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        metaAtomTaskRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaAtomTask> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @GetMapping("/findAll")
+    public List<MetaAtomTask> findAll() {
+        return metaAtomTaskRepo.findAllByDel(false);
+    }
+}
+

+ 20 - 0
src/main/java/com/izouma/nineth/web/MetaResourcesController.java

@@ -2,6 +2,7 @@ package com.izouma.nineth.web;
 
 import com.izouma.nineth.domain.MetaResources;
 import com.izouma.nineth.domain.MetaResourcesLikeRecord;
+import com.izouma.nineth.dto.MetaResourcesLikeDTO;
 import com.izouma.nineth.dto.MetaRestResult;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.exception.BusinessException;
@@ -104,5 +105,24 @@ public class MetaResourcesController extends BaseController {
         metaResourcesRepo.save(metaResources);
         return MetaRestResult.returnSuccess(metaResources.getLikeNum());
     }
+
+
+    @GetMapping("/getLikeNum/{id}/{userId}")
+    public MetaRestResult<MetaResourcesLikeDTO> getLikeNum(@PathVariable Long id, @PathVariable Long userId) {
+        MetaResourcesLikeDTO metaResourcesLikeDTO = new MetaResourcesLikeDTO();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateTimeUtils.DATE_FORMAT);
+        LocalDate likeTime = LocalDate.parse(LocalDate.now().format(formatter), formatter);
+        MetaResourcesLikeRecord metaResourcesLikeRecord = metaResourcesLikeRecordRepo.findByMetaResourcesIdAndUserIdAndLikeTime(id,userId,likeTime);
+        if (Objects.nonNull(metaResourcesLikeRecord)) {
+            metaResourcesLikeDTO.setLike(true);
+        }
+        MetaResources metaResources = metaResourcesRepo.findById(id).orElse(null);
+        if (Objects.isNull(metaResources)) {
+            return MetaRestResult.returnError("当前资源不存在!");
+        }
+        metaResourcesLikeDTO.setNum(metaResources.getLikeNum());
+        metaResourcesLikeDTO.setLike(false);
+        return MetaRestResult.returnSuccess(metaResourcesLikeDTO);
+    }
 }
 

+ 135 - 0
src/main/java/com/izouma/nineth/web/MetaStoreController.java

@@ -0,0 +1,135 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaStore;
+import com.izouma.nineth.domain.MetaUserProp;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaPropUsedType;
+import com.izouma.nineth.enums.MetaStoreCommodityType;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaStoreRepo;
+import com.izouma.nineth.repo.MetaUserPropRepo;
+import com.izouma.nineth.service.MetaStoreService;
+import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
+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;
+import java.util.Objects;
+
+@RestController
+@RequestMapping("/metaStore")
+@AllArgsConstructor
+public class MetaStoreController extends BaseController {
+
+    private MetaStoreService metaStoreService;
+
+    private MetaStoreRepo metaStoreRepo;
+
+    private MetaUserPropRepo metaUserPropRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public MetaStore save(@RequestBody MetaStore record) {
+        if (Objects.isNull(record.getId())) {
+            if (MetaStoreCommodityType.META_PROP.equals(record.getCommodityType()) && !checkMetaProp(record.getMetaPropId())) {
+                throw new BusinessException("商店中已经存在该道具");
+            }
+            if (MetaStoreCommodityType.NFT.equals(record.getCommodityType())) {
+                MetaStore metaStore = metaStoreRepo.findByCommodityTypeAndNameAndDel(MetaStoreCommodityType.NFT, record.getName(), false);
+                if (Objects.nonNull(metaStore)) {
+                    throw new BusinessException("商店中已经存在该NFT");
+                }
+            }
+            return metaStoreRepo.save(record);
+        }
+        MetaStore orig = metaStoreRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+        ObjUtils.merge(orig, record);
+        return metaStoreRepo.save(orig);
+    }
+
+    @PostMapping("/{id}/onShelf")
+    public void onShelf(@PathVariable Long id) {
+        MetaStore metaStore = metaStoreRepo.findByIdAndDel(id, false);
+        if (Objects.isNull(metaStore)) {
+            throw new BusinessException("无记录");
+        }
+        if (metaStore.isOnShelf()) {
+            throw new BusinessException("当前商品已经处于上架状态!");
+        }
+        metaStore.setOnShelf(true);
+        metaStoreRepo.save(metaStore);
+    }
+
+    @PostMapping("/{id}/cancelOnShelf")
+    public void cancelOnShelf(@PathVariable Long id) {
+        MetaStore metaStore = metaStoreRepo.findByIdAndDel(id, false);
+        if (Objects.isNull(metaStore)) {
+            throw new BusinessException("无记录");
+        }
+        if (!metaStore.isOnShelf()) {
+            throw new BusinessException("当前商品已经处于下架状态!");
+        }
+        metaStore.setOnShelf(false);
+        metaStoreRepo.save(metaStore);
+    }
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<MetaStore> all(@RequestBody PageQuery pageQuery) {
+        return metaStoreService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public MetaStore get(@PathVariable Long id) {
+        return metaStoreRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        metaStoreRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaStore> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @GetMapping("/{metaPropId}/checkMetaProp")
+    public boolean checkMetaProp(@PathVariable Long metaPropId) {
+        MetaStore metaStore = metaStoreRepo.findByCommodityTypeAndMetaPropIdAndDel(MetaStoreCommodityType.META_PROP, metaPropId, false);
+        return Objects.isNull(metaStore);
+    }
+
+    @PostMapping("/{id}/purchase")
+    public MetaRestResult<Void> purchase(@PathVariable Long id) {
+        return metaStoreService.purchase(id);
+    }
+
+    @GetMapping("findByType")
+    public MetaRestResult<List<MetaStore>> findByType(MetaStoreCommodityType commodityType) {
+        List<MetaStore> metaStores = metaStoreRepo.findAllByCommodityTypeAndOnShelfAndDel(commodityType, true, false);
+        if (CollectionUtils.isEmpty(metaStores)) {
+            return MetaRestResult.returnSuccess(metaStores);
+        }
+        if (MetaStoreCommodityType.META_PROP.equals(commodityType)) {
+            Long userId = SecurityUtils.getAuthenticatedUser().getId();
+            metaStores.forEach(metaStore -> {
+                MetaUserProp metaUserProp = metaUserPropRepo.findByUserIdAndMetaPropIdAndDel(userId, metaStore.getMetaPropId(), false);
+                if (Objects.nonNull(metaUserProp) && MetaPropUsedType.PERMANENT.equals(metaUserProp.getUsedType()) && metaUserProp.getNum() >= 1) {
+                    metaStore.setCanPurchase(false);
+                }
+            });
+        }
+        return MetaRestResult.returnSuccess(metaStores);
+    }
+}
+

+ 33 - 0
src/main/java/com/izouma/nineth/web/MetaStorePurchaseRecordController.java

@@ -0,0 +1,33 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaStorePurchaseRecord;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.service.MetaStorePurchaseRecordService;
+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("/metaStorePurchaseRecord")
+@AllArgsConstructor
+public class MetaStorePurchaseRecordController extends BaseController {
+
+    private MetaStorePurchaseRecordService metaStorePurchaseRecordService;
+
+    @PostMapping("/all")
+    public Page<MetaStorePurchaseRecord> all(@RequestBody PageQuery pageQuery) {
+        return metaStorePurchaseRecordService.all(pageQuery);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaStorePurchaseRecord> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}

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

@@ -6,7 +6,7 @@ import com.izouma.nineth.domain.MetaTask;
 import com.izouma.nineth.dto.MetaRestResult;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.enums.MetaAwardTypeEnum;
-import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.enums.MetaTaskTarget;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.CollectionRepo;
 import com.izouma.nineth.repo.MetaPropRepo;
@@ -42,7 +42,7 @@ public class MetaTaskController extends BaseController {
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
     public MetaTask save(@RequestBody MetaTask record) {
-        if (record.getType().equals(MetaTaskType.COLLECT_COLLECTION)) {
+        if (record.getType().equals(MetaTaskTarget.COLLECT_COLLECTION)) {
             String[] split = record.getValue().split(MetaConstants.BLANK);
             Arrays.stream(split).forEach(collectionId -> {
                 collectionRepo.findByIdAndDelFalse(Long.parseLong(collectionId)).orElseThrow(new BusinessException(String.format("不存在collectionId[%S]的藏品", collectionId)));

+ 87 - 0
src/main/java/com/izouma/nineth/web/MetaTaskNewController.java

@@ -0,0 +1,87 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaTaskBind;
+import com.izouma.nineth.domain.MetaTaskNew;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaTaskType;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaTaskBindRepo;
+import com.izouma.nineth.repo.MetaTaskNewRepo;
+import com.izouma.nineth.service.MetaTaskNewService;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
+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("/metaTaskNew")
+@AllArgsConstructor
+public class MetaTaskNewController extends BaseController {
+
+    private MetaTaskNewService metaTaskNewService;
+
+    private MetaTaskNewRepo metaTaskNewRepo;
+
+    private MetaTaskBindRepo metaTaskBindRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public MetaTaskNew save(@RequestBody MetaTaskNew record) {
+        return metaTaskNewService.save(record);
+    }
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<MetaTaskNew> all(@RequestBody PageQuery pageQuery) {
+        return metaTaskNewService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public MetaTaskNew get(@PathVariable Long id) {
+        MetaTaskNew metaTaskNew = metaTaskNewRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+        List<MetaTaskBind> metaNodeTask = metaTaskBindRepo.findByTaskIdAndTypeAndDel(metaTaskNew.getId(), MetaTaskType.NODE, false);
+        if (CollectionUtils.isNotEmpty(metaNodeTask)) {
+            metaTaskNew.setMetaNodeTask(metaNodeTask);
+        }
+        List<MetaTaskBind> metaBranchLineTask = metaTaskBindRepo.findByTaskIdAndTypeAndDel(metaTaskNew.getId(), MetaTaskType.BRANCH_LINE, false);
+        if (CollectionUtils.isNotEmpty(metaBranchLineTask)) {
+            metaTaskNew.setMetaBranchLineTask(metaBranchLineTask);
+        }
+        List<MetaTaskBind> metaDailyTask = metaTaskBindRepo.findByTaskIdAndTypeAndDel(metaTaskNew.getId(), MetaTaskType.DAILY, false);
+        if (CollectionUtils.isNotEmpty(metaDailyTask)) {
+            metaTaskNew.setMetaDailyTask(metaDailyTask);
+        }
+        return metaTaskNew;
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        metaTaskNewRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaTaskNew> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @GetMapping("/findAll")
+    public MetaRestResult<List<MetaTaskNew>> findAll() {
+        List<MetaTaskNew> metaTaskNews = metaTaskNewRepo.findAllByPublishAndFinishAndDel(true, false, false);
+        return MetaRestResult.returnSuccess(metaTaskNews);
+    }
+
+    @GetMapping("/{userId}/{channelId}/canGet")
+    public MetaRestResult<List<MetaTaskNew>> canGet(@PathVariable Long userId, @PathVariable Long channelId) {
+        List<MetaTaskNew> metaTaskNews = metaTaskNewRepo.canGet(userId, channelId);
+        return MetaRestResult.returnSuccess(metaTaskNews);
+    }
+}
+

+ 64 - 0
src/main/java/com/izouma/nineth/web/MetaTaskToUserNewController.java

@@ -0,0 +1,64 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaTaskToUserNew;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaTaskStatus;
+import com.izouma.nineth.repo.MetaTaskToUserNewRepo;
+import com.izouma.nineth.service.MetaTaskToUserNewService;
+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;
+import java.util.Objects;
+
+@RestController
+@RequestMapping("/metaTaskToUserNew")
+@AllArgsConstructor
+public class MetaTaskToUserNewController {
+
+    private MetaTaskToUserNewService metaTaskToUserNewService;
+
+    private MetaTaskToUserNewRepo metaTaskToUserNewRepo;
+
+    @PostMapping("/all")
+    public Page<MetaTaskToUserNew> all(@RequestBody PageQuery pageQuery) {
+        return metaTaskToUserNewService.all(pageQuery);
+    }
+
+    @PostMapping("/autoReceiveTask")
+    public MetaRestResult<Void> autoReceiveTask() {
+        return metaTaskToUserNewService.autoReceiveTask();
+    }
+
+    @PostMapping("/receiveTask")
+    public MetaRestResult<MetaTaskToUserNew> receiveTask(@RequestBody MetaTaskToUserNew metaTaskToUserNew) {
+        return metaTaskToUserNewService.receiveTask(metaTaskToUserNew, true);
+    }
+
+    @GetMapping("/{id}/findProgress")
+    public MetaRestResult<MetaTaskToUserNew> findProgress(@PathVariable Long id) {
+        MetaTaskToUserNew metaTaskToUserNew = metaTaskToUserNewRepo.findByIdAndDel(id, false);
+        if (Objects.isNull(metaTaskToUserNew)) {
+            return MetaRestResult.returnError(String.format("根据id[%S]查询不到用户领取记录", id));
+        }
+        return metaTaskToUserNewService.setSingleProgress(metaTaskToUserNew);
+    }
+
+    @GetMapping("/{userId}/{channelId}/{status}/findByStatus")
+    public MetaRestResult<List<MetaTaskToUserNew>> findByStatus(@PathVariable Long userId, @PathVariable Long channelId, @PathVariable MetaTaskStatus status) {
+        return metaTaskToUserNewService.findByStatus(userId, channelId, status);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaTaskToUserNew> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+}

+ 51 - 0
src/main/java/com/izouma/nineth/web/MetaUserTaskProgressNewController.java

@@ -0,0 +1,51 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaUserTaskProgressNew;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaUserTaskProgressNewRepo;
+import com.izouma.nineth.service.MetaUserTaskProgressNewService;
+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("/metaUserTaskProgressNew")
+@AllArgsConstructor
+public class MetaUserTaskProgressNewController extends BaseController {
+
+    private MetaUserTaskProgressNewService metaUserTaskProgressNewService;
+
+    private MetaUserTaskProgressNewRepo metaUserTaskProgressNewRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<MetaUserTaskProgressNew> all(@RequestBody PageQuery pageQuery) {
+        return metaUserTaskProgressNewService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public MetaUserTaskProgressNew get(@PathVariable Long id) {
+        return metaUserTaskProgressNewRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaUserTaskProgressNew> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @PostMapping("/metaSave")
+    public MetaRestResult<Boolean> metaSave(@RequestBody MetaUserTaskProgressNew metaUserTaskProgressNew) {
+        return metaUserTaskProgressNewService.metaSave(metaUserTaskProgressNew);
+    }
+
+}
+

+ 72 - 4
src/main/java/com/izouma/nineth/web/RiceController.java

@@ -5,6 +5,7 @@ import com.izouma.nineth.domain.User;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.R;
 import com.izouma.nineth.dto.RiceDTO;
+import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.*;
 import com.izouma.nineth.service.*;
@@ -53,6 +54,10 @@ public class RiceController extends BaseController {
     @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<Rice> all(@RequestBody PageQuery pageQuery) {
+
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            pageQuery.getQuery().put("userId", SecurityUtils.getAuthenticatedUser().getId());
+        }
         return riceService.all(pageQuery);
     }
 
@@ -70,8 +75,12 @@ public class RiceController extends BaseController {
     @GetMapping("/excel")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
-        List<Rice> data = all(pageQuery).getContent();
-        ExcelUtils.export(response, data);
+
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            List<Rice> data = all(pageQuery).getContent();
+            ExcelUtils.export(response, data);
+        }
+
     }
 
     //点击水稻游戏后对riceuser进行初始化赋值
@@ -125,6 +134,17 @@ public class RiceController extends BaseController {
         return R.success(top100);
     }
 
+
+    //只获取自己的排名
+    @GetMapping("/riceUserRank")
+    public R<?> getRiceUserRank() {
+        User authenticatedUser = SecurityUtils.getAuthenticatedUser();
+        Long userId = authenticatedUser.getId();
+
+        return riceService.getRiceUserRank(userId);
+    }
+
+
     //浇水响应
     @GetMapping("/watering")
     public R<String> watering() {
@@ -169,13 +189,61 @@ public class RiceController extends BaseController {
         return riceService.exchangeScoreForWaterDrop(authenticatedUser);
     }
 
+
     //活动积分兑换水滴
     @GetMapping("/exchangeActivityScoreForWaterDrop")
     public R<?> exchangeActivityScoreForWaterDrop() {
         User authenticatedUser = SecurityUtils.getAuthenticatedUser();
-        return riceService.exchangeScoreForWaterDrop(authenticatedUser);
+        return riceService.exchangeActivityScoreForWaterDrop(authenticatedUser);
     }
 
 
-}
+    @GetMapping("/newRiceUser")
+    public R<?> newRiceUser() {
+        User authenticatedUser = SecurityUtils.getAuthenticatedUser();
+        Long id = authenticatedUser.getId();
+        Optional<User> byId = userRepo.findByIdAndDelFalse(id);
+        String nickname = null;
+        String avatar = null;
+        if (byId.isPresent()) {
+            User user = byId.get();
+            nickname = user.getNickname();
+            avatar = user.getAvatar();
+        } else {
+            throw new BusinessException("用户不存在");
+        }
+
+        UUID uuid = UUID.randomUUID();
+        Rice rice = new Rice();
+            rice.setUserId(generateUniqueId());
+            rice.setAvatar(avatar);
+            rice.setNickname(nickname);
+            rice.setLevel(0L);
+            rice.setWaterDropCount(0L);
+            rice.setSignCount(0L);
+            rice.setSelfScore(0L);
+            rice.setSelfActivityScore(0L);
+            rice.setEmpiricalValue(0L);
+            riceRepo.save(rice);
+            return R.success("添加成功");
+        }
+
+
+
+    public static Long generateUniqueId() {
+        UUID uuid = UUID.randomUUID();
+        long lsb = uuid.getLeastSignificantBits();
+        long msb = uuid.getMostSignificantBits();
+        return new Long((lsb & Long.MAX_VALUE) | (msb & Long.MAX_VALUE));
+    }
+
+
+
+
+
+    }
+
+
+
+
 

+ 100 - 29
src/main/java/com/izouma/nineth/web/RiceInviteController.java

@@ -1,15 +1,15 @@
 package com.izouma.nineth.web;
-import com.izouma.nineth.domain.Invite;
-import com.izouma.nineth.domain.Rice;
-import com.izouma.nineth.domain.RiceInvite;
-import com.izouma.nineth.domain.RiceOperationRecord;
+
+import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.R;
+import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.enums.RiceOperationType;
 import com.izouma.nineth.repo.*;
 import com.izouma.nineth.service.*;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.exception.BusinessException;
 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;
@@ -18,6 +18,10 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneOffset;
 import java.util.List;
 import java.util.Optional;
 
@@ -50,54 +54,109 @@ public class RiceInviteController extends BaseController {
         }
         return riceInviteRepo.save(record);
     }
+
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<RiceInvite> all(@RequestBody PageQuery pageQuery) {
+
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            pageQuery.getQuery().put("userId", SecurityUtils.getAuthenticatedUser().getId());
+        }
         return riceInviteService.all(pageQuery);
     }
+
     @GetMapping("/get/{id}")
     public RiceInvite get(@PathVariable Long id) {
         return riceInviteRepo.findById(id).orElseThrow(new BusinessException("无记录"));
     }
-    @PostMapping("/del/{id}")
-    public void del(@PathVariable Long id) {
-        riceInviteRepo.softDelete(id);
-    }
+
+    /* @PostMapping("/del/{id}")
+     public void del(@PathVariable Long id) {
+         riceInviteRepo.softDelete(id);
+     }*/
     @GetMapping("/excel")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
-        List<RiceInvite> data = all(pageQuery).getContent();
-        ExcelUtils.export(response, data);
-    }
 
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            List<RiceInvite> data = all(pageQuery).getContent();
+            ExcelUtils.export(response, data);
+        }
+
+    }
 
 
-    //邀请别人并认领水滴
-    @PostMapping("/inviteAndClaimWaterDrop")
-    public R<?> inviteAndClaimWaterDrop(@RequestParam Long inviterId, @RequestParam Long inviteeId) {
-        // 检查邀请是否重复
-        Optional<RiceInvite> invite = riceInviteRepo.findByInviterIdAndInviteeId(inviterId, inviteeId);
+    //助力别人并认领水滴
+    @PostMapping("/helpOthers")
+    public R<?> helpOthers(@RequestParam Long helperId, @RequestParam Long helpeeId) {
+        // 检查助力者是否已经助力过该用户
+        Optional<RiceInvite> invite = riceInviteRepo.findByHelperIdAndHelpeeIdAndCreateTimeBetween(helperId, helpeeId, getTodayStartTime(), getTodayEndTime());
         if (invite.isPresent()) {
-            return R.error("邀请已发送,请勿重复发送");
+            Optional<Rice> byUserId = riceRepo.findByUserId(helpeeId);
+            String avatar = null;
+            String nickname = null;
+            if (byUserId.isPresent()) {
+                Rice rice = byUserId.get();
+                avatar = rice.getAvatar();
+                nickname = rice.getNickname();
+
+            }
+            return R.error("您今天已经助力过该用户,请勿重复助力").add("avatar", avatar).add("nickname", nickname);
+        }
+
+
+        // 检查助力者是否已经助力过其他用户
+        Optional<RiceInvite> helperRice = riceInviteRepo.findByHelperIdAndCreateTimeBetween(helperId, getTodayStartTime(), getTodayEndTime());
+        if (helperRice.isPresent()) {
+            Optional<Rice> byUserId = riceRepo.findByUserId(helpeeId);
+            String avatar = null;
+            String nickname = null;
+            if (byUserId.isPresent()) {
+                Rice rice = byUserId.get();
+                avatar = rice.getAvatar();
+                nickname = rice.getNickname();
+
+            }
+            return R.error("您今天已经助力过其他用户,请勿重复助力").add("avatar", avatar).add("nickname", nickname);
         }
+
+        // 检查被助力者是否已经被别人助力
+        Optional<RiceInvite> helpeeRice = riceInviteRepo.findByHelpeeIdAndDelIsFalseAndCreateTimeBetween(helpeeId, getTodayStartTime(), getTodayEndTime());
+        if (helpeeRice.isPresent()) {
+            Optional<Rice> byUserId = riceRepo.findByUserId(helpeeId);
+            String avatar = null;
+            String nickname = null;
+            if (byUserId.isPresent()) {
+                Rice rice = byUserId.get();
+                avatar = rice.getAvatar();
+                nickname = rice.getNickname();
+
+            }
+            return R.error("该用户今天已经获得了助力,请勿重复助力").add("avatar", avatar).add("nickname", nickname);
+        }
+
+
         // 创建邀请记录
         RiceInvite newInvite = new RiceInvite();
-        newInvite.setInviterId(inviterId);
-        newInvite.setInviteeId(inviteeId);
+        newInvite.setHelperId(helperId);
+        newInvite.setHelpeeId(helpeeId);
         newInvite.setCreateTime(System.currentTimeMillis());
         riceInviteRepo.save(newInvite);
 
-        // 增加邀请者的水滴数
-        Optional<Rice> inviterRice = riceRepo.findById(inviterId);
-        if (!inviterRice.isPresent()) {
-            return R.error("未找到邀请者的用户信息");
+        // 增加被助力者的水滴数
+        Optional<Rice> rice = riceRepo.findByUserId(helpeeId);
+        if (rice.isPresent()) {
+            Rice helpee = rice.get();
+            Long beforeWaterDropCount = helpee.getWaterDropCount();
+            helpee.setWaterDropCount(helpee.getWaterDropCount() + 1);
+            riceRepo.save(helpee);
+            createRiceOperationRecord(helpeeId, RiceOperationType.WATER_DROP, 1L, beforeWaterDropCount, helpee.getWaterDropCount());
+        } else {
+            return R.error("未找到被助力者的用户信息").add("avatar", rice.get().getAvatar()).add("nickname", rice.get().getNickname());
         }
-        Rice rice = inviterRice.get();
-        Long beforeWaterDropCount = rice.getWaterDropCount();
-        rice.setWaterDropCount(rice.getWaterDropCount() + 1);
-        riceRepo.save(rice);
-        createRiceOperationRecord(inviterId,RiceOperationType.WATER_DROP,1L,beforeWaterDropCount,rice.getWaterDropCount());
-        return R.success("邀请成功并领取水滴").add("waterDropCount", rice.getWaterDropCount());
+
+        // 返回助力结果以及被助力者的头像和昵称
+        return R.success("助力成功").add("avatar", rice.get().getAvatar()).add("nickname", rice.get().getNickname());
     }
 
 
@@ -111,5 +170,17 @@ public class RiceInviteController extends BaseController {
         riceOperationRecordRepo.save(record);
     }
 
+    private Long getTodayStartTime() {
+        LocalDate localDate = LocalDate.now();
+        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MIN);
+        return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+    }
+
+    private Long getTodayEndTime() {
+        LocalDate localDate = LocalDate.now();
+        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MAX);
+        return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+    }
+
 }
 

+ 12 - 4
src/main/java/com/izouma/nineth/web/RiceOperationRecordController.java

@@ -1,10 +1,12 @@
 package com.izouma.nineth.web;
 import com.izouma.nineth.domain.RiceOperationRecord;
+import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.service.RiceOperationRecordService;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.RiceOperationRecordRepo;
 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;
@@ -37,6 +39,9 @@ public class RiceOperationRecordController extends BaseController {
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<RiceOperationRecord> all(@RequestBody PageQuery pageQuery) {
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            pageQuery.getQuery().put("userId", SecurityUtils.getAuthenticatedUser().getId());
+        }
         return riceOperationRecordService.all(pageQuery);
     }
 
@@ -45,16 +50,19 @@ public class RiceOperationRecordController extends BaseController {
         return riceOperationRecordRepo.findById(id).orElseThrow(new BusinessException("无记录"));
     }
 
-    @PostMapping("/del/{id}")
+/*    @PostMapping("/del/{id}")
     public void del(@PathVariable Long id) {
         riceOperationRecordRepo.softDelete(id);
-    }
+    }*/
 
     @GetMapping("/excel")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
-        List<RiceOperationRecord> data = all(pageQuery).getContent();
-        ExcelUtils.export(response, data);
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            List<RiceOperationRecord> data = all(pageQuery).getContent();
+            ExcelUtils.export(response, data);
+        }
+
     }
 }
 

+ 13 - 4
src/main/java/com/izouma/nineth/web/RiceUserWaterDropRecordController.java

@@ -1,10 +1,12 @@
 package com.izouma.nineth.web;
 import com.izouma.nineth.domain.RiceUserWaterDropRecord;
+import com.izouma.nineth.enums.AuthorityName;
 import com.izouma.nineth.service.RiceUserWaterDropRecordService;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.RiceUserWaterDropRecordRepo;
 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;
@@ -37,6 +39,10 @@ public class RiceUserWaterDropRecordController extends BaseController {
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<RiceUserWaterDropRecord> all(@RequestBody PageQuery pageQuery) {
+
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            pageQuery.getQuery().put("userId", SecurityUtils.getAuthenticatedUser().getId());
+        }
         return riceUserWaterDropRecordService.all(pageQuery);
     }
 
@@ -45,16 +51,19 @@ public class RiceUserWaterDropRecordController extends BaseController {
         return riceUserWaterDropRecordRepo.findById(id).orElseThrow(new BusinessException("无记录"));
     }
 
-    @PostMapping("/del/{id}")
+ /*   @PostMapping("/del/{id}")
     public void del(@PathVariable Long id) {
         riceUserWaterDropRecordRepo.softDelete(id);
-    }
+    }*/
 
     @GetMapping("/excel")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
-        List<RiceUserWaterDropRecord> data = all(pageQuery).getContent();
-        ExcelUtils.export(response, data);
+        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_ORDERINFO)) {
+            List<RiceUserWaterDropRecord> data = all(pageQuery).getContent();
+            ExcelUtils.export(response, data);
+        }
+
     }
 }
 

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

@@ -111,12 +111,14 @@ public class StatisticController {
     }
 
     @GetMapping("/otherStatistic")
+    @PreAuthorize("hasAnyRole('ADMIN','COMPANY','ORDERINFO','SAAS')")
     public Map<String, Object> otherStatistic() {
         return statisticService.otherStatistic();
     }
 
     @GetMapping("/statisticDetail")
     @Cacheable("statisticDetail")
+    @PreAuthorize("hasAnyRole('ADMIN','COMPANY','ORDERINFO','SAAS')")
     public Map<String, Map<String, Object>> statisticDetail() {
         return statisticService.statisticDetail();
     }

+ 74 - 0
src/main/java/com/izouma/nineth/web/nftdomain/CartController.java

@@ -0,0 +1,74 @@
+package com.izouma.nineth.web.nftdomain;
+
+import com.izouma.nineth.web.BaseController;
+import com.izouma.nineth.domain.nftdomain.Cart;
+import com.izouma.nineth.service.nftdomain.CartService;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.nftdomain.CartRepo;
+import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/cart")
+@AllArgsConstructor
+public class CartController extends BaseController {
+    private CartService cartService;
+    private CartRepo    cartRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public Cart save(@RequestBody Cart record) {
+        if (record.getId() != null) {
+            Cart orig = cartRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return cartRepo.save(orig);
+        }
+        return cartRepo.save(record);
+    }
+
+    @PostMapping("/create")
+    public Cart save(Long collectionId) {
+        return cartService.create(collectionId);
+    }
+
+    @PostMapping("/status")
+    public Map<String, Object> status(Long collectionId) {
+        return cartService.collectionCartStatus(collectionId);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<Cart> all(@RequestBody PageQuery pageQuery) {
+        return cartService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public Cart get(@PathVariable Long id) {
+        return cartRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        cartRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<Cart> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 1 - 0
src/main/resources/genjson/MetaAtomTask.json

@@ -0,0 +1 @@
+{"tableName":"MetaAtomTask","className":"MetaAtomTask","remark":"基础任务","genTable":true,"genClass":true,"genList":true,"genForm":true,"genRouter":true,"javaPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/java/com/izouma/nineth","viewPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src/views","routerPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src","resourcesPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"name","modelName":"name","remark":"任务名称","showInList":true,"showInForm":true,"formType":"singleLineText","required":true},{"name":"detail","modelName":"detail","remark":"任务详情","showInList":true,"showInForm":true,"formType":"singleLineText","required":true},{"name":"targetType","modelName":"targetType","remark":"任务目标","showInList":true,"showInForm":true,"formType":"select","required":true,"apiFlag":"1","optionsValue":"[{\"label\":\"收集藏品\",\"value\":\"COLLECT_COLLECTION\"},{\"label\":\"每日在线时长\",\"value\":\"ON_LINE_TIME_DAILY\"},{\"label\":\"累计\",\"value\":\"ACCUMULATE\"}]"},{"name":"targetConfig","modelName":"targetConfig","remark":"目标配置","showInList":true,"showInForm":true,"formType":"singleLineText","required":true},{"name":"awardType","modelName":"awardType","remark":"奖励类型","showInList":true,"showInForm":true,"formType":"select","required":true,"apiFlag":"1","optionsValue":"[{\"label\":\"空\",\"value\":\"NULL\"},{\"label\":\"NFT\",\"value\":\"NFT\"},{\"label\":\"金币\",\"value\":\"GOLD\"},{\"label\":\"元宇宙道具\",\"value\":\"META_PROP\"}]"},{"name":"awardConfig","modelName":"awardConfig","remark":"奖励配置","showInList":true,"showInForm":true,"formType":"singleLineText","required":true}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.nineth","tablePackage":"com.izouma.nineth.domain.MetaAtomTask"}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
src/main/resources/genjson/MetaStore.json


+ 1 - 0
src/main/resources/genjson/MetaTaskNew.json

@@ -0,0 +1 @@
+{"tableName":"MetaTaskNew","className":"MetaTaskNew","remark":"新任务管理","genTable":true,"genClass":true,"genList":true,"genForm":true,"genRouter":true,"javaPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/java/com/izouma/nineth","viewPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src/views","routerPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src","resourcesPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"name","modelName":"name","remark":"任务名称","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"detail","modelName":"detail","remark":"任务详情","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"type","modelName":"type","remark":"任务分类","showInList":true,"showInForm":true,"formType":"select","apiFlag":"1","optionsValue":"[{\"label\":\"主线任务\",\"value\":\"MAIN_LINE\"},{\"label\":\"支线任务\",\"value\":\"BRANCH_LINE\"},{\"label\":\"日常任务\",\"value\":\"DAILY\"}]"},{"name":"publish","modelName":"publish","remark":"是否发布","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"autoReceive","modelName":"autoReceive","remark":"自动领取","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"channelId","modelName":"channelId","remark":"频道id","showInList":true,"showInForm":true,"formType":"number"}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.nineth","tablePackage":"com.izouma.nineth.domain.MetaTaskNew"}

+ 1 - 1
src/main/vue/.env.development

@@ -1 +1 @@
-VUE_APP_BASE_URL=http://localhost:8080/
+VUE_APP_BASE_URL=https://www.raex.vip/

+ 57 - 1
src/main/vue/src/router.js

@@ -1957,7 +1957,63 @@ const router = new Router({
                     meta: {
                        title: '水稻用户操作记录表',
                     },
-               }
+               },
+                {
+                    path: '/metaAtomTaskEdit',
+                    name: 'MetaAtomTaskEdit',
+                    component: () => import(/* webpackChunkName: "metaAtomTaskEdit" */ '@/views/MetaAtomTaskEdit.vue'),
+                    meta: {
+                        title: '基础任务编辑',
+                    },
+                },
+                {
+                    path: '/metaAtomTaskList',
+                    name: 'MetaAtomTaskList',
+                    component: () => import(/* webpackChunkName: "metaAtomTaskList" */ '@/views/MetaAtomTaskList.vue'),
+                    meta: {
+                        title: '基础任务',
+                    },
+                },
+                {
+                    path: '/metaTaskNewEdit',
+                    name: 'MetaTaskNewEdit',
+                    component: () => import(/* webpackChunkName: "metaTaskNewEdit" */ '@/views/MetaTaskNewEdit.vue'),
+                    meta: {
+                        title: '新任务管理编辑',
+                    },
+                },
+                {
+                    path: '/metaTaskNewList',
+                    name: 'MetaTaskNewList',
+                    component: () => import(/* webpackChunkName: "metaTaskNewList" */ '@/views/MetaTaskNewList.vue'),
+                    meta: {
+                        title: '新任务管理',
+                    },
+                },
+                {
+                    path: '/metaStoreEdit',
+                    name: 'MetaStoreEdit',
+                    component: () => import(/* webpackChunkName: "metaStoreEdit" */ '@/views/MetaStoreEdit.vue'),
+                    meta: {
+                        title: '商店编辑',
+                    },
+                },
+                {
+                    path: '/metaStoreList',
+                    name: 'MetaStoreList',
+                    component: () => import(/* webpackChunkName: "metaStoreList" */ '@/views/MetaStoreList.vue'),
+                    meta: {
+                        title: '商店',
+                    },
+                },
+                {
+                    path: '/metaStorePurchaseRecordList',
+                    name: 'MetaStorePurchaseRecordList',
+                    component: () => import(/* webpackChunkName: "metaStorePurchaseRecordList" */ '@/views/MetaStorePurchaseRecordList.vue'),
+                    meta: {
+                        title: '商店购买记录',
+                    },
+                }
                 /**INSERT_LOCATION**/
             ]
         },

+ 225 - 0
src/main/vue/src/views/MetaAtomTaskEdit.vue

@@ -0,0 +1,225 @@
+<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="120px" label-position="right" size="small"
+                    style="max-width: 500px;">
+                    <el-form-item prop="name" label="任务名称">
+                        <el-input v-model="formData.name"> </el-input>
+                    </el-form-item>
+                    <el-form-item prop="detail" label="任务详情" style="width: calc(100vw - 450px)">
+                        <el-input v-model="formData.detail" type="textarea" :autosize="{ minRows: 3, maxRows: 20 }"
+                            placeholder="请输入任务详情">
+                        </el-input>
+                    </el-form-item>
+                    <el-form-item prop="targetType" label="任务目标">
+                        <el-select v-model="formData.targetType" clearable filterable placeholder="请选择"
+                            @change="changeTargetType" :disabled="!canEdit">
+                            <el-option v-for="item in targetTypeOptions" :key="item.value" :label="item.label"
+                                :value="item.value">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="targetConfig" label="藏品名称"
+                        v-if="formData.targetType && formData.targetType === 'COLLECT_COLLECTION'">
+                        <el-input v-model="formData.targetConfig" placeholder="请指定藏品名称" :disabled="!canEdit"> </el-input>
+                    </el-form-item>
+                    <el-form-item prop="targetConfig" label="累计次数"
+                        v-if="formData.targetType && formData.targetType === 'ACCUMULATE'">
+                        <el-input-number v-model="formData.targetConfig" :min="0" :disabled="!canEdit"> </el-input-number>
+                    </el-form-item>
+                    <el-form-item prop="targetConfig" label="在线时长(min)"
+                        v-if="formData.targetType && formData.targetType === 'ON_LINE_TIME_DAILY'">
+                        <el-input-number v-model="formData.targetConfig" :min="0" :disabled="!canEdit"> </el-input-number>
+                    </el-form-item>
+                    <el-form-item prop="awardType" label="奖励类型">
+                        <el-select v-model="formData.awardType" clearable filterable placeholder="请选择"
+                            @change="changeAwardType" :disabled="!canEdit">
+                            <el-option v-for="item in awardTypeOptions" :key="item.value" :label="item.label"
+                                :value="item.value">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="awardConfig" label="道具"
+                        v-if="formData.awardType && formData.awardType === 'META_PROP'">
+                        <el-select v-model="formData.awardConfig" placeholder="请选择" filterable :disabled="!canEdit">
+                            <el-option v-for="item in metaProps" :key="item.id" :label="item.name" :value="item.id">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="awardConfig" label="奖励图片" v-if="formData.awardType && formData.awardType === 'NFT'">
+                        <single-upload v-model="formData.awardConfig" :disabled="!canEdit"> </single-upload>
+                    </el-form-item>
+                    <el-form-item prop="awardConfig" label="奖励金币数量"
+                        v-if="formData.awardType && formData.awardType === 'GOLD'">
+                        <el-input-number type="awardConfig" v-model="formData.awardConfig" :step="1" :min="1"
+                            :disabled="!canEdit">
+                        </el-input-number>
+                        <div class="tip">输入规则:正整数,最小为1</div>
+                    </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 { reg } from '../util/regRules';
+export default {
+	name: 'MetaAtomTaskEdit',
+	created() {
+		if (this.$route.query.id) {
+			this.$http
+				.get('metaAtomTask/get/' + this.$route.query.id)
+				.then(res => {
+					this.formData = res;
+				})
+				.catch(e => {
+					console.log(e);
+					this.$message.error(e.error);
+				});
+		}
+		this.$http.get('/metaProp/findAll').then(res => {
+			this.metaProps = res;
+		});
+	},
+	computed: {
+		canEdit() {
+			return !!!this.$route.query.id;
+		}
+	},
+	data() {
+		return {
+			metaProps: [],
+			reg,
+			saving: false,
+			formData: {},
+			rules: {
+				name: [
+					{
+						required: true,
+						message: '请输入任务名称',
+						trigger: 'blur'
+					}
+				],
+				detail: [
+					{
+						required: true,
+						message: '请输入任务详情',
+						trigger: 'blur'
+					}
+				],
+				targetType: [
+					{
+						required: true,
+						message: '请输入任务目标',
+						trigger: 'blur'
+					}
+				],
+				targetConfig: [
+					{
+						required: true,
+						message: '请输入目标配置',
+						trigger: 'blur'
+					}
+				],
+				awardType: [
+					{
+						required: true,
+						message: '请输入奖励类型',
+						trigger: 'blur'
+					}
+				],
+				awardConfig: [
+					{
+						required: true,
+						message: '请输入奖励配置',
+						trigger: 'blur'
+					}
+				]
+			},
+			targetTypeOptions: [
+				{ label: '累计', value: 'ACCUMULATE' },
+				{ label: '收集藏品', value: 'COLLECT_COLLECTION' },
+                { label: '每日在线时长', value: 'ON_LINE_TIME_DAILY' }
+			],
+			awardTypeOptions: [
+				{ label: '空', value: 'NULL' },
+				{ label: 'NFT', value: 'NFT' },
+				{ label: '金币', value: 'GOLD' },
+				{ label: '元宇宙道具', value: 'META_PROP' }
+			]
+		};
+	},
+	methods: {
+		changeAwardType() {
+			if (this.formData.awardConfig) {
+				this.$delete(this.formData, 'awardConfig');
+			}
+		},
+		changeTargetType() {
+			if (this.formData.targetConfig) {
+				this.$delete(this.formData, 'targetConfig');
+			}
+		},
+		onSave() {
+			this.$refs.form.validate(valid => {
+				if (valid) {
+					this.submit();
+				} else {
+					return false;
+				}
+			});
+		},
+		submit() {
+			let data = { ...this.formData };
+
+			this.saving = true;
+			this.$http
+				.post('/metaAtomTask/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(`/metaAtomTask/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>

+ 190 - 0
src/main/vue/src/views/MetaAtomTaskList.vue

@@ -0,0 +1,190 @@
+<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" align="center" label="ID" width="100">
+            </el-table-column>
+            <el-table-column prop="name" align="center" label="任务名称">
+            </el-table-column>
+            <el-table-column prop="detail" align="center" label="任务详情">
+            </el-table-column>
+            <el-table-column prop="targetType" align="center" label="任务目标" :formatter="targetTypeFormatter">
+            </el-table-column>
+            <el-table-column prop="targetConfig" align="center" label="目标配置">
+            </el-table-column>
+            <el-table-column prop="awardType" align="center" label="奖励类型" :formatter="awardTypeFormatter">
+            </el-table-column>
+            <el-table-column prop="awardConfig" align="center" label="奖励配置">
+                <template v-slot="{ row }">
+                    <template v-if="row.awardType && row.awardType === 'NFT'">
+                        <el-image
+                        style="width: 30px; height: 30px"
+                        :src="row.awardConfig"
+                        fit="cover"
+                        :preview-src-list="[row.awardConfig]"
+                    >
+                    </el-image>
+                    </template>
+                    <template v-else>
+                        {{ row.awardConfig }}
+                    </template>
+                </template>
+            </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">
+            <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: 'MetaAtomTaskList',
+	mixins: [pageableTable],
+	data() {
+		return {
+			multipleMode: false,
+			search: '',
+			url: '/metaAtomTask/all',
+			downloading: false,
+			targetTypeOptions: [
+				{ label: '收集藏品', value: 'COLLECT_COLLECTION' },
+				{ label: '每日在线时长', value: 'ON_LINE_TIME_DAILY' },
+				{ label: '累计', value: 'ACCUMULATE' }
+			],
+			awardTypeOptions: [
+				{ label: '空', value: 'NULL' },
+				{ label: 'NFT', value: 'NFT' },
+				{ label: '金币', value: 'GOLD' },
+				{ label: '元宇宙道具', value: 'META_PROP' }
+			]
+		};
+	},
+	computed: {
+		selection() {
+			return this.$refs.table.selection.map(i => i.id);
+		}
+	},
+	methods: {
+		targetTypeFormatter(row, column, cellValue, index) {
+			let selectedOption = this.targetTypeOptions.find(i => i.value === cellValue);
+			if (selectedOption) {
+				return selectedOption.label;
+			}
+			return '';
+		},
+		awardTypeFormatter(row, column, cellValue, index) {
+			let selectedOption = this.awardTypeOptions.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: '/metaAtomTaskEdit',
+				query: {
+					...this.$route.query
+				}
+			});
+		},
+		editRow(row) {
+			this.$router.push({
+				path: '/metaAtomTaskEdit',
+				query: {
+					id: row.id
+				}
+			});
+		},
+		download() {
+			this.downloading = true;
+			this.$axios
+				.get('/metaAtomTask/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(`/metaAtomTask/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>

+ 281 - 0
src/main/vue/src/views/MetaStoreEdit.vue

@@ -0,0 +1,281 @@
+<template>
+    <div class="edit-view">
+        <page-title>
+            <el-button @click="$router.go(-1)" :disabled="saving">取消</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="80px" label-position="right" size="small"
+                    style="max-width: 500px;">
+                    <el-form-item prop="commodityType" label="商品类型">
+                        <el-select v-model="formData.commodityType" clearable filterable placeholder="请选择"
+                            @change="changeCommodityType" :disabled="!canEdit">
+                            <el-option v-for="item in commodityTypeOptions" :key="item.value" :label="item.label"
+                                :value="item.value">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="metaPropId" label="道具"
+                        v-if="formData.commodityType && formData.commodityType === 'META_PROP'">
+                        <el-select v-model="formData.metaPropId" placeholder="请选择" filterable :disabled="!canEdit"
+                            @change="changeMetaProp($event)">
+                            <el-option v-for="item in metaProps" :key="item.id" :label="item.name" :value="item.id">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="name" label="商品名称">
+                        <el-input v-model="formData.name"
+                            :disabled="!canEdit || formData.commodityType === 'META_PROP'"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="pic" label="商品图片">
+                        <single-upload v-model="formData.pic"
+                            :disabled="!canEdit || formData.commodityType === 'META_PROP'"> </single-upload>
+                    </el-form-item>
+                    <el-form-item prop="introduction" label="商品介绍">
+                        <el-input type="textarea" v-model="formData.introduction"
+                            :disabled="formData.commodityType === 'META_PROP'"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="price" label="金币价格">
+                        <el-input-number type="price" v-model="formData.price" :step="1" :min="1" :disabled="!canEdit">
+                        </el-input-number>
+                        <div class="tip">输入规则:正整数,最小为1</div>
+                    </el-form-item>
+                    <template v-if="formData.commodityType && formData.commodityType === 'NFT'">
+                        <el-form-item prop="stockNum" label="库存数量">
+                            <el-input-number type="stockNum" v-model="formData.stockNum" :step="1" :min="1"
+                                :disabled="!canEdit">
+                            </el-input-number>
+                            <div class="tip">输入规则:正整数,最小为1</div>
+                        </el-form-item>
+                        <el-form-item prop="purchaseLimitNum" label="限购数量">
+                            <el-input-number type="purchaseLimitNum" v-model="formData.purchaseLimitNum" :step="1" :min="1"
+                                :disabled="!canEdit">
+                            </el-input-number>
+                            <div class="tip">输入规则:正整数,最小为1</div>
+                        </el-form-item>
+                    </template>
+                    <el-form-item prop="onShelf" label="是否上架">
+                        <el-switch v-model="formData.onShelf"> </el-switch>
+                    </el-form-item>
+                    <el-form-item class="form-submit">
+                        <el-button @click="onSave" :loading="saving" type="primary">
+                            保存
+                        </el-button>
+                        <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+                    </el-form-item>
+                </el-form>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import { reg } from '../util/regRules';
+export default {
+	name: 'MetaStoreEdit',
+	created() {
+		if (this.$route.query.id) {
+			this.$http
+				.get('metaStore/get/' + this.$route.query.id)
+				.then(res => {
+					this.formData = res;
+				})
+				.catch(e => {
+					console.log(e);
+					this.$message.error(e.error);
+				});
+		}
+		this.$http.get('/metaProp/findAll').then(res => {
+			this.metaProps = res;
+		});
+	},
+	computed: {
+		canEdit() {
+			return !!!this.$route.query.id;
+		}
+	},
+	data() {
+		return {
+            reg,
+			metaProps: [],
+			saving: false,
+			formData: {
+				introduction: '',
+				name: '',
+				pic: ''
+			},
+			rules: {
+				commodityType: [
+					{
+						required: true,
+						message: '请选择商品类型',
+						trigger: 'blur'
+					}
+				],
+				metaPropId: [
+					{
+						required: true,
+						message: '请选择道具',
+						trigger: 'blur'
+					}
+				],
+				name: [
+					{
+						required: true,
+						message: '请输入商品名称',
+						trigger: 'blur'
+					}
+				],
+				pic: [
+					{
+						required: true,
+						message: '请上传商品图片',
+						trigger: 'blur'
+					}
+				],
+				introduction: [
+					{
+						required: true,
+						message: '请输入商品介绍',
+						trigger: 'blur'
+					}
+				],
+				price: [
+					{
+						required: true,
+						message: '请输入金币价格',
+						trigger: 'blur'
+					},
+					{
+						validator: (rule, value, callback) => {
+							if (!this.reg.test(value)) {
+								callback(new Error('金币价格必须为大于1的整数'));
+								return;
+							} else {
+								callback();
+							}
+						}
+					}
+				],
+				stockNum: [
+					{
+						required: true,
+						message: '请输入库存数量',
+						trigger: 'blur'
+					},
+					{
+						validator: (rule, value, callback) => {
+							if (!this.reg.test(value)) {
+								callback(new Error('库存数量必须为大于1的整数'));
+								return;
+							} else {
+								callback();
+							}
+						}
+					}
+				],
+				purchaseLimitNum: [
+					{
+						required: true,
+						message: '请输入限购数量',
+						trigger: 'blur'
+					},
+					{
+						validator: (rule, value, callback) => {
+							if (!this.reg.test(value)) {
+								callback(new Error('限购数量必须为大于1的整数'));
+								return;
+							} else {
+								callback();
+							}
+						}
+					}
+				]
+			},
+			commodityTypeOptions: [
+				{ label: 'NFT', value: 'NFT' },
+				{ label: '元宇宙道具', value: 'META_PROP' }
+			]
+		};
+	},
+	methods: {
+		changeCommodityType() {
+			this.formData.introduction = '';
+			this.formData.pic = '';
+			this.formData.name = '';
+			this.$delete(this.formData, 'metaPropId');
+			this.$delete(this.formData, 'price');
+			this.$delete(this.formData, 'stockNum');
+			this.$delete(this.formData, 'purchaseLimitNum');
+		},
+		changeMetaProp(value) {
+			this.$http
+				.get('metaStore/' + value + '/checkMetaProp')
+				.then(res => {
+					if (res) {
+						this.$http
+							.get('metaProp/get/' + value)
+							.then(res => {
+								this.formData.introduction = res.introduction;
+								this.formData.name = res.name;
+								this.formData.pic = res.pic;
+							})
+							.catch(e => {
+								console.log(e);
+								this.$message.error(e.error);
+							});
+					} else {
+						this.$message.error('商店中已经存在该道具');
+					}
+				})
+				.catch(e => {
+					console.log(e);
+					this.$message.error(e.error);
+				});
+		},
+		onSave() {
+			this.$refs.form.validate(valid => {
+				if (valid) {
+					this.submit();
+				} else {
+					return false;
+				}
+			});
+		},
+		submit() {
+			let data = { ...this.formData };
+
+			this.saving = true;
+			this.$http
+				.post('/metaStore/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(`/metaStore/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>

+ 214 - 0
src/main/vue/src/views/MetaStoreList.vue

@@ -0,0 +1,214 @@
+<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="name" align="center" label="商品名称">
+            </el-table-column>
+            <el-table-column prop="commodityType" align="center" label="商品类型" :formatter="commodityTypeFormatter">
+            </el-table-column>
+            <el-table-column prop="pic" align="center" label="商品图片">
+                <template slot-scope="{ row }">
+                    <el-image style="width: 30px; height: 30px" :src="row.pic" fit="cover" :preview-src-list="[row.pic]">
+                    </el-image>
+                </template>
+            </el-table-column>
+            <el-table-column prop="introduction" align="center" label="商品介绍">
+            </el-table-column>
+            <el-table-column prop="price" align="center" label="金币价格">
+            </el-table-column>
+            <el-table-column prop="stockNum" align="center" label="库存数量">
+                <template slot-scope="{ row }">
+                    <template v-if="row.commodityType && row.commodityType ==='NFT'">
+                        {{ row.stockNum }}
+                    </template>
+                    <template v-else>
+                        {{ '不限' }}
+                    </template>
+                </template>
+            </el-table-column>
+            <el-table-column prop="purchaseLimitNum" align="center" label="限购数量">
+                <template slot-scope="{ row }">
+                    <template v-if="row.commodityType && row.commodityType ==='NFT'">
+                        {{ row.purchaseLimitNum }}
+                    </template>
+                    <template v-else>
+                        {{ '不限' }}
+                    </template>
+                </template>
+            </el-table-column>
+            <el-table-column prop="onShelf" align="center" label="是否上架">
+                <template slot-scope="{ row }">
+                    <el-tag :type="row.onShelf ? '' : 'info'"> {{ row.onShelf }} </el-tag>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="350">
+                <template slot-scope="{row}">
+                    <template v-if="!row.onShelf">
+                        <el-button @click="onShelf(row)" type="primary" size="mini" plain>上架</el-button>
+                    </template>
+                    <template v-else>
+                        <el-button @click="cancelOnShelf(row)" type="primary" size="mini" plain>下架</el-button>
+                    </template>
+                    <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">
+            <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: 'MetaStoreList',
+	mixins: [pageableTable],
+	data() {
+		return {
+			multipleMode: false,
+			search: '',
+			url: '/metaStore/all',
+			downloading: false,
+			commodityTypeOptions: [
+				{ label: 'NFT', value: 'NFT' },
+				{ label: '元宇宙道具', value: 'META_PROP' }
+			]
+		};
+	},
+	computed: {
+		selection() {
+			return this.$refs.table.selection.map(i => i.id);
+		}
+	},
+	methods: {
+		onShelf(row) {
+            this.$alert('确定要上架该商品吗?', '警告', { type: 'info' })
+				.then(() => {
+					return this.$http.post('/metaStore/' + row.id + '/onShelf');
+				})
+				.then(() => {
+					this.$message.success('上架成功');
+					this.getData();
+				})
+				.catch(e => {
+					if (e !== 'cancel') {
+						this.$message.error(e.error);
+					}
+				});
+        },
+		cancelOnShelf(row) {
+            this.$alert('确定要下架该商品吗?', '警告', { type: 'info' })
+				.then(() => {
+					return this.$http.post('/metaStore/' + row.id + '/cancelOnShelf');
+				})
+				.then(() => {
+					this.$message.success('下架成功');
+					this.getData();
+				})
+				.catch(e => {
+					if (e !== 'cancel') {
+						this.$message.error(e.error);
+					}
+				});
+        },
+		commodityTypeFormatter(row, column, cellValue, index) {
+			let selectedOption = this.commodityTypeOptions.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: '/metaStoreEdit',
+				query: {
+					...this.$route.query
+				}
+			});
+		},
+		editRow(row) {
+			this.$router.push({
+				path: '/metaStoreEdit',
+				query: {
+					id: row.id
+				}
+			});
+		},
+		download() {
+			this.downloading = true;
+			this.$axios
+				.get('/metaStore/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);
+				});
+		},
+		deleteRow(row) {
+			this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+				.then(() => {
+					return this.$http.post(`/metaStore/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>

+ 84 - 0
src/main/vue/src/views/MetaStorePurchaseRecordList.vue

@@ -0,0 +1,84 @@
+<template>
+	<div class="list-view">
+		<page-title>
+			<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 prop="userId" align="center" label="用户id">
+			</el-table-column>
+			<el-table-column prop="metaStoreId" align="center" label="商品id">
+			</el-table-column>
+			<el-table-column prop="purchaseTime" align="center" label="购买时间">
+			</el-table-column>
+		</el-table>
+		<div class="pagination-wrapper">
+			<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: 'MetaStorePurchaseRecordList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            search: '',
+            url: '/metaStorePurchaseRecord/all',
+            downloading: false
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        beforeGetData() {
+            return { search: this.search, query: { del: false } };
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/metaStorePurchaseRecord/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);
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 1 - 21
src/main/vue/src/views/MetaTaskEdit.vue

@@ -48,24 +48,6 @@
                         </el-select>
                     </el-form-item>
                     <template v-if="formData.type">
-                        <!-- <el-form-item v-if="formData.type === 'SIGN_IN_SINGLE_DAY'" prop="value" label="签到日期">
-                            <el-date-picker
-                                v-model="formData.value"
-                                type="date"
-                                value-format="yyyy-MM-dd"
-                                placeholder="指定签到日期"
-                            >
-                            </el-date-picker>
-                        </el-form-item>
-                        <el-form-item v-if="formData.type === 'SIGN_IN_CONTINUOUS'" prop="value" label="开始日期">
-                            <el-date-picker
-                                v-model="formData.value"
-                                type="date"
-                                value-format="yyyy-MM-dd"
-                                placeholder="指定开始日期"
-                            >
-                            </el-date-picker>
-                        </el-form-item> -->
                         <el-form-item prop="value" label="藏品id" v-if="formData.type === 'COLLECT_COLLECTION'">
                             <el-input v-model="formData.value" placeholder="请输入定藏品id" :disabled="!canEdit"> </el-input>
                             <div class="tip">多个藏品id请用空格隔开 例如 111 222 333</div>
@@ -202,7 +184,7 @@ export default {
 				channelId: [
 					{
 						required: true,
-						message: '请选择所属道',
+						message: '请选择所属道',
 						trigger: 'blur'
 					}
 				],
@@ -215,8 +197,6 @@ export default {
 				]
 			},
 			typeOptions: [
-				// { label: '单日签到', value: 'SIGN_IN_SINGLE_DAY' },
-				// { label: '连续多日签到', value: 'SIGN_IN_CONTINUOUS' },
 				{ label: '收集藏品', value: 'COLLECT_COLLECTION' },
 				{ label: '每日在线时长', value: 'ON_LINE_TIME_DAILY' },
 				{ label: '累计', value: 'ACCUMULATE' }

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

@@ -125,8 +125,6 @@ export default {
             url: '/metaTask/all',
             downloading: false,
             typeOptions: [
-                // { label: '单日签到', value: 'SIGN_IN_SINGLE_DAY' },
-                // { label: '连续多日签到', value: 'SIGN_IN_CONTINUOUS' },
                 { label: '收集藏品', value: 'COLLECT_COLLECTION' },
                 { label: '每日在线时长', value: 'ON_LINE_TIME_DAILY' },
                 { label: '累计', value: 'ACCUMULATE' }

+ 355 - 0
src/main/vue/src/views/MetaTaskNewEdit.vue

@@ -0,0 +1,355 @@
+<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="120px" label-position="right" size="small"
+                    style="max-width: 500px;">
+                    <el-form-item prop="name" label="任务名称">
+                        <el-input v-model="formData.name"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="detail" label="任务详情">
+                        <el-input v-model="formData.detail" type="textarea" :autosize="{ minRows: 3, maxRows: 20 }"
+                            placeholder="请输入任务详情">
+                        </el-input>
+                    </el-form-item>
+                    <el-form-item prop="type" label="任务分类">
+                        <el-select v-model="formData.type" clearable filterable placeholder="请选择" :disabled="!canEdit"
+                            @change="changeTaskType">
+                            <el-option v-for="item in typeOptions" :key="item.value" :label="item.label"
+                                :value="item.value">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <template v-if="formData && formData.type == 'MAIN_LINE'">
+                        <el-form-item prop="metaNodeTask" label="节点任务配置" style="width: calc(100vw - 1550px)" size="mini">
+                            <el-table :data="formData.metaNodeTask">
+                                <el-table-column prop="atomTaskIndex" label="索引" align="center" width="50">
+                                    <template v-slot="{ row, $index }">
+                                        {{ $index }}
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="atomTaskId" label="任务" align="center">
+                                    <template v-slot="{ row }">
+                                        <el-select v-model="row.atomTaskId" clearable filterable placeholder="请选择"
+                                            :disabled="!canEdit" style="width: 150px">
+                                            <el-option v-for="item in atomTasks" :key="item.id" :label="item.name"
+                                                :value="item.id">
+                                            </el-option>
+                                        </el-select>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column width="100" label="操作" align="center">
+                                    <template v-slot="{ row, $index }">
+                                        <el-button type="danger" plain size="mini" @click="delNodeTask($index)"
+                                            :disabled="!canEdit">
+                                            删除
+                                        </el-button>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button size="mini" @click="addNodeTask" :disabled="!canEdit"> 添加节点任务 </el-button>
+                        </el-form-item>
+                        <el-form-item prop="metaBranchLineTask" label="支线任务配置" style="width: calc(100vw - 1550px)"
+                            size="mini">
+                            <el-table :data="formData.metaBranchLineTask">
+                                <el-table-column prop="atomTaskIndex" label="索引" align="center" width="50">
+                                    <template v-slot="{ row, $index }">
+                                        {{ $index }}
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="atomTaskId" label="任务" align="center">
+                                    <template v-slot="{ row }">
+                                        <el-select v-model="row.atomTaskId" clearable filterable placeholder="请选择"
+                                            :disabled="!canEdit" style="width: 150px">
+                                            <el-option v-for="item in atomTasks" :key="item.id" :label="item.name"
+                                                :value="item.id">
+                                            </el-option>
+                                        </el-select>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column width="100" label="操作" align="center">
+                                    <template v-slot="{ row, $index }">
+                                        <el-button type="danger" plain size="mini" @click="delBranchLineTask($index)"
+                                            :disabled="!canEdit">
+                                            删除
+                                        </el-button>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button size="mini" @click="addBranchLineTask" :disabled="!canEdit"> 添加支线任务 </el-button>
+                        </el-form-item>
+                    </template>
+                    <template v-if="formData && formData.type == 'BRANCH_LINE'">
+                        <el-form-item prop="metaBranchLineTask" label="支线任务配置" style="width: calc(100vw - 1550px)"
+                            size="mini">
+                            <el-table :data="formData.metaBranchLineTask">
+                                <el-table-column prop="atomTaskIndex" label="索引" align="center" width="50">
+                                    <template v-slot="{ row, $index }">
+                                        {{ $index }}
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="atomTaskId" label="任务" align="center">
+                                    <template v-slot="{ row }">
+                                        <el-select v-model="row.atomTaskId" clearable filterable placeholder="请选择"
+                                            :disabled="!canEdit" style="width: 150px">
+                                            <el-option v-for="item in atomTasks" :key="item.id" :label="item.name"
+                                                :value="item.id">
+                                            </el-option>
+                                        </el-select>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column width="100" label="操作" align="center">
+                                    <template v-slot="{ row, $index }">
+                                        <el-button type="danger" plain size="mini" @click="delBranchLineTask($index)"
+                                            :disabled="!canEdit">
+                                            删除
+                                        </el-button>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button size="mini" @click="addBranchLineTask" :disabled="!canEdit"> 添加支线任务 </el-button>
+                        </el-form-item>
+                    </template>
+                    <template v-if="formData && formData.type == 'DAILY'">
+                        <el-form-item prop="metaDailyTask" label="日常任务配置" style="width: calc(100vw - 1550px)" size="mini">
+                            <el-table :data="formData.metaDailyTask">
+                                <el-table-column prop="atomTaskIndex" label="索引" align="center" width="50">
+                                    <template v-slot="{ row, $index }">
+                                        {{ $index }}
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="atomTaskId" label="任务" align="center">
+                                    <template v-slot="{ row }">
+                                        <el-select v-model="row.atomTaskId" clearable filterable placeholder="请选择"
+                                            :disabled="!canEdit" style="width: 150px">
+                                            <el-option v-for="item in atomTasks" :key="item.id" :label="item.name"
+                                                :value="item.id">
+                                            </el-option>
+                                        </el-select>
+                                    </template>
+                                </el-table-column>
+                                <el-table-column width="100" label="操作" align="center">
+                                    <template v-slot="{ row, $index }">
+                                        <el-button type="danger" plain size="mini" @click="delDailyTask($index)"
+                                            :disabled="!canEdit">
+                                            删除
+                                        </el-button>
+                                    </template>
+                                </el-table-column>
+                            </el-table>
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button size="mini" @click="addDailyTask" :disabled="!canEdit"> 添加日常任务 </el-button>
+                        </el-form-item>
+                    </template>
+                    <el-form-item label="所属频道" prop="channelId">
+                        <el-select v-model="formData.channelId" placeholder="请选择" style="width: 100%" :disabled="!canEdit">
+                            <el-option v-for="item in channels" :key="item.id" :label="item.name" :value="item.id">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item prop="autoReceive" label="是否自动领取">
+                        <el-switch v-model="formData.autoReceive"> </el-switch>
+                    </el-form-item>
+                    <el-form-item prop="publish" label="是否发布">
+                        <el-switch v-model="formData.publish"> </el-switch>
+                    </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: 'MetaTaskNewEdit',
+	created() {
+		if (this.$route.query.id) {
+			this.$http
+				.get('metaTaskNew/get/' + this.$route.query.id)
+				.then(res => {
+					this.formData = res;
+				})
+				.catch(e => {
+					console.log(e);
+					this.$message.error(e.error);
+				});
+		}
+		this.$http.get('/metaChannel/findAll').then(res => {
+			this.channels = res;
+		});
+		this.$http.get('/metaAtomTask/findAll').then(res => {
+			this.atomTasks = res;
+		});
+	},
+	computed: {
+		canEdit() {
+			return !!!this.$route.query.id;
+		}
+	},
+	data() {
+		return {
+			atomTasks: [],
+			channels: [],
+			saving: false,
+			formData: {
+				metaNodeTask: [],
+				metaBranchLineTask: [],
+				metaDailyTask: []
+			},
+			rules: {
+				name: [
+					{
+						required: true,
+						message: '请输入任务名称',
+						trigger: 'blur'
+					}
+				],
+				detail: [
+					{
+						required: true,
+						message: '请输入任务详情',
+						trigger: 'blur'
+					}
+				],
+				type: [
+					{
+						required: true,
+						message: '请输入任务类型',
+						trigger: 'blur'
+					}
+				],
+				channelId: [
+					{
+						required: true,
+						message: '请选择所属频道',
+						trigger: 'blur'
+					}
+				]
+			},
+			typeOptions: [
+				{ label: '主线任务', value: 'MAIN_LINE' },
+				{ label: '支线任务', value: 'BRANCH_LINE' },
+				{ label: '日常任务', value: 'DAILY' }
+			]
+		};
+	},
+	methods: {
+		changeTaskType() {
+			this.formData.metaNodeTask = [];
+			this.formData.metaBranchLineTask = [];
+			this.formData.metaDailyTask = [];
+		},
+		addDailyTask() {
+			this.formData.metaDailyTask.push({
+				atomTaskId: ''
+			});
+		},
+		addBranchLineTask() {
+			this.formData.metaBranchLineTask.push({
+				atomTaskId: ''
+			});
+		},
+		addNodeTask() {
+			this.formData.metaNodeTask.push({
+				atomTaskId: ''
+			});
+		},
+		delDailyTask(i) {
+			this.formData.metaDailyTask.splice(i, 1);
+		},
+		delBranchLineTask(i) {
+			this.formData.metaBranchLineTask.splice(i, 1);
+		},
+		delNodeTask(i) {
+			this.formData.metaNodeTask.splice(i, 1);
+		},
+		onSave() {
+			this.$refs.form.validate(valid => {
+				if (valid) {
+					this.submit();
+				} else {
+					return false;
+				}
+			});
+		},
+		submit() {
+			let data = { ...this.formData };
+			if (data.metaNodeTask) {
+				for (var i = 0; i < data.metaNodeTask.length; i++) {
+					data.metaNodeTask[i].atomTaskIndex = i;
+				}
+			}
+			if (data.metaBranchLineTask) {
+				for (var i = 0; i < data.metaBranchLineTask.length; i++) {
+					data.metaBranchLineTask[i].atomTaskIndex = i;
+				}
+			}
+			if (data.metaDailyTask) {
+				for (var i = 0; i < data.metaDailyTask.length; i++) {
+					data.metaDailyTask[i].atomTaskIndex = i;
+				}
+			}
+			if (data.type === 'MAIN_LINE' && data.metaNodeTask.length <= 0) {
+				this.$message.error('主线任务至少添加一种节点任务');
+			} else if (data.type === 'BRANCH_LINE' && data.metaBranchLineTask.length <= 0) {
+				this.$message.error('至少添加一种支线任务');
+			} else if (data.type === 'DAILY' && data.metaDailyTask.length <= 0) {
+				this.$message.error('至少添加一种日常任务');
+			} else {
+				this.saving = true;
+				this.$http
+					.post('/metaTaskNew/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(`/metaTaskNew/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>

+ 168 - 0
src/main/vue/src/views/MetaTaskNewList.vue

@@ -0,0 +1,168 @@
+<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" align="center" label="ID" width="100">
+			</el-table-column>
+			<el-table-column prop="name" align="center" label="任务名称" width="300">
+			</el-table-column>
+			<el-table-column prop="detail" align="center" label="任务详情">
+			</el-table-column>
+			<el-table-column prop="type" align="center" label="任务分类" :formatter="typeFormatter" width="100">
+			</el-table-column>
+			<el-table-column prop="channelId" align="center" label="所属频道" width="100"></el-table-column>
+			<el-table-column prop="autoReceive" align="center" label="自动领取" width="100">
+				<template slot-scope="{ row }">
+					<el-tag :type="row.autoReceive ? '' : 'info'"> {{ row.autoReceive }} </el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column prop="publish" align="center" label="是否发布" width="100">
+				<template slot-scope="{ row }">
+					<el-tag :type="row.publish ? '' : 'info'"> {{ row.publish }} </el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column label="操作" align="center" fixed="right" width="250">
+				<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">
+			<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: 'MetaTaskNewList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/metaTaskNew/all',
+            downloading: false,
+            typeOptions: [
+                { label: '主线任务', value: 'MAIN_LINE' },
+                { label: '支线任务', value: 'BRANCH_LINE' },
+                { label: '日常任务', value: 'DAILY' }
+            ]
+        };
+    },
+    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: '/metaTaskNewEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/metaTaskNewEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/metaTaskNew/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(`/metaTaskNew/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>

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

@@ -85,8 +85,6 @@ export default {
             url: '/metaTaskToUser/all',
             downloading: false,
             taskTypeOptions: [
-                // { label: '单日签到', value: 'SIGN_IN_SINGLE_DAY' },
-                // { label: '连续多日签到', value: 'SIGN_IN_CONTINUOUS' },
                 { label: '收集藏品', value: 'COLLECT_COLLECTION' },
                 { label: '每日在线时长', value: 'ON_LINE_TIME_DAILY' },
                 { label: '累计', value: 'ACCUMULATE' }

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

@@ -70,8 +70,6 @@ export default {
             url: '/metaUserTaskProgress/all',
             downloading: false,
             taskTypeOptions: [
-                // { label: '单日签到', value: 'SIGN_IN_SINGLE_DAY' },
-                // { label: '连续多日签到', value: 'SIGN_IN_CONTINUOUS' },
                 { label: '收集藏品', value: 'COLLECT_COLLECTION' },
                 { label: '每日在线时长', value: 'ON_LINE_TIME_DAILY' },
                 { label: '累计', value: 'ACCUMULATE' }

+ 6 - 1
src/main/vue/src/widgets/Detail.vue

@@ -28,6 +28,7 @@
         <div class="chart-box">
             <div class="table">
                 <el-table :data="order" border style="width: 100%">
+                    <el-table-column align="center" prop="type" label=""> </el-table-column>
                     <el-table-column align="center" prop="domainOrder" label="元域名"> </el-table-column>
                     <el-table-column align="center" prop="photoAsset" label="星图"> </el-table-column>
                     <el-table-column align="center" prop="auction" label="易拍"> </el-table-column>
@@ -45,6 +46,7 @@
 <script>
 import WidgetCard from './WidgetCard';
 import acc from '../mixins/acc';
+import { format, parse, addMonths, addDays } from 'date-fns';
 
 export default {
     data() {
@@ -80,7 +82,10 @@ export default {
     methods: {
         init() {
             this.$http.get('/statistic/statisticDetail').then(res => {
-                this.order = [{ ...res.today, auction: 0 }];
+                this.order = [
+                    { ...res.today, auction: 0, type: '今天' },
+                    { ...res.yesterday, auction: 0, type: '昨天' }
+                ];
                 this.myChart = new Chart(this.$refs.chart.getContext('2d'), {
                     type: 'bar',
                     data: {

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است