Browse Source

Merge branch 'master_fix0328' into dev

# Conflicts:
#	src/main/java/com/izouma/nineth/service/OrderService.java
#	src/main/vue/src/router.js
wangqifan 3 years ago
parent
commit
4db142352a
100 changed files with 4935 additions and 123 deletions
  1. 5 0
      src/main/java/com/izouma/nineth/config/MetaConstants.java
  2. 54 0
      src/main/java/com/izouma/nineth/domain/MetaAtomTask.java
  3. 1 1
      src/main/java/com/izouma/nineth/domain/MetaParamsConfig.java
  4. 1 0
      src/main/java/com/izouma/nineth/domain/MetaProblem.java
  5. 1 1
      src/main/java/com/izouma/nineth/domain/MetaResourcesLikeRecord.java
  6. 62 0
      src/main/java/com/izouma/nineth/domain/MetaStore.java
  7. 35 0
      src/main/java/com/izouma/nineth/domain/MetaStorePurchaseRecord.java
  8. 12 16
      src/main/java/com/izouma/nineth/domain/MetaTask.java
  9. 38 0
      src/main/java/com/izouma/nineth/domain/MetaTaskBind.java
  10. 59 0
      src/main/java/com/izouma/nineth/domain/MetaTaskNew.java
  11. 13 2
      src/main/java/com/izouma/nineth/domain/MetaTaskToUser.java
  12. 83 0
      src/main/java/com/izouma/nineth/domain/MetaTaskToUserNew.java
  13. 28 0
      src/main/java/com/izouma/nineth/domain/MetaTop.java
  14. 2 0
      src/main/java/com/izouma/nineth/domain/MetaUserGold.java
  15. 2 0
      src/main/java/com/izouma/nineth/domain/MetaUserGoldRecord.java
  16. 39 0
      src/main/java/com/izouma/nineth/domain/MetaUserTaskAwardReceivedRecordNew.java
  17. 3 3
      src/main/java/com/izouma/nineth/domain/MetaUserTaskProgress.java
  18. 53 0
      src/main/java/com/izouma/nineth/domain/MetaUserTaskProgressNew.java
  19. 29 0
      src/main/java/com/izouma/nineth/dto/MetaGoldTopDTO.java
  20. 21 0
      src/main/java/com/izouma/nineth/dto/MetaResourcesLikeDTO.java
  21. 19 0
      src/main/java/com/izouma/nineth/enums/MetaStoreCommodityType.java
  22. 0 22
      src/main/java/com/izouma/nineth/enums/MetaTaskClassification.java
  23. 21 0
      src/main/java/com/izouma/nineth/enums/MetaTaskTarget.java
  24. 4 7
      src/main/java/com/izouma/nineth/enums/MetaTaskType.java
  25. 3 0
      src/main/java/com/izouma/nineth/repo/AssetRepo.java
  26. 21 0
      src/main/java/com/izouma/nineth/repo/MetaAtomTaskRepo.java
  27. 2 0
      src/main/java/com/izouma/nineth/repo/MetaPropRepo.java
  28. 1 1
      src/main/java/com/izouma/nineth/repo/MetaResourcesLikeRecordRepo.java
  29. 11 0
      src/main/java/com/izouma/nineth/repo/MetaStorePurchaseRecordRepo.java
  30. 32 0
      src/main/java/com/izouma/nineth/repo/MetaStoreRepo.java
  31. 26 0
      src/main/java/com/izouma/nineth/repo/MetaTaskBindRepo.java
  32. 27 0
      src/main/java/com/izouma/nineth/repo/MetaTaskNewRepo.java
  33. 21 0
      src/main/java/com/izouma/nineth/repo/MetaTaskToUserNewRepo.java
  34. 16 0
      src/main/java/com/izouma/nineth/repo/MetaTopRepo.java
  35. 7 0
      src/main/java/com/izouma/nineth/repo/MetaUserGoldRecordRepo.java
  36. 7 1
      src/main/java/com/izouma/nineth/repo/MetaUserGoldRepo.java
  37. 15 0
      src/main/java/com/izouma/nineth/repo/MetaUserTaskAwardReceivedRecordNewRepo.java
  38. 18 0
      src/main/java/com/izouma/nineth/repo/MetaUserTaskProgressNewRepo.java
  39. 20 0
      src/main/java/com/izouma/nineth/service/MetaAtomTaskService.java
  40. 20 0
      src/main/java/com/izouma/nineth/service/MetaStorePurchaseRecordService.java
  41. 184 0
      src/main/java/com/izouma/nineth/service/MetaStoreService.java
  42. 110 0
      src/main/java/com/izouma/nineth/service/MetaTaskNewService.java
  43. 306 0
      src/main/java/com/izouma/nineth/service/MetaTaskToUserNewService.java
  44. 16 0
      src/main/java/com/izouma/nineth/service/MetaTaskToUserService.java
  45. 20 0
      src/main/java/com/izouma/nineth/service/MetaTopService.java
  46. 2 0
      src/main/java/com/izouma/nineth/service/MetaUserGoldRecordService.java
  47. 40 19
      src/main/java/com/izouma/nineth/service/MetaUserGoldService.java
  48. 74 0
      src/main/java/com/izouma/nineth/service/MetaUserTaskAwardReceivedRecordNewService.java
  49. 3 3
      src/main/java/com/izouma/nineth/service/MetaUserTaskAwardReceivedRecordService.java
  50. 183 0
      src/main/java/com/izouma/nineth/service/MetaUserTaskProgressNewService.java
  51. 5 5
      src/main/java/com/izouma/nineth/service/MetaUserTaskProgressService.java
  52. 3 0
      src/main/java/com/izouma/nineth/service/UserHoldCountService.java
  53. 43 0
      src/main/java/com/izouma/nineth/utils/MetaTaskTargetConverter.java
  54. 41 0
      src/main/java/com/izouma/nineth/utils/excel/ChatTypeConverter.java
  55. 11 0
      src/main/java/com/izouma/nineth/utils/excel/ExcelUtils.java
  56. 41 0
      src/main/java/com/izouma/nineth/utils/excel/MetaLuckyDrawAwardModelConverter.java
  57. 42 0
      src/main/java/com/izouma/nineth/utils/excel/MetaPropTriggerTypeConverter.java
  58. 41 0
      src/main/java/com/izouma/nineth/utils/excel/MetaPropTypeConverter.java
  59. 42 0
      src/main/java/com/izouma/nineth/utils/excel/MetaPropUsedTypeConverter.java
  60. 42 0
      src/main/java/com/izouma/nineth/utils/excel/MetaResourcesTypeConverter.java
  61. 41 0
      src/main/java/com/izouma/nineth/utils/excel/MetaStoreCommodityTypeConverter.java
  62. 41 0
      src/main/java/com/izouma/nineth/utils/excel/MetaSwitchTypeConverter.java
  63. 3 0
      src/main/java/com/izouma/nineth/web/AirDropController.java
  64. 10 0
      src/main/java/com/izouma/nineth/web/AssetController.java
  65. 65 0
      src/main/java/com/izouma/nineth/web/MetaAtomTaskController.java
  66. 2 2
      src/main/java/com/izouma/nineth/web/MetaProblemController.java
  67. 25 5
      src/main/java/com/izouma/nineth/web/MetaResourcesController.java
  68. 135 0
      src/main/java/com/izouma/nineth/web/MetaStoreController.java
  69. 33 0
      src/main/java/com/izouma/nineth/web/MetaStorePurchaseRecordController.java
  70. 17 2
      src/main/java/com/izouma/nineth/web/MetaTaskController.java
  71. 65 0
      src/main/java/com/izouma/nineth/web/MetaTaskNewController.java
  72. 64 0
      src/main/java/com/izouma/nineth/web/MetaTaskToUserNewController.java
  73. 60 0
      src/main/java/com/izouma/nineth/web/MetaTopController.java
  74. 7 3
      src/main/java/com/izouma/nineth/web/MetaUserGoldController.java
  75. 52 1
      src/main/java/com/izouma/nineth/web/MetaUserGoldRecordController.java
  76. 3 2
      src/main/java/com/izouma/nineth/web/MetaUserTaskAwardReceivedRecordController.java
  77. 39 0
      src/main/java/com/izouma/nineth/web/MetaUserTaskAwardReceivedRecordNewController.java
  78. 51 0
      src/main/java/com/izouma/nineth/web/MetaUserTaskProgressNewController.java
  79. 1 0
      src/main/resources/genjson/MetaAtomTask.json
  80. 0 0
      src/main/resources/genjson/MetaStore.json
  81. 1 0
      src/main/resources/genjson/MetaTaskNew.json
  82. 1 1
      src/main/vue/.env.development
  83. 225 0
      src/main/vue/src/views/MetaAtomTaskEdit.vue
  84. 190 0
      src/main/vue/src/views/MetaAtomTaskList.vue
  85. 11 0
      src/main/vue/src/views/MetaParamsConfigList.vue
  86. 281 0
      src/main/vue/src/views/MetaStoreEdit.vue
  87. 215 0
      src/main/vue/src/views/MetaStoreList.vue
  88. 84 0
      src/main/vue/src/views/MetaStorePurchaseRecordList.vue
  89. 1 21
      src/main/vue/src/views/MetaTaskEdit.vue
  90. 0 2
      src/main/vue/src/views/MetaTaskList.vue
  91. 355 0
      src/main/vue/src/views/MetaTaskNewEdit.vue
  92. 168 0
      src/main/vue/src/views/MetaTaskNewList.vue
  93. 0 2
      src/main/vue/src/views/MetaTaskToUserList.vue
  94. 97 0
      src/main/vue/src/views/MetaTaskToUserNewList.vue
  95. 132 0
      src/main/vue/src/views/MetaTopDetailList.vue
  96. 106 0
      src/main/vue/src/views/MetaTopEdit.vue
  97. 185 0
      src/main/vue/src/views/MetaTopList.vue
  98. 1 1
      src/main/vue/src/views/MetaUserGoldList.vue
  99. 1 0
      src/main/vue/src/views/MetaUserGoldRecordList.vue
  100. 86 0
      src/main/vue/src/views/MetaUserTaskAwardReceivedRecordNewList.vue

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

