소스 검색

铸造活动定时发布

licailing 3 년 전
부모
커밋
27fe04bb1f

+ 9 - 0
src/main/java/com/izouma/nineth/domain/MintActivity.java

@@ -13,6 +13,7 @@ import javax.persistence.Column;
 import javax.persistence.Convert;
 import javax.persistence.Entity;
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.List;
 
 @Data
@@ -65,4 +66,12 @@ public class MintActivity extends BaseEntity{
     @ApiModelProperty("空投/实物")
     private boolean airDrop;
 
+    @ApiModelProperty("定时发布")
+    private boolean scheduleSale;
+
+    @ApiModelProperty("开始时间")
+    private LocalDateTime startTime;
+
+    @ApiModelProperty("上架")
+    private boolean onShelf;
 }

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

@@ -1,6 +1,7 @@
 package com.izouma.nineth.repo;
 
 import com.izouma.nineth.domain.MintActivity;
+import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
@@ -34,4 +35,10 @@ public interface MintActivityRepo extends JpaRepository<MintActivity, Long>, Jpa
     @Modifying
     int updateStock(Long id, int stock);
 
+    @Transactional
+    @Modifying
+    @Query("update MintActivity c set c.scheduleSale = false, c.startTime = null, c.onShelf = true where c.id = ?1")
+    @CacheEvict(value = "mintActivity", key = "#id")
+    void scheduleOnShelf(Long id);
+
 }

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