@@ -12,8 +12,13 @@ public interface MetaConstants {
 
     String META_LUCKY_DRAW_ID = "META_LUCKY_DRAW_ID";
 
+    String META_GOLD_TOP_END_TIME = "META_GOLD_TOP_END_TIME";
+
+    String META_GOLD_TOP_BEGIN_TIME = "META_GOLD_TOP_BEGIN_TIME";
+
     String COMMA = ",";
 
     String BLANK = " ";
 
+    String REDIS_STOCK_PREFIX = "stock:";
 }

+ 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;
+
+}

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

@@ -34,7 +34,7 @@ public class MetaParamsConfig extends AuditedEntity {
     public enum ValueType {
 
         STRING,
-
+        DATETIME,
         BOOLEAN
 
     }

+ 1 - 0
src/main/java/com/izouma/nineth/domain/MetaProblem.java

@@ -23,6 +23,7 @@ public class MetaProblem extends BaseEntity {
     private String title;
 
     @ApiModelProperty("答案")
+    @Column(columnDefinition = "TEXT")
     private String answer;
 
     @ApiModelProperty("文件")

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

@@ -15,7 +15,7 @@ import java.time.LocalDate;
 @ApiModel("元宇宙资源点赞记录")
 public class MetaResourcesLikeRecord extends BaseEntity {
 
-    private Long metaResourcesId;
+    private String metaResourcesName;
 
     private Long userId;
 

+ 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;
+}

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

@@ -1,21 +1,18 @@
 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.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;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
+import javax.persistence.*;
 
 @Data
 @AllArgsConstructor
@@ -37,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("参数")
@@ -77,12 +69,16 @@ 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;
+
+    @Transient
+    @ExcelIgnore
+    private MetaProp metaProp;
 }

+ 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;
+}

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

@@ -0,0 +1,59 @@
+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;
+
+    @Transient
+    private List<MetaTaskBind> metaNodeTask;
+
+    @Transient
+    private List<MetaTaskBind> metaBranchLineTask;
+
+    @Transient
+    private List<MetaTaskBind> metaDailyTask;
+
+}

+ 13 - 2
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)
@@ -78,4 +86,7 @@ public class MetaTaskToUser extends BaseEntity {
     @ApiModelProperty("进度")
     @ExcelIgnore
     private String process;
+
+    @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;
+}

+ 28 - 0
src/main/java/com/izouma/nineth/domain/MetaTop.java

@@ -0,0 +1,28 @@
+package com.izouma.nineth.domain;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙排行榜管理")
+public class MetaTop extends BaseEntity{
+
+    @ApiModelProperty("排行榜名称")
+    private String name;
+
+    @ApiModelProperty("排行榜用途")
+    private String rule;
+
+    @ApiModelProperty("配置图片")
+    private String pic;
+
+}

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

@@ -1,6 +1,7 @@
 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;
@@ -16,6 +17,7 @@ import javax.persistence.Entity;
 @ApiModel("元宇宙玩家金币")
 public class MetaUserGold extends BaseEntity {
 
+    @Searchable
     @ApiModelProperty("用户id")
     @ExcelProperty("用户id")
     private Long userId;

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

@@ -1,6 +1,7 @@
 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;
@@ -16,6 +17,7 @@ import javax.persistence.Entity;
 @ApiModel("元宇宙玩家金币明细")
 public class MetaUserGoldRecord extends BaseEntity {
 
+    @Searchable
     @ApiModelProperty("用户id")
     @ExcelProperty("用户id")
     private Long userId;

+ 39 - 0
src/main/java/com/izouma/nineth/domain/MetaUserTaskAwardReceivedRecordNew.java

@@ -0,0 +1,39 @@
+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 MetaUserTaskAwardReceivedRecordNew extends BaseEntity {
+
+    @Searchable
+    @ApiModelProperty("用户id")
+    @ExcelProperty("用户id")
+    private Long userId;
+
+    @Searchable
+    @ApiModelProperty("任务id")
+    @ExcelProperty("任务id")
+    private Long taskId;
+
+    @Searchable
+    @ApiModelProperty("原子任务id")
+    @ExcelProperty("原子任务id")
+    private Long atomTaskId;
+
+    @ApiModelProperty("领取时间")
+    @ExcelProperty("领取时间")
+    private LocalDateTime receivedTime;
+}

+ 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("任务名称")

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

@@ -0,0 +1,53 @@
+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;
+import java.time.LocalDateTime;
+
+@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("进度上传时间")
+    @ExcelProperty("进度上传时间")
+    private LocalDateTime progressTime;
+
+    @ApiModelProperty("备注参数是否唯一,例如收集彩蛋的任务每个备注(彩蛋id)不允许重复完成")
+    @ExcelProperty("备注参数是否唯一")
+    private boolean remarkOnly;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("任务详情")
+    private MetaTaskNew metaTaskNew;
+
+    @Transient
+    @ExcelIgnore
+    @ApiModelProperty("原子任务详情")
+    private MetaAtomTask metaAtomTask;
+}

+ 29 - 0
src/main/java/com/izouma/nineth/dto/MetaGoldTopDTO.java

@@ -0,0 +1,29 @@
+package com.izouma.nineth.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class MetaGoldTopDTO {
+
+    @ApiModelProperty("用户Id")
+    @ExcelProperty("用户ID")
+    private Long userId;
+
+    @ApiModelProperty("用户头像")
+    @ExcelProperty("头像")
+    private String head;
+
+    @ApiModelProperty("用户昵称")
+    @ExcelProperty("昵称")
+    private String nickName;
+
+    @ApiModelProperty("用户金币数量")
+    @ExcelProperty("金币数量")
+    private Long num;
+}

+ 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 = false;
+
+}

+ 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;
@@ -183,4 +184,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);
+}

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

@@ -16,4 +16,6 @@ public interface MetaPropRepo extends JpaRepository<MetaProp, Long>, JpaSpecific
     void softDelete(Long id);
 
     List<MetaProp> findAllByDel(boolean del);
+
+    MetaProp findByIdAndDel(Long id, boolean del);
 }

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

@@ -8,5 +8,5 @@ import java.time.LocalDate;
 
 public interface MetaResourcesLikeRecordRepo extends JpaRepository<MetaResourcesLikeRecord, Long>, JpaSpecificationExecutor<MetaResourcesLikeRecord> {
 
-    MetaResourcesLikeRecord findByMetaResourcesIdAndUserIdAndLikeTime(Long metaResourcesId, Long userId, LocalDate likeTime);
+    MetaResourcesLikeRecord findByMetaResourcesNameAndUserIdAndLikeTime(String name, Long userId, LocalDate likeTime);
 }

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

@@ -0,0 +1,11 @@
+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;
+
+
+public interface MetaStorePurchaseRecordRepo extends JpaRepository<MetaStorePurchaseRecord, Long>, JpaSpecificationExecutor<MetaStorePurchaseRecord> {
+
+    int countByMetaStoreIdAndUserId(Long metaStoreId, Long userId);
+}

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

@@ -0,0 +1,32 @@
+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);
+
+    @Query("update MetaStore t set t.stockNum = ?2 where t.id = ?1")
+    @Modifying
+    @Transactional
+    void updateStockNum(Long updateStockNum, int stockNum);
+
+}

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

@@ -0,0 +1,26 @@
+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(value = "select m.atom_task_id from meta_task_bind m where m.task_id = ?1 and m.type = ?2 and m.del = false order by m.atom_task_index asc limit 1", nativeQuery = true)
+    Long findAtomTaskId(Long taskId, String type);
+
+    @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);
+
+}

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

@@ -0,0 +1,27 @@
+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);
+
+    @Query(value = "select m1 from MetaTaskNew m1 where m1.autoReceive = true and m1.del = false and m1.id not in (select m2.taskId from MetaTaskToUserNew m2 where m2.userId = ?1 and m2.del = false)")
+    List<MetaTaskNew> findUnReceivedAndAutoReceivedTask(Long userId);
+
+    List<MetaTaskNew> findAllByPublishAndDel(boolean publish, 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);
+}

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

@@ -0,0 +1,21 @@
+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);
+
+    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);
+
+}

+ 16 - 0
src/main/java/com/izouma/nineth/repo/MetaTopRepo.java

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

+ 7 - 0
src/main/java/com/izouma/nineth/repo/MetaUserGoldRecordRepo.java

@@ -1,16 +1,23 @@
 package com.izouma.nineth.repo;
 
 import com.izouma.nineth.domain.MetaUserGoldRecord;
+import com.izouma.nineth.dto.MetaGoldTopDTO;
+import org.springframework.data.domain.Pageable;
 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;
+import java.util.Map;
 
 public interface MetaUserGoldRecordRepo extends JpaRepository<MetaUserGoldRecord, Long>, JpaSpecificationExecutor<MetaUserGoldRecord> {
     @Query("update MetaUserGoldRecord t set t.del = true where t.id = ?1")
     @Modifying
     @Transactional
     void softDelete(Long id);
+
+    @Query(value = "select user_id userId,sum(operation_num) num,nickname nickName,avatar head from meta_user_gold_record inner join user u on meta_user_gold_record.user_id = u.id where meta_user_gold_record.created_at between ?1 and ?2 and operation_num > 0 group by user_id  order by sum(operation_num) desc",nativeQuery = true)
+    List<Map<String,String>> top(String beginTime, String endTime);
 }

+ 7 - 1
src/main/java/com/izouma/nineth/repo/MetaUserGoldRepo.java

@@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.Query;
 
 import javax.transaction.Transactional;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 
 public interface MetaUserGoldRepo extends JpaRepository<MetaUserGold, Long>, JpaSpecificationExecutor<MetaUserGold> {
@@ -16,7 +17,12 @@ public interface MetaUserGoldRepo extends JpaRepository<MetaUserGold, Long>, Jpa
     @Transactional
     void softDelete(Long id);
 
-    MetaUserGold findByUserIdAndDel(Long userId, boolean del);
+    Optional<MetaUserGold> findByUserIdAndDel(Long userId, boolean del);
 
     List<MetaUserGold> findAllByUserIdInAndDel(Set<Long> userIds, boolean del);
+
+    @Query("update MetaUserGold m set m.num = ?2 where m.userId = ?1")
+    @Modifying
+    @Transactional
+    void updateNumByUserId(Long userId, int num);
 }

+ 15 - 0
src/main/java/com/izouma/nineth/repo/MetaUserTaskAwardReceivedRecordNewRepo.java

@@ -0,0 +1,15 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaUserTaskAwardReceivedRecordNew;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.time.LocalDateTime;
+
+public interface MetaUserTaskAwardReceivedRecordNewRepo extends JpaRepository<MetaUserTaskAwardReceivedRecordNew, Long>, JpaSpecificationExecutor<MetaUserTaskAwardReceivedRecordNew> {
+
+    MetaUserTaskAwardReceivedRecordNew findByUserIdAndTaskIdAndAtomTaskIdAndDel(Long userId, Long taskId, Long atomTaskId, boolean del);
+
+    MetaUserTaskAwardReceivedRecordNew findByUserIdAndTaskIdAndAtomTaskIdAndDelAndReceivedTimeAfter(Long userId, Long taskId, Long atomTaskId, boolean del, LocalDateTime receivedTime);
+
+}

+ 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);
+
+}

+ 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));
+    }
+}

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

@@ -0,0 +1,184 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.annotations.RedisLock;
+import com.izouma.nineth.config.Constants;
+import com.izouma.nineth.config.MetaConstants;
+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.lang.StringUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.Objects;
+
+@Service
+@AllArgsConstructor
+public class MetaStoreService {
+
+    private RedisTemplate<String, String> redisTemplate;
+
+    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);
+    }
+
+    @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("购买成功!");
+
+    }
+
+    @Transactional
+    @RedisLock("'updateStockNumLock::'+#metaStore.getId()")
+    public MetaRestResult<Void> purchaseNFT(MetaStore metaStore, Long userId) {
+        int price = metaStore.getPrice();
+        if (price <= 0) {
+            return MetaRestResult.returnError("购买失败,道具价格不合法");
+        }
+        // 从缓存中获取库存
+        int stockNum = getStockNumFromCache(metaStore.getId());
+        if (stockNum <= 0) {
+            return MetaRestResult.returnError("购买失败,库存不足");
+        }
+        // 限购
+        if (isPurchaseLimitReached(metaStore.getId(), userId, 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());
+        }
+        // 更新库存
+        updateStockNum(metaStore.getId(), stockNum - 1);
+        // 保存购买记录
+        metaStorePurchaseRecordRepo.save(new MetaStorePurchaseRecord(metaStore.getId(), userId, LocalDateTime.now()));
+        return MetaRestResult.returnSuccess("购买成功!");
+    }
+
+
+    /**
+     * 从 Redis 中获取库存信息
+     *
+     * @param metaStoreId 商品id
+     * @return 库存数量
+     */
+    private int getStockNumFromCache(Long metaStoreId) {
+        String key = MetaConstants.REDIS_STOCK_PREFIX.concat(String.valueOf(metaStoreId));
+        String stockStr = redisTemplate.opsForValue().get(key);
+        if (StringUtils.isNotBlank(stockStr)) {
+            return Integer.parseInt(stockStr);
+        }
+        // 如果 Redis 中不存在,则从数据库中加载,并写入 Redis 缓存
+        MetaStore metaStore = metaStoreRepo.findByIdAndDel(metaStoreId, false);
+        if (metaStore != null) {
+            int stockNum = metaStore.getStockNum();
+            redisTemplate.opsForValue().set(key, String.valueOf(stockNum), Duration.ofMinutes(5)); // 设置过期时间 5 分钟
+            return stockNum;
+        }
+        return 0;
+    }
+
+    /**
+     * 更新 Redis 中的库存信息,异步更新数据库中的库存
+     *
+     * @param metaStoreId 商品id
+     * @param stockNum    库存数量
+     */
+    @RedisLock("'updateStockNumLock::'+#metaStoreId")
+    public void updateStockNum(Long metaStoreId, int stockNum) {
+        String key = MetaConstants.REDIS_STOCK_PREFIX.concat(String.valueOf(metaStoreId));
+        redisTemplate.opsForValue().set(key, String.valueOf(stockNum), Duration.ofMinutes(5)); // 设置过期时间 5 分钟
+        metaStoreRepo.updateStockNum(metaStoreId, stockNum);
+    }
+
+    /**
+     * 判断是否达到购买限制
+     *
+     * @param metaStoreId      商品id
+     * @param userId           用户id
+     * @param purchaseLimitNum 最大购买数量
+     * @return 是否达到购买限制
+     */
+    private boolean isPurchaseLimitReached(Long metaStoreId, Long userId, Integer purchaseLimitNum) {
+        if (purchaseLimitNum == null || purchaseLimitNum <= 0) {
+            return false;
+        }
+        int count = metaStorePurchaseRecordRepo.countByMetaStoreIdAndUserId(metaStoreId, userId);
+        return count >= purchaseLimitNum;
+    }
+
+}

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

@@ -0,0 +1,110 @@
+package com.izouma.nineth.service;
+
+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.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;
+
+import java.util.List;
+
+@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));
+    }
+
+    public MetaTaskNew get(Long id) {
+        MetaTaskNew metaTaskNew = metaTaskNewRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+        buildAtomTask(metaTaskNew);
+        return metaTaskNew;
+    }
+
+    public MetaRestResult<List<MetaTaskNew>> canGet(Long userId, Long channelId) {
+        List<MetaTaskNew> metaTaskNews = metaTaskNewRepo.canGet(userId, channelId);
+        metaTaskNews.forEach(this::buildAtomTask);
+        return MetaRestResult.returnSuccess(metaTaskNews);
+    }
+
+    private void buildAtomTask(MetaTaskNew metaTaskNew) {
+        if (MetaTaskType.MAIN_LINE.equals(metaTaskNew.getType())) {
+            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);
+            }
+            return;
+        }
+        if (MetaTaskType.BRANCH_LINE.equals(metaTaskNew.getType())) {
+            List<MetaTaskBind> metaBranchLineTask = metaTaskBindRepo.findByTaskIdAndTypeAndDel(metaTaskNew.getId(), MetaTaskType.BRANCH_LINE, false);
+            if (CollectionUtils.isNotEmpty(metaBranchLineTask)) {
+                metaTaskNew.setMetaBranchLineTask(metaBranchLineTask);
+            }
+            return;
+        }
+        if (MetaTaskType.DAILY.equals(metaTaskNew.getType())) {
+            List<MetaTaskBind> metaDailyTask = metaTaskBindRepo.findByTaskIdAndTypeAndDel(metaTaskNew.getId(), MetaTaskType.DAILY, false);
+            if (CollectionUtils.isNotEmpty(metaDailyTask)) {
+                metaTaskNew.setMetaDailyTask(metaDailyTask);
+            }
+        }
+    }
+}

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