@@ -56,7 +56,6 @@ public class CollectionService {
     private BlindBoxItemRepo              blindBoxItemRepo;
     private AppointmentRepo               appointmentRepo;
     private UserRepo                      userRepo;
-    private AssetService                  assetService;
     private TaskScheduler                 taskScheduler;
     private CacheService                  cacheService;
     private RedisTemplate<String, Object> redisTemplate;

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

@@ -3,6 +3,7 @@ package com.izouma.nineth.service;
 import com.izouma.nineth.annotations.Debounce;
 import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.config.RedisKeys;
+import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.domain.MintActivity;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.repo.MintActivityRepo;
@@ -13,9 +14,16 @@ import org.apache.rocketmq.spring.core.RocketMQTemplate;
 import org.springframework.data.domain.Page;
 import org.springframework.data.redis.core.BoundValueOperations;
 import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.TaskScheduler;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Optional;
+import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
 @Slf4j
@@ -23,11 +31,14 @@ import java.util.concurrent.TimeUnit;
 @AllArgsConstructor
 public class MintActivityService {
 
-    private MintActivityRepo              mintActivityRepo;
-    private RedisTemplate<String, Object> redisTemplate;
-    private CacheService                  cacheService;
-    private RocketMQTemplate              rocketMQTemplate;
-    private GeneralProperties             generalProperties;
+    private       MintActivityRepo              mintActivityRepo;
+    private       RedisTemplate<String, Object> redisTemplate;
+    private       CacheService                  cacheService;
+    private       RocketMQTemplate              rocketMQTemplate;
+    private       GeneralProperties             generalProperties;
+    private       TaskScheduler                 taskScheduler;
+    private final Map<Long, ScheduledFuture<?>> tasks = new HashMap<>();
+
 
     public Page<MintActivity> all(PageQuery pageQuery) {
         return mintActivityRepo.findAll(JpaUtils.toSpecification(pageQuery, MintActivity.class), JpaUtils.toPageRequest(pageQuery));
@@ -74,4 +85,25 @@ public class MintActivityService {
         }
     }
 
+    private void onShelfTask(MintActivity record) {
+        ScheduledFuture<?> task = tasks.get(record.getId());
+        if (task != null) {
+            if (!task.cancel(true)) {
+                return;
+            }
+        }
+        if (record.isScheduleSale()) {
+            if (record.getStartTime().minusSeconds(2).isAfter(LocalDateTime.now())) {
+                Date date = Date.from(record.getStartTime().atZone(ZoneId.systemDefault()).toInstant());
+                ScheduledFuture<?> future = taskScheduler.schedule(() -> {
+                    mintActivityRepo.scheduleOnShelf(record.getId());
+                    tasks.remove(record.getId());
+                }, date);
+                tasks.put(record.getId(), future);
+            } else {
+                mintActivityRepo.scheduleOnShelf(record.getId());
+            }
+        }
+    }
+
 }

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

@@ -29,10 +29,14 @@ public class MintActivityController extends BaseController {
         if (record.getId() != null) {
             MintActivity orig = mintActivityRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
             ObjUtils.merge(orig, record);
-            return mintActivityRepo.save(orig);
+            orig = mintActivityRepo.save(orig);
+            mintActivityService.syncStock(record.getId());
+            return orig;
         }
         record.setStock(record.getTotal());
-        return mintActivityRepo.save(record);
+        record = mintActivityRepo.save(record);
+        mintActivityService.syncStock(record.getId());
+        return record;
     }
 
 

+ 68 - 5
src/main/vue/src/views/MintActivityEdit.vue

@@ -20,7 +20,11 @@
                         <el-input v-model="formData.name" class="width"></el-input>
                     </el-form-item>
                     <el-form-item prop="minterId" label="铸造者">
-                        <minter-select v-model="formData.minterId" @detail="onMinterDetail" class="width"></minter-select>
+                        <minter-select
+                            v-model="formData.minterId"
+                            @detail="onMinterDetail"
+                            class="width"
+                        ></minter-select>
                     </el-form-item>
                     <el-form-item prop="cover" label="封面">
                         <single-upload v-model="formData.cover"></single-upload>
@@ -32,7 +36,14 @@
                         <el-input v-model="formData.collectionName" :disabled="!canEdit" class="width"></el-input>
                     </el-form-item>
                     <el-form-item prop="num" label="藏品数量">
-                        <el-input-number type="number" v-model="formData.num" :disabled="!canEdit" :step="1" :min="0" class="width1"></el-input-number>
+                        <el-input-number
+                            type="number"
+                            v-model="formData.num"
+                            :disabled="!canEdit"
+                            :step="1"
+                            :min="0"
+                            class="width1"
+                        ></el-input-number>
                         <div class="tip">0表示不限</div>
                     </el-form-item>
                     <el-form-item prop="consume" label="是否消耗藏品">
@@ -43,16 +54,46 @@
                     </el-form-item>
                     <!-- <div class="inline-wrapper"> -->
                     <el-form-item prop="total" label="发行数量">
-                        <el-input-number type="number" v-model="formData.total" :disabled="!canEdit" :step="1" :min="0" class="width1"></el-input-number>
+                        <el-input-number
+                            type="number"
+                            v-model="formData.total"
+                            :disabled="!canEdit"
+                            :step="1"
+                            :min="0"
+                            class="width1"
+                        ></el-input-number>
                     </el-form-item>
                     <el-form-item prop="gasPrice" label="铸造gas费">
-                        <el-input-number v-model="formData.gasPrice" :disabled="!canEdit" :min="0" class="width1"></el-input-number>
+                        <el-input-number
+                            v-model="formData.gasPrice"
+                            :disabled="!canEdit"
+                            :min="0"
+                            class="width1"
+                        ></el-input-number>
                     </el-form-item>
                     <!-- </div> -->
                     <el-form-item prop="airDrop" label="类型">
                         <el-radio v-model="formData.airDrop" :label="true" :disabled="!canEdit">空投铸造</el-radio>
                         <el-radio v-model="formData.airDrop" :label="false" :disabled="!canEdit">实物铸造</el-radio>
                     </el-form-item>
+                    <el-form-item prop="onShelf" label="上架">
+                        <el-radio v-model="formData.onShelf" :label="true">是</el-radio>
+                        <el-radio v-model="formData.onShelf" :label="false">否</el-radio>
+                    </el-form-item>
+
+                    <el-form-item prop="startTime" label="定时发布">
+                        <el-radio v-model="formData.scheduleSale" :label="true">是</el-radio>
+                        <el-radio v-model="formData.scheduleSale" :label="false">否</el-radio>
+                    </el-form-item>
+                    <el-form-item prop="startTime" label="发布时间" v-if="formData.scheduleSale">
+                        <el-date-picker
+                            v-model="formData.startTime"
+                            type="datetime"
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            placeholder="发布时间"
+                        ></el-date-picker>
+                    </el-form-item>
+
                     <el-form-item 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">
@@ -66,6 +107,7 @@
     </div>
 </template>
 <script>
+import { format, parse, isBefore } from 'date-fns';
 export default {
     name: 'MintActivityEdit',
     created() {
@@ -84,7 +126,10 @@ export default {
     data() {
         return {
             saving: false,
-            formData: {},
+            formData: {
+                onShelf: false,
+                scheduleSale: true
+            },
             rules: {
                 name: [
                     {
@@ -134,6 +179,24 @@ export default {
                         message: '请选择类型',
                         trigger: 'blur'
                     }
+                ],
+                startTime: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (this.formData.scheduleSale) {
+                                if (!value) {
+                                    callback(new Error('请填写发布时间'));
+                                } else if (isBefore(parse(value, 'yyyy-MM-dd HH:mm:ss', new Date()), new Date())) {
+                                    callback(new Error('发布时间不能小于当前时间'));
+                                } else {
+                                    callback();
+                                }
+                            } else {
+                                callback();
+                            }
+                        },
+                        trigger: 'blur'
+                    }
                 ]
             }
         };