@@ -0,0 +1,306 @@
+package com.izouma.nineth.service;
+
+import cn.hutool.core.collection.CollectionUtil;
+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;
+
+@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.findUnReceivedAndAutoReceivedTask(userId);
+        if (CollectionUtil.isNotEmpty(metaTaskNews)) {
+            metaTaskNews.forEach(metaTaskNew -> {
+                MetaTaskToUserNew 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.toString());
+                    if (Objects.nonNull(atomTaskId)) {
+                        metaTaskToUserNew.setAtomTaskId(atomTaskId);
+                    }
+                }
+                if (MetaTaskType.BRANCH_LINE.equals(metaTaskNew.getType())) {
+                    Long atomTaskId = metaTaskBindRepo.findAtomTaskId(metaTaskNew.getId(), MetaTaskType.BRANCH_LINE.toString());
+                    if (Objects.nonNull(atomTaskId)) {
+                        metaTaskToUserNew.setAtomTaskId(atomTaskId);
+                    }
+                }
+                if (MetaTaskType.DAILY.equals(metaTaskNew.getType())) {
+                    Long atomTaskId = metaTaskBindRepo.findAtomTaskId(metaTaskNew.getId(), MetaTaskType.DAILY.toString());
+                    if (Objects.nonNull(atomTaskId)) {
+                        metaTaskToUserNew.setAtomTaskId(atomTaskId);
+                    }
+                }
+                MetaRestResult<MetaTaskToUserNew> result = receiveTask(metaTaskToUserNew, false);
+                if (Constants.MetaRestCode.success != result.getCode()) {
+                    throw new BusinessException(result.getMessage());
+                }
+            });
+            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());
+        }
+        metaTaskToUserNew.setMetaTaskNew(metaTaskNew);
+        MetaAtomTask metaAtomTask = metaAtomTaskRepo.findByIdAndDel(metaTaskToUserNew.getAtomTaskId(), false);
+        MetaServiceResult checkMetaAtomTaskResult = checkMetaAtomTask(metaAtomTask);
+        if (!checkMetaAtomTaskResult.isSuccess()) {
+            return MetaRestResult.returnError(checkMetaAtomTaskResult.getMessage());
+        }
+        metaTaskToUserNew.setMetaAtomTask(metaAtomTask);
+        MetaServiceResult buildMetaPropResult = buildMetaProp(metaTaskToUserNew);
+        if (!buildMetaPropResult.isSuccess()) {
+            return MetaRestResult.returnError(buildMetaPropResult.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);
+        save.setMetaTaskNew(metaTaskToUserNew.getMetaTaskNew());
+        save.setMetaAtomTask(metaTaskToUserNew.getMetaAtomTask());
+        save.setMetaProp(metaTaskToUserNew.getMetaProp());
+        if (progress) {
+            setProgress(save);
+        }
+        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 checkMetaAtomTaskResult = checkMetaAtomTask(metaAtomTask);
+        if (!checkMetaAtomTaskResult.isSuccess()) {
+            return MetaRestResult.returnError(checkMetaAtomTaskResult.getMessage());
+        }
+        metaTaskToUserNew.setMetaAtomTask(metaAtomTask);
+        MetaTaskNew metaTaskNew = metaTaskNewRepo.findByIdAndDel(metaTaskToUserNew.getTaskId(), false);
+        MetaServiceResult checkMetaTaskNewResult = checkMetaTaskNew(metaTaskNew);
+        if (!checkMetaTaskNewResult.isSuccess()) {
+            return MetaRestResult.returnError(checkMetaTaskNewResult.getMessage());
+        }
+        metaTaskToUserNew.setMetaTaskNew(metaTaskNew);
+        MetaServiceResult buildMetaPropResult = buildMetaProp(metaTaskToUserNew);
+        if (!buildMetaPropResult.isSuccess()) {
+            return MetaRestResult.returnError(buildMetaPropResult.getMessage());
+        }
+        setProgress(metaTaskToUserNew);
+        return MetaRestResult.returnSuccess(metaTaskToUserNew);
+    }
+
+    /**
+     * 设置任务进度
+     *
+     * @param metaTaskToUserNew 任务领取信息
+     */
+    private void setProgress(MetaTaskToUserNew metaTaskToUserNew) {
+        MetaAtomTask metaAtomTask = metaTaskToUserNew.getMetaAtomTask();
+        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 (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();
+    }
+
+    /**
+     * 道具奖励 构建道具信息
+     *
+     * @param metaTaskToUserNew 任务领取信息
+     * @return result
+     */
+    private MetaServiceResult buildMetaProp(MetaTaskToUserNew metaTaskToUserNew) {
+        if (!MetaAwardTypeEnum.META_PROP.equals(metaTaskToUserNew.getMetaAtomTask().getAwardType())) {
+            return MetaServiceResult.returnSuccess();
+        }
+        MetaProp metaProp = metaPropRepo.findByIdAndDel(Long.parseLong(metaTaskToUserNew.getMetaAtomTask().getAwardConfig()), false);
+        if (Objects.isNull(metaProp)) {
+            return MetaServiceResult.returnError(String.format("基础任务[%S]道具奖励 道具信息为空", metaTaskToUserNew.getMetaAtomTask().getId()));
+        }
+        metaTaskToUserNew.setMetaProp(metaProp);
+        return MetaServiceResult.returnSuccess();
+    }
+}

+ 16 - 0
src/main/java/com/izouma/nineth/service/MetaTaskToUserService.java

@@ -1,12 +1,14 @@
 package com.izouma.nineth.service;
 
 import com.alibaba.excel.util.CollectionUtils;
+import com.izouma.nineth.domain.MetaProp;
 import com.izouma.nineth.domain.MetaTask;
 import com.izouma.nineth.domain.MetaTaskToUser;
 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.repo.MetaPropRepo;
 import com.izouma.nineth.repo.MetaTaskRepo;
 import com.izouma.nineth.repo.MetaTaskToUserRepo;
 import com.izouma.nineth.repo.MetaUserTaskProgressRepo;
@@ -36,6 +38,8 @@ public class MetaTaskToUserService {
 
     private final String PREFIX = "0/";
 
+    private MetaPropRepo metaPropRepo;
+
     public Page<MetaTaskToUser> all(PageQuery pageQuery) {
         return metaTaskToUserRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaTaskToUser.class), JpaUtils.toPageRequest(pageQuery));
     }
@@ -80,6 +84,12 @@ public class MetaTaskToUserService {
         if (Objects.nonNull(metaTask.getAwardPic())) {
             metaTaskToUser.setAwardPic(metaTask.getAwardPic());
         }
+        if (metaTask.getGoldNum() > 0) {
+            metaTaskToUser.setGoldNum(metaTask.getGoldNum());
+        }
+        if (Objects.nonNull(metaTask.getMetaPropId())) {
+            metaTaskToUser.setMetaPropId(metaTask.getMetaPropId());
+        }
         metaTaskToUser.setTaskName(metaTask.getName());
         metaTaskToUser.setTaskType(metaTask.getType());
         metaTaskToUser.setDetail(metaTask.getDetail());
@@ -115,6 +125,12 @@ public class MetaTaskToUserService {
      * @param metaTaskToUser 参数
      */
     private void setProgress(MetaTaskToUser metaTaskToUser) {
+        if (Objects.nonNull(metaTaskToUser.getMetaPropId())) {
+            MetaProp metaProp = metaPropRepo.findByIdAndDel(metaTaskToUser.getMetaPropId(), false);
+            if (Objects.nonNull(metaProp)) {
+                metaTaskToUser.setMetaProp(metaProp);
+            }
+        }
         MetaTask metaTask = metaTaskRepo.findByIdAndDel(metaTaskToUser.getTaskId(), false);
         if (Objects.isNull(metaTask)) {
             log.error("任务信息为空");

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

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

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

@@ -2,6 +2,8 @@ package com.izouma.nineth.service;
 
 import com.izouma.nineth.domain.MetaUserGoldRecord;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.PageWrapper;
+import com.izouma.nineth.dto.UserHoldDTO;
 import com.izouma.nineth.repo.MetaUserGoldRecordRepo;
 import com.izouma.nineth.utils.JpaUtils;
 import lombok.AllArgsConstructor;

+ 40 - 19
src/main/java/com/izouma/nineth/service/MetaUserGoldService.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.service;
 
+import com.izouma.nineth.annotations.RedisLock;
 import com.izouma.nineth.domain.MetaUserGold;
 import com.izouma.nineth.domain.MetaUserGoldRecord;
 import com.izouma.nineth.dto.MetaRestResult;
@@ -17,6 +18,7 @@ import org.springframework.stereotype.Service;
 
 import javax.transaction.Transactional;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
@@ -35,13 +37,13 @@ public class MetaUserGoldService {
 
     @Transactional
     public void initMetaUserGold(String userIds) {
-        String[] split = userIds.split(" ");
-        List<MetaUserGold> metaUserGolds = new ArrayList<>();
-        List<MetaUserGoldRecord> metaUserGoldRecords = new ArrayList<>();
-        Arrays.stream(split).forEach(userId -> {
-            metaUserGolds.add(new MetaUserGold(Long.parseLong(userId), 0));
-            metaUserGoldRecords.add(new MetaUserGoldRecord(Long.parseLong(userId), 0, 0, 0, "初始化"));
-        });
+        List<MetaUserGold> metaUserGolds = Arrays.stream(userIds.split(" "))
+                                                 .map(Long::parseLong)
+                                                 .map(userId -> new MetaUserGold(userId, 0))
+                                                 .collect(Collectors.toList());
+        List<MetaUserGoldRecord> metaUserGoldRecords = metaUserGolds.stream()
+                                                                    .map(metaUserGold -> new MetaUserGoldRecord(metaUserGold.getUserId(), 0, 0, 0, "初始化"))
+                                                                    .collect(Collectors.toList());
         metaUserGoldRepo.saveAll(metaUserGolds);
         metaUserGoldRecordRepo.saveAll(metaUserGoldRecords);
     }
@@ -66,27 +68,46 @@ public class MetaUserGoldService {
         }
     }
 
+    /**
+     * 操作金币
+     *
+     * @param userId 玩家id
+     * @param num    操作数量(负数代表扣减)
+     * @param remark 备注信息
+     * @return result
+     */
     @Transactional
+    @RedisLock("'userGoldLock::'+#userId")
     public MetaRestResult<MetaUserGold> changeNum(Long userId, int num, String remark) {
-        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false);
-        if (Objects.isNull(metaUserGold)) {
-            log.info(String.format("不存在用户[%S]记录。默认初始化", userId));
-            initMetaUserGold(String.valueOf(userId));
-            metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false);
+        Objects.requireNonNull(userId, "用户ID不能为空");
+        Objects.requireNonNull(remark, "备注不能为空");
+        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false)
+                                                    .orElseGet(() -> {
+                                                        log.info(String.format("不存在用户[%S]记录。默认初始化", userId));
+                                                        initMetaUserGold(String.valueOf(userId));
+                                                        return metaUserGoldRepo.findByUserIdAndDel(userId, false).orElse(null);
+                                                    });
+        if (metaUserGold == null) {
+            throw new RuntimeException(String.format("无法初始化用户[%S]记录", userId));
         }
-        // 操作前金币数量
         int nowNum = metaUserGold.getNum();
+        int afterNum;
+        try {
+            afterNum = Math.addExact(nowNum, num);
+        } catch (Exception e) {
+            throw new RuntimeException(String.format("金额操作发生异常[%S]", e.getMessage()));
+        }
+        if (afterNum < 0) {
+            throw new RuntimeException(String.format("用户[%S] 当前金币剩余[%S],无法进行数量为[%S]的操作", userId, nowNum, -num));
+        }
         MetaUserGoldRecord metaUserGoldRecord = new MetaUserGoldRecord();
         metaUserGoldRecord.setUserId(userId);
         metaUserGoldRecord.setBeforeNum(nowNum);
-        metaUserGoldRecord.setAfterNum(nowNum + num);
+        metaUserGoldRecord.setAfterNum(afterNum);
         metaUserGoldRecord.setOperationNum(num);
         metaUserGoldRecord.setRemark(remark);
-        if (metaUserGoldRecord.getAfterNum() < 0) {
-            return MetaRestResult.returnError(String.format("用户[%S] 当前金币剩余[%S] 本次操作需要金币数量为[%S]", userId, nowNum, -num));
-        }
-        metaUserGold.setNum(nowNum + num);
         metaUserGoldRecordRepo.save(metaUserGoldRecord);
-        return MetaRestResult.returnSuccess(metaUserGoldRepo.save(metaUserGold));
+        metaUserGoldRepo.updateNumByUserId(userId, afterNum);
+        return MetaRestResult.returnSuccess(metaUserGold);
     }
 }

+ 74 - 0
src/main/java/com/izouma/nineth/service/MetaUserTaskAwardReceivedRecordNewService.java

@@ -0,0 +1,74 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.MetaAtomTask;
+import com.izouma.nineth.domain.MetaTaskToUserNew;
+import com.izouma.nineth.domain.MetaUserTaskAwardReceivedRecordNew;
+import com.izouma.nineth.dto.MetaAwardReceiveDTO;
+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.repo.MetaAtomTaskRepo;
+import com.izouma.nineth.repo.MetaTaskToUserNewRepo;
+import com.izouma.nineth.repo.MetaUserTaskAwardReceivedRecordNewRepo;
+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 javax.transaction.Transactional;
+import java.time.LocalDateTime;
+import java.util.Objects;
+
+@Service
+@AllArgsConstructor
+public class MetaUserTaskAwardReceivedRecordNewService {
+
+    private MetaUserTaskAwardReceivedRecordNewRepo metaUserTaskAwardReceivedRecordNewRepo;
+
+    private MetaTaskToUserNewRepo metaTaskToUserNewRepo;
+
+    private MetaAtomTaskRepo metaAtomTaskRepo;
+
+    private MetaAwardReceiveService metaAwardReceiveService;
+
+    public Page<MetaUserTaskAwardReceivedRecordNew> all(PageQuery pageQuery) {
+        return metaUserTaskAwardReceivedRecordNewRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaUserTaskAwardReceivedRecordNew.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    @Transactional
+    public MetaRestResult<Void> receiveAward(Long taskId, Long atomTaskId) {
+        Long userId = SecurityUtils.getAuthenticatedUser().getId();
+        MetaAtomTask metaAtomTask = metaAtomTaskRepo.findByIdAndDel(atomTaskId, false);
+        if (Objects.isNull(metaAtomTask)) {
+            return MetaRestResult.returnError("奖励领取失败:基础任务不存在!");
+        }
+        MetaTaskToUserNew metaTaskToUserNew = metaTaskToUserNewRepo.findByUserIdAndTaskIdAndAtomTaskIdAndDel(userId, taskId, atomTaskId, false);
+        if (Objects.isNull(metaTaskToUserNew)) {
+            return MetaRestResult.returnError("奖励领取失败:用户未领取过该任务!");
+        }
+        if (MetaTaskStatus.PROGRESS.equals(metaTaskToUserNew.getStatus()) || MetaTaskStatus.FINISH.equals(metaTaskToUserNew.getStatus())) {
+            return MetaRestResult.returnError(String.format("奖励领取失败:当前任务状态为[%S]", metaTaskToUserNew.getStatus().getDescription()));
+        }
+        if (MetaTaskTarget.ON_LINE_TIME_DAILY.equals(metaAtomTask.getTargetType())) {
+            MetaUserTaskAwardReceivedRecordNew metaUserTaskAwardReceivedRecordNew = metaUserTaskAwardReceivedRecordNewRepo.findByUserIdAndTaskIdAndAtomTaskIdAndDelAndReceivedTimeAfter(userId, taskId, atomTaskId, false, LocalDateTime.now().withHour(0).withMinute(0).withSecond(0));
+            if (Objects.nonNull(metaUserTaskAwardReceivedRecordNew)) {
+                return MetaRestResult.returnError("奖励领取失败:用户今天已经领取过该任务奖励,不可重复领取!");
+            }
+        }
+        if (!MetaTaskTarget.ON_LINE_TIME_DAILY.equals(metaAtomTask.getTargetType())) {
+            MetaUserTaskAwardReceivedRecordNew metaUserTaskAwardReceivedRecordNew = metaUserTaskAwardReceivedRecordNewRepo.findByUserIdAndTaskIdAndAtomTaskIdAndDel(userId, taskId, atomTaskId, false);
+            if (Objects.nonNull(metaUserTaskAwardReceivedRecordNew)) {
+                return MetaRestResult.returnError("奖励领取失败:用户已经领取过该任务奖励,不可重复领取!");
+            }
+        }
+        MetaServiceResult receive = metaAwardReceiveService.receive(new MetaAwardReceiveDTO(metaAtomTask.getAwardType(), metaAtomTask.getAwardConfig(), userId, "基础任务" + atomTaskId));
+        if (!receive.isSuccess()) {
+            return MetaRestResult.returnError(receive.getMessage());
+        }
+        metaUserTaskAwardReceivedRecordNewRepo.save(new MetaUserTaskAwardReceivedRecordNew(userId, taskId, atomTaskId, LocalDateTime.now()));
+        return MetaRestResult.returnSuccess(receive.getMessage());
+    }
+}

+ 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("奖励领取失败:用户已经领取过该任务奖励,不可重复领取!");

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

@@ -0,0 +1,183 @@
+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("该任务未配置达标次数");
+            }
+        }
+        metaUserTaskProgressNew.setProgressTime(LocalDateTime.now());
+        // 在线时长任务 如记录存在则更新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));
+            dbMetaUserTaskProgressNew.setProgressTime(LocalDateTime.now());
+            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);

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

@@ -22,8 +22,11 @@ public class UserHoldCountService {
         if (Boolean.FALSE.equals(redisTemplate.hasKey(Constants.USER_HOLD_CACHE_KEY))) {
             throw new BusinessException("key失效,请刷新!如果已经刷新,请等待!");
         }
+        // 当前页
         int page = pageQuery.getPage();
+        // pageSize 每页查询多少条数据
         int size = pageQuery.getSize();
+        // limit 开始偏移量
         int start = page * size;
         List<UserHoldDTO> userHoldDTOS = (List<UserHoldDTO>) redisTemplate.opsForValue().get(Constants.USER_HOLD_CACHE_KEY);
         int totalElements;

+ 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;
+    }
+}
+

+ 41 - 0
src/main/java/com/izouma/nineth/utils/excel/ChatTypeConverter.java

@@ -0,0 +1,41 @@
+package com.izouma.nineth.utils.excel;
+
+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.ChatType;
+
+public class ChatTypeConverter implements Converter<ChatType> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return ChatType.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public ChatType convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (ChatType value : ChatType.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(ChatType value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

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

@@ -1,6 +1,7 @@
 package com.izouma.nineth.utils.excel;
 
 import com.alibaba.excel.EasyExcel;
+import com.izouma.nineth.utils.MetaTaskTargetConverter;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -23,6 +24,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())
@@ -41,6 +43,15 @@ public class ExcelUtils<T> {
                 .registerConverter(new MoveTypeConverter())
                 .registerConverter(new MetaAwardTypeEnumConverter())
                 .registerConverter(new MetaPurchaseMethodEnumConverter())
+                .registerConverter(new MetaTaskTargetConverter())
+                .registerConverter(new MetaStoreCommodityTypeConverter())
+                .registerConverter(new MetaResourcesTypeConverter())
+                .registerConverter(new ChatTypeConverter())
+                .registerConverter(new MetaSwitchTypeConverter())
+                .registerConverter(new MetaPropTypeConverter())
+                .registerConverter(new MetaLuckyDrawAwardModelConverter())
+                .registerConverter(new MetaPropTriggerTypeConverter())
+                .registerConverter(new MetaPropUsedTypeConverter())
                 .doWrite(data);
     }
 }

+ 41 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaLuckyDrawAwardModelConverter.java

@@ -0,0 +1,41 @@
+package com.izouma.nineth.utils.excel;
+
+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.alibaba.fastjson.JSON;
+import com.izouma.nineth.domain.MetaGameAward;
+import com.izouma.nineth.domain.MetaLuckyDrawAwardModel;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Objects;
+
+public class MetaLuckyDrawAwardModelConverter implements Converter<MetaLuckyDrawAwardModel> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaLuckyDrawAwardModel.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaLuckyDrawAwardModel convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (StringUtils.isEmpty(cellData.getStringValue())) {
+            return null;
+        }
+        return JSON.parseObject(cellData.getStringValue(), MetaLuckyDrawAwardModel.class);
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaLuckyDrawAwardModel value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (Objects.nonNull(value)) {
+            return new CellData(JSON.toJSONString(value));
+        }
+        return null;
+    }
+}

+ 42 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaPropTriggerTypeConverter.java

@@ -0,0 +1,42 @@
+package com.izouma.nineth.utils.excel;
+
+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.MetaPropTriggerType;
+import com.izouma.nineth.enums.MetaPropType;
+
+public class MetaPropTriggerTypeConverter implements Converter<MetaPropTriggerType> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaPropTriggerType.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaPropTriggerType convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaPropTriggerType value : MetaPropTriggerType.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaPropTriggerType value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

+ 41 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaPropTypeConverter.java

@@ -0,0 +1,41 @@
+package com.izouma.nineth.utils.excel;
+
+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.MetaPropType;
+
+public class MetaPropTypeConverter implements Converter<MetaPropType> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaPropType.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaPropType convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaPropType value : MetaPropType.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaPropType value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

+ 42 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaPropUsedTypeConverter.java

@@ -0,0 +1,42 @@
+package com.izouma.nineth.utils.excel;
+
+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.MetaPropType;
+import com.izouma.nineth.enums.MetaPropUsedType;
+
+public class MetaPropUsedTypeConverter implements Converter<MetaPropUsedType> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaPropUsedType.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaPropUsedType convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaPropUsedType value : MetaPropUsedType.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaPropUsedType value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

+ 42 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaResourcesTypeConverter.java

@@ -0,0 +1,42 @@
+package com.izouma.nineth.utils.excel;
+
+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.MetaResourcesType;
+
+public class MetaResourcesTypeConverter implements Converter<MetaResourcesType> {
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaResourcesType.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaResourcesType convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaResourcesType value : MetaResourcesType.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaResourcesType value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

+ 41 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaStoreCommodityTypeConverter.java

@@ -0,0 +1,41 @@
+package com.izouma.nineth.utils.excel;
+
+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.MetaStoreCommodityType;
+
+public class MetaStoreCommodityTypeConverter implements Converter<MetaStoreCommodityType> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaStoreCommodityType.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaStoreCommodityType convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaStoreCommodityType value : MetaStoreCommodityType.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaStoreCommodityType value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

+ 41 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaSwitchTypeConverter.java

@@ -0,0 +1,41 @@
+package com.izouma.nineth.utils.excel;
+
+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.MetaSwitchType;
+
+public class MetaSwitchTypeConverter implements Converter<MetaSwitchType> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaSwitchType.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaSwitchType convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaSwitchType value : MetaSwitchType.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaSwitchType value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

+ 3 - 0
src/main/java/com/izouma/nineth/web/AirDropController.java

@@ -32,11 +32,13 @@ public class AirDropController extends BaseController {
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
+    @PreAuthorize("hasAnyRole('ADMIN', 'SAAS')")
     public Page<AirDrop> all(@RequestBody PageQuery pageQuery) {
         return airDropService.all(pageQuery);
     }
 
     @GetMapping("/get/{id}")
+    @PreAuthorize("hasAnyRole('ADMIN', 'SAAS')")
     public AirDrop get(@PathVariable Long id) {
         return airDropRepo.findById(id).orElseThrow(new BusinessException("无记录"));
     }
@@ -47,6 +49,7 @@ public class AirDropController extends BaseController {
     }
 
     @GetMapping("/excel")
+    @PreAuthorize("hasAnyRole('ADMIN', 'SAAS')")
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
         List<AirDrop> data = all(pageQuery).getContent();

+ 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());
+    }
 }
 
 

+ 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);
+    }
+}
+

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

@@ -59,8 +59,8 @@ public class MetaProblemController extends BaseController {
     }
 
     @GetMapping("/findAll")
-    public List<MetaProblem> findAll(){
-        return metaProblemRepo.findAllByDel(false);
+    public MetaRestResult<List<MetaProblem>> findAll(){
+        return MetaRestResult.returnSuccess("查询成功",metaProblemRepo.findAllByDel(false));
     }
 
     @GetMapping("/getAnswer/{id}")

+ 25 - 5
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;
@@ -83,20 +84,20 @@ public class MetaResourcesController extends BaseController {
         return MetaRestResult.returnSuccess("查询成功", metaResources.getValue());
     }
 
-    @PostMapping("/like")
-    public MetaRestResult<Integer> like(Long id, Long userId) {
-        MetaResources metaResources = metaResourcesRepo.findById(id).orElse(null);
+    @PostMapping("/like/{name}/{userId}")
+    public MetaRestResult<Integer> like(@PathVariable String name, @PathVariable Long userId) {
+        MetaResources metaResources = metaResourcesRepo.findByNameAndDel(name, false);
         if (Objects.isNull(metaResources)) {
             return MetaRestResult.returnError("当前资源不存在!");
         }
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateTimeUtils.DATE_FORMAT);
         LocalDate likeTime = LocalDate.parse(LocalDate.now().format(formatter), formatter);
-        MetaResourcesLikeRecord metaResourcesLikeRecord = metaResourcesLikeRecordRepo.findByMetaResourcesIdAndUserIdAndLikeTime(id, userId, likeTime);
+        MetaResourcesLikeRecord metaResourcesLikeRecord = metaResourcesLikeRecordRepo.findByMetaResourcesNameAndUserIdAndLikeTime(name, userId, likeTime);
         if (Objects.nonNull(metaResourcesLikeRecord)) {
             return MetaRestResult.returnError("该资源今天已经点过赞,不可重复点赞");
         }
         metaResourcesLikeRecord = new MetaResourcesLikeRecord();
-        metaResourcesLikeRecord.setMetaResourcesId(id);
+        metaResourcesLikeRecord.setMetaResourcesName(name);
         metaResourcesLikeRecord.setUserId(userId);
         metaResourcesLikeRecord.setLikeTime(likeTime);
         metaResourcesLikeRecordRepo.save(metaResourcesLikeRecord);
@@ -104,5 +105,24 @@ public class MetaResourcesController extends BaseController {
         metaResourcesRepo.save(metaResources);
         return MetaRestResult.returnSuccess(metaResources.getLikeNum());
     }
+
+
+    @GetMapping("/getLikeNum/{name}/{userId}")
+    public MetaRestResult<MetaResourcesLikeDTO> getLikeNum(@PathVariable String name, @PathVariable Long userId) {
+        MetaResources metaResources = metaResourcesRepo.findByNameAndDel(name, false);
+        if (Objects.isNull(metaResources)) {
+            return MetaRestResult.returnError("当前资源不存在!");
+        }
+        MetaResourcesLikeDTO metaResourcesLikeDTO = new MetaResourcesLikeDTO();
+        metaResourcesLikeDTO.setNum(metaResources.getLikeNum());
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateTimeUtils.DATE_FORMAT);
+        LocalDate likeTime = LocalDate.parse(LocalDate.now().format(formatter), formatter);
+        MetaResourcesLikeRecord metaResourcesLikeRecord = metaResourcesLikeRecordRepo.findByMetaResourcesNameAndUserIdAndLikeTime(name, userId, likeTime);
+        if (Objects.nonNull(metaResourcesLikeRecord)) {
+            metaResourcesLikeDTO.setLike(true);
+            return MetaRestResult.returnSuccess(metaResourcesLikeDTO);
+        }
+        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);
+    }
+}

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

@@ -1,13 +1,15 @@
 package com.izouma.nineth.web;
 
 import com.izouma.nineth.config.MetaConstants;
+import com.izouma.nineth.domain.MetaProp;
 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;
 import com.izouma.nineth.repo.MetaTaskRepo;
 import com.izouma.nineth.repo.MetaTaskToUserRepo;
 import com.izouma.nineth.service.MetaTaskService;
@@ -21,22 +23,26 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 
 @RestController
 @RequestMapping("/metaTask")
 @AllArgsConstructor
 public class MetaTaskController extends BaseController {
     private MetaTaskService metaTaskService;
+
     private MetaTaskRepo metaTaskRepo;
 
     private MetaTaskToUserRepo metaTaskToUserRepo;
 
     private CollectionRepo collectionRepo;
 
+    private MetaPropRepo metaPropRepo;
+
     //@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)));
@@ -95,6 +101,15 @@ public class MetaTaskController extends BaseController {
     @GetMapping("/{userId}/{channelId}/canGet")
     public MetaRestResult<List<MetaTask>> canGet(@PathVariable Long userId, @PathVariable Long channelId) {
         List<MetaTask> metaTasks = metaTaskRepo.canGet(userId, channelId);
+        metaTasks.forEach(metaTask -> {
+            if (MetaAwardTypeEnum.META_PROP.equals(metaTask.getAwardType()) && Objects.nonNull(metaTask.getMetaPropId())) {
+                MetaProp metaProp = metaPropRepo.findByIdAndDel(metaTask.getMetaPropId(), false);
+                if (Objects.isNull(metaProp)) {
+                    throw new BusinessException(String.format("道具[%S]不存在!", metaTask.getMetaPropId()));
+                }
+                metaTask.setMetaProp(metaProp);
+            }
+        });
         return MetaRestResult.returnSuccess(metaTasks);
     }
 

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

@@ -0,0 +1,65 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaTaskNew;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.MetaTaskNewRepo;
+import com.izouma.nineth.service.MetaTaskNewService;
+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("/metaTaskNew")
+@AllArgsConstructor
+public class MetaTaskNewController extends BaseController {
+
+    private MetaTaskNewService metaTaskNewService;
+
+    private MetaTaskNewRepo metaTaskNewRepo;
+
+    //@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) {
+        return metaTaskNewService.get(id);
+    }
+
+    @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.findAllByPublishAndDel(true, false);
+        return MetaRestResult.returnSuccess(metaTaskNews);
+    }
+
+    @GetMapping("/{userId}/{channelId}/canGet")
+    public MetaRestResult<List<MetaTaskNew>> canGet(@PathVariable Long userId, @PathVariable Long channelId) {
+        return metaTaskNewService.canGet(userId, channelId);
+    }
+}

+ 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);
+    }
+
+}

+ 60 - 0
src/main/java/com/izouma/nineth/web/MetaTopController.java

@@ -0,0 +1,60 @@
+package com.izouma.nineth.web;
+import com.izouma.nineth.domain.MetaTop;
+import com.izouma.nineth.service.MetaTopService;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaTopRepo;
+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;
+
+@RestController
+@RequestMapping("/metaTop")
+@AllArgsConstructor
+public class MetaTopController extends BaseController {
+    private MetaTopService metaTopService;
+    private MetaTopRepo metaTopRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public MetaTop save(@RequestBody MetaTop record) {
+        if (record.getId() != null) {
+            MetaTop orig = metaTopRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return metaTopRepo.save(orig);
+        }
+        return metaTopRepo.save(record);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<MetaTop> all(@RequestBody PageQuery pageQuery) {
+        return metaTopService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public MetaTop get(@PathVariable Long id) {
+        return metaTopRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        metaTopRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaTop> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 7 - 3
src/main/java/com/izouma/nineth/web/MetaUserGoldController.java

@@ -70,10 +70,14 @@ public class MetaUserGoldController extends BaseController {
 
     @GetMapping("/{userId}/queryNum")
     public MetaRestResult<Integer> queryGoldNum(@PathVariable Long userId) {
-        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false);
-        if (Objects.isNull(metaUserGold)) {
+        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false).orElseGet(() -> {
             metaUserGoldService.initMetaUserGold(String.valueOf(userId));
-            return MetaRestResult.returnSuccess(0);
+            return metaUserGoldRepo.findByUserIdAndDel(userId, false).orElse(null);
+        });
+        if (Objects.isNull(metaUserGold)) {
+            String errMMsg = String.format("当前用户[%S]金币账户数据不存在且无法初始化数据", userId);
+            log.error(errMMsg);
+            return MetaRestResult.returnError(errMMsg);
         }
         return MetaRestResult.returnSuccess(metaUserGold.getNum());
     }

+ 52 - 1
src/main/java/com/izouma/nineth/web/MetaUserGoldRecordController.java

@@ -1,19 +1,29 @@
 package com.izouma.nineth.web;
 
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.izouma.nineth.config.MetaConstants;
+import com.izouma.nineth.domain.MetaGameBoxPoints;
+import com.izouma.nineth.domain.MetaParamsConfig;
 import com.izouma.nineth.domain.MetaUserGoldRecord;
-import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.*;
 import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaParamsConfigRepo;
 import com.izouma.nineth.repo.MetaUserGoldRecordRepo;
+import com.izouma.nineth.service.MetaParamsConfigService;
 import com.izouma.nineth.service.MetaUserGoldRecordService;
 import com.izouma.nineth.utils.ObjUtils;
 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.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 @RestController
 @RequestMapping("/metaUserGoldRecord")
@@ -21,6 +31,7 @@ import java.util.List;
 public class MetaUserGoldRecordController extends BaseController {
     private MetaUserGoldRecordService metaUserGoldRecordService;
     private MetaUserGoldRecordRepo metaUserGoldRecordRepo;
+    private MetaParamsConfigService metaParamsConfigService;
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
@@ -56,5 +67,45 @@ public class MetaUserGoldRecordController extends BaseController {
         List<MetaUserGoldRecord> data = all(pageQuery).getContent();
         ExcelUtils.export(response, data);
     }
+
+    @GetMapping("/excel/top")
+    @ResponseBody
+    public void excelTop(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaGoldTopDTO> data = top(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @PostMapping("/goldTop")
+    public Page<MetaGoldTopDTO> top(@RequestBody PageQuery pageQuery) {
+        String beginTime = metaParamsConfigService.getString(MetaConstants.META_GOLD_TOP_BEGIN_TIME);
+        String endTime = metaParamsConfigService.getString(MetaConstants.META_GOLD_TOP_END_TIME);
+        List<Map<String, String>> map = metaUserGoldRecordRepo.top(beginTime, endTime);
+        JSONArray jsonArray = new JSONArray();
+        jsonArray.addAll(map);
+        List<MetaGoldTopDTO> metaGoldTopDTOS = jsonArray.toJavaList(MetaGoldTopDTO.class);
+        // 当前页
+        int page = pageQuery.getPage();
+        // pageSize 每页查询多少条数据
+        int size = pageQuery.getSize();
+        // limit 开始偏移量
+        int start = page * size;
+        int totalElements = 0;
+        if (CollectionUtils.isEmpty(metaGoldTopDTOS)) {
+            totalElements = 0;
+            return new PageWrapper<>(new ArrayList<MetaGoldTopDTO>(), page,
+                    size, totalElements).toPage();
+        }
+        totalElements = metaGoldTopDTOS.size();
+        List<MetaGoldTopDTO> newMetaGoldTopDTOS;
+        if (metaGoldTopDTOS.size() < start + size) {
+            newMetaGoldTopDTOS = metaGoldTopDTOS.subList(start, metaGoldTopDTOS.size());
+            return new PageWrapper<>(newMetaGoldTopDTOS, page,
+                    size, totalElements).toPage();
+        }
+        newMetaGoldTopDTOS = metaGoldTopDTOS.subList(start, start + size);
+        return new PageWrapper<>(newMetaGoldTopDTOS, page,
+                size, totalElements).toPage();
+
+    }
 }
 

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

@@ -3,6 +3,7 @@ package com.izouma.nineth.web;
 import com.izouma.nineth.dto.MetaRestResult;
 import com.izouma.nineth.service.MetaUserTaskAwardReceivedRecordService;
 import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -14,8 +15,8 @@ public class MetaUserTaskAwardReceivedRecordController {
 
     private MetaUserTaskAwardReceivedRecordService metaUserTaskAwardReceivedRecordService;
 
-    @PostMapping("/receiveAward")
-    public MetaRestResult<Void> receiveAward(Long metaTaskId) {
+    @PostMapping("/receiveAward/{metaTaskId}")
+    public MetaRestResult<Void> receiveAward(@PathVariable Long metaTaskId) {
         return metaUserTaskAwardReceivedRecordService.receiveAward(metaTaskId);
     }
 }

+ 39 - 0
src/main/java/com/izouma/nineth/web/MetaUserTaskAwardReceivedRecordNewController.java

@@ -0,0 +1,39 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaUserTaskAwardReceivedRecordNew;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.service.MetaUserTaskAwardReceivedRecordNewService;
+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("/metaUserTaskAwardReceivedRecordNew")
+@AllArgsConstructor
+public class MetaUserTaskAwardReceivedRecordNewController {
+
+    private MetaUserTaskAwardReceivedRecordNewService metaUserTaskAwardReceivedRecordNewService;
+
+    @PostMapping("/receiveAward/{taskId}/{atomTaskId}")
+    public MetaRestResult<Void> receiveAward(@PathVariable Long taskId, @PathVariable Long atomTaskId) {
+        return metaUserTaskAwardReceivedRecordNewService.receiveAward(taskId, atomTaskId);
+    }
+
+    @PostMapping("/all")
+    public Page<MetaUserTaskAwardReceivedRecordNew> all(@RequestBody PageQuery pageQuery) {
+        return metaUserTaskAwardReceivedRecordNewService.all(pageQuery);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaUserTaskAwardReceivedRecordNew> 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);
+    }
+
+}
+

+ 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"}

File diff suppressed because it is too large
+ 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/

+ 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>

+ 11 - 0
src/main/vue/src/views/MetaParamsConfigList.vue

@@ -53,6 +53,13 @@
                         active-value="1"
                         inactive-value="0"
                     ></el-switch>
+                    <el-date-picker
+                        v-model="formData.value"
+                        v-if="formData.type === 'DATETIME'"
+                        type="datetime"
+                        value-format="yyyy-MM-dd HH:mm:ss"
+                        placeholder="请选择日期时间"
+                    ></el-date-picker>
                 </el-form-item>
             </el-form>
             <span slot="footer">
@@ -95,6 +102,10 @@ export default {
                     label: '字符串',
                     value: 'STRING'
                 },
+                {
+                    label: '日期时间',
+                    value: 'DATETIME'
+                },
                 {
                     label: '开关',
                     value: 'BOOLEAN'

+ 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>

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

@@ -0,0 +1,215 @@
+<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="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 - 450px)" 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 - 450px)"
+                            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 - 450px)"
+                            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 - 450px)" 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' }

+ 97 - 0
src/main/vue/src/views/MetaTaskToUserNewList.vue

@@ -0,0 +1,97 @@
+<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="id" align="center" label="ID"> </el-table-column>
+            <el-table-column prop="userId" align="center" label="用户id"> </el-table-column>
+            <el-table-column prop="getTime" align="center" label="领取时间"> </el-table-column>
+            <el-table-column prop="finishTime" align="center" label="完成时间"> </el-table-column>
+            <el-table-column prop="taskId" align="center" label="任务id"> </el-table-column>
+			<el-table-column prop="atomTaskId" align="center" label="基础任务id"> </el-table-column>
+			<el-table-column prop="status" align="center" label="当前状态" :formatter="taskStatusFormatter"> </el-table-column>
+            <el-table-column prop="channelId" 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: 'MetaTaskToUserNewList',
+	mixins: [pageableTable],
+	data() {
+		return {
+			search: '',
+			url: '/metaTaskToUserNew/all',
+			downloading: false,
+			taskStatusOptions: [
+                { label: '进行中', value: 'PROGRESS' },
+                { label: '已完成', value: 'COMPLETION' }
+            ]
+		};
+	},
+	computed: {
+		selection() {
+			return this.$refs.table.selection.map(i => i.id);
+		}
+	},
+	methods: {
+		taskStatusFormatter(row, column, cellValue, index) {
+            let selectedOption = this.taskStatusOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+		beforeGetData() {
+			return { search: this.search, query: { del: false } };
+		},
+		download() {
+			this.downloading = true;
+			this.$axios
+				.get('/metaTaskToUserNew/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>

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

@@ -0,0 +1,132 @@
+<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 v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+            <el-table-column prop="userId" label="用户Id" width="100"> </el-table-column>
+            <el-table-column prop="head" label="用户头像"> </el-table-column>
+            <el-table-column prop="nickName" label="用户昵称"> </el-table-column>
+            <el-table-column prop="num" label="金币数量"> </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+    name: 'MetaTopDetailList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/metaUserGoldRecord/goldTop',
+            downloading: false
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        beforeGetData() {
+            return { search: this.search, query: { del: false } };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/metaUserGoldRecord/excel/top', {
+                    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');
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+</style>

+ 106 - 0
src/main/vue/src/views/MetaTopEdit.vue

@@ -0,0 +1,106 @@
+<template>
+    <div class="edit-view">
+        <page-title>
+            <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+            <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
+                删除
+            </el-button>
+            <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
+        </page-title>
+        <div class="edit-view__content-wrapper">
+            <div class="edit-view__content-section">
+                <el-form :model="formData" :rules="rules" ref="form" label-width="94px" label-position="right"
+                         size="small"
+                         style="max-width: 500px;">
+                        <el-form-item prop="name" label="排行榜名称">
+                                    <el-input v-model="formData.name"></el-input>
+                        </el-form-item>
+                        <el-form-item prop="rule" label="排行榜用途">
+                                    <el-input v-model="formData.rule"></el-input>
+                        </el-form-item>
+                        <el-form-item prop="pic" label="配置图片">
+                                    <single-upload v-model="formData.pic"></single-upload>
+                        </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: 'MetaTopEdit',
+        created() {
+            if (this.$route.query.id) {
+                this.$http
+                    .get('metaTop/get/' + this.$route.query.id)
+                    .then(res => {
+                        this.formData = res;
+                    })
+                    .catch(e => {
+                        console.log(e);
+                        this.$message.error(e.error);
+                    });
+            }
+        },
+        data() {
+            return {
+                saving: false,
+                formData: {
+                },
+                rules: {
+                },
+            }
+        },
+        methods: {
+            onSave() {
+                this.$refs.form.validate((valid) => {
+                    if (valid) {
+                        this.submit();
+                    } else {
+                        return false;
+                    }
+                });
+            },
+            submit() {
+                let data = {...this.formData};
+
+                this.saving = true;
+                this.$http
+                    .post('/metaTop/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(`/metaTop/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>

+ 185 - 0
src/main/vue/src/views/MetaTopList.vue

@@ -0,0 +1,185 @@
+<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>
+        </page-title>
+        <div class="filters-container">
+            <el-input
+                placeholder="搜索..."
+                v-model="search"
+                clearable
+                class="filter-item search"
+                @keyup.enter.native="getData"
+            >
+                <el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
+            </el-input>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+            v-loading="fetchingData"
+        >
+            <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+            <el-table-column prop="id" label="ID" width="100"> </el-table-column>
+            <el-table-column prop="name" label="排行榜名称"> </el-table-column>
+            <el-table-column prop="rule" label="排行榜用途"> </el-table-column>
+            <el-table-column prop="pic" 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 label="操作" align="center" fixed="right" width="150">
+                <template slot-scope="{ row }">
+                    <el-button @click="MetaTopDetailList(row)" type="primary" size="mini" plain>查看</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+    name: 'MetaTopList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/metaTop/all',
+            downloading: false
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        beforeGetData() {
+            return { search: this.search, query: { del: false } };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/metaTopEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        MetaTopDetailList() {
+            this.$router.push({
+                path: '/MetaTopDetailList',
+                query: {
+                    
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/metaTopEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/metaTop/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(`/metaTop/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>

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

@@ -1,7 +1,7 @@
 <template>
 	<div class="list-view">
 		<page-title>
-			<el-button @click="addUserIds" type="primary" class="filter-item"> 初始化用户 </el-button>
+			<!-- <el-button @click="addUserIds" type="primary" class="filter-item"> 初始化用户 </el-button> -->
 			<el-button
 				@click="download"
 				icon="el-icon-upload2"

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

@@ -55,6 +55,7 @@
                 </template>
             </el-table-column>
             <el-table-column prop="afterNum" align="center" label="操作后金币数量"> </el-table-column>
+            <el-table-column prop="remark" align="center" label="备注" show-overflow-tooltip> </el-table-column>
         </el-table>
         <div class="pagination-wrapper">
             <el-pagination

+ 86 - 0
src/main/vue/src/views/MetaUserTaskAwardReceivedRecordNewList.vue

@@ -0,0 +1,86 @@
+<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="taskId" align="center" label="任务id">
+            </el-table-column>
+            <el-table-column prop="atomTaskId" align="center" label="基础任务id">
+            </el-table-column>
+            <el-table-column prop="receivedTime" 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: 'MetaUserTaskAwardReceivedRecordNewList',
+	mixins: [pageableTable],
+	data() {
+		return {
+			search: '',
+			url: '/metaUserTaskAwardReceivedRecordNew/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('/metaUserTaskAwardReceivedRecordNew/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>

Some files were not shown because too many files changed in this diff