فهرست منبع

白名单额度

licailing 3 سال پیش
والد
کامیت
96ddf30b0e

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

@@ -26,4 +26,6 @@ public class GeneralProperties {
     private String  updateActivityStockTopic;
     private int     dataCenterId;
     private int     workerId;
+    private String  updateQuotaGroup;
+    private String  updateQuotaTopic;
 }

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

@@ -9,6 +9,8 @@ public class RedisKeys {
 
     public static final String COLLECTION_SALE = "collectionSale::";
 
+    public static final String COLLECTION_QUOTA = "collectionQuota::";
+
     public static final String PAY_RECORD = "payRecord::";
 
     public static final String ORDER_LOCK = "orderLock::";

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

@@ -171,7 +171,10 @@ public class Collection extends BaseEntity {
     @ApiModelProperty("注册背景")
     private String registerBg;
 
-    @ApiModelProperty("白名单额度")
+    @ApiModelProperty("总额度")
+    private Integer totalQuota;
+
+    @ApiModelProperty("剩余额度")
     private Integer vipQuota;
 
     @ApiModelProperty("延迟销售")

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

@@ -0,0 +1,28 @@
+package com.izouma.nineth.listener;
+
+import com.izouma.nineth.service.CollectionService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.annotation.ConsumeMode;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+@AllArgsConstructor
+@RocketMQMessageListener(
+        consumerGroup = "${general.update-quota-group}",
+        topic = "${general.update-quota-topic}",
+        consumeMode = ConsumeMode.ORDERLY)
+@ConditionalOnProperty(value = "general.notify-server", havingValue = "false", matchIfMissing = true)
+public class UpdateQuotaListener implements RocketMQListener<Long> {
+
+    private CollectionService collectionService;
+
+    @Override
+    public void onMessage(Long id) {
+        collectionService.syncQuota(id);
+    }
+}

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

@@ -130,4 +130,9 @@ public interface CollectionRepo extends JpaRepository<Collection, Long>, JpaSpec
             "c.owner_avatar = ?5, c.detail = ?6 where c.id = ?1", nativeQuery = true)
     int updateCDN(Long id, String pic, String model3d, String minterAvatar,
                   String ownerAvatar, String detail);
+
+    @Query("update Collection c set c.vipQuota = ?2 where c.id = ?1")
+    @Transactional
+    @Modifying
+    int updateVipQuota(Long id, int vipQuota);
 }

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

@@ -417,4 +417,14 @@ public class CollectionService {
             cacheService.clearCollection(id);
         }
     }
+
+    @Debounce(key = "#id", delay = 500)
+    public void syncQuota(Long id) {
+        Integer quota = (Integer) redisTemplate.opsForValue().get(RedisKeys.COLLECTION_QUOTA + id);
+        if (quota != null) {
+            log.info("同步额度信息{}", id);
+            collectionRepo.updateVipQuota(id, quota);
+            cacheService.clearCollection(id);
+        }
+    }
 }

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

@@ -213,6 +213,8 @@ public class UserService {
                                     .type("VIP_POINT")
                                     .point(1)
                                     .build());
+                            // 扣除藏品额度
+                            collectionRepo.updateVipQuota(collectionId, -1);
                         }
                     }
                 }

+ 12 - 0
src/main/resources/application.yaml

@@ -153,6 +153,8 @@ general:
   mint-topic: mint-topic-dev
   update-activity-stock-group: update-activity-stock-group-dev
   update-activity-stock-topic: update-activity-stock-topic-dev
+  update-quota-group: update-quota-group-dev
+  update-quota-topic: update-quota-topic-dev
 mychain:
   rest:
     bizid: a00e36c5
@@ -229,6 +231,8 @@ general:
   mint-topic: mint-topic-test
   update-activity-stock-group: update-activity-stock-group-test
   update-activity-stock-topic: update-activity-stock-topic-test
+  update-quota-group: update-quota-group-test
+  update-quota-topic: update-quota-topic-test
 ---
 
 spring:
@@ -256,6 +260,8 @@ general:
   notify-server: true
   update-activity-stock-group: update-activity-stock-group-test1
   update-activity-stock-topic: update-activity-stock-topic-test1
+  update-quota-group: update-quota-group-test1
+  update-quota-topic: update-quota-topic-test1
 wx:
   pay:
     notify-url: https://test1.raex.vip/notify/order/weixin
@@ -308,6 +314,8 @@ general:
   mint-topic: mint-topic
   update-activity-stock-group: update-activity-stock-group
   update-activity-stock-topic: update-activity-stock-topic
+  update-quota-group: update-quota-group
+  update-quota-topic: update-quota-topic
 wx:
   pay:
     notify-url: https://www.raex.vip/notify/order/weixin
@@ -352,6 +360,8 @@ general:
   notify-server: true
   update-activity-stock-group: update-activity-stock-group
   update-activity-stock-topic: update-activity-stock-topic
+  update-quota-group: update-quota-group
+  update-quota-topic: update-quota-topic
 wx:
   pay:
     notify-url: https://www.raex.vip/notify/order/weixin
@@ -394,6 +404,8 @@ general:
   notify-server: true
   update-activity-stock-group: update-activity-stock-group-test
   update-activity-stock-topic: update-activity-stock-topic-test
+  update-quota-group: update-quota-group-test
+  update-quota-topic: update-quota-topic-test
 rocketmq:
   name-server: 172.29.50.102:9876
   producer:

+ 109 - 54
src/main/vue/src/views/BlindBoxEdit.vue

@@ -193,28 +193,60 @@
                         <el-radio v-model="formData.noSoldOut" :label="false">是</el-radio>
                         <el-radio v-model="formData.noSoldOut" :label="true">否</el-radio>
                     </el-form-item>
-                    <el-form-item prop="assignment" label="拉新任务指标">
-                        <el-input-number
-                            type="number"
-                            :min="0"
-                            :step="1"
-                            :max="5"
-                            v-model="formData.assignment"
-                        ></el-input-number>
-                        <div class="tip">0表示无拉新任务限制</div>
+                    <el-form-item prop="couponPayment" label="支付方式">
+                        <el-radio-group v-model="formData.couponPayment">
+                            <el-radio :label="true">兑换券</el-radio>
+                            <el-radio :label="false">支付宝/微信</el-radio>
+                        </el-radio-group>
                     </el-form-item>
+                    <div class="inline-wrapper">
+                        <el-form-item prop="assignment" label="拉新任务指标">
+                            <el-input-number
+                                type="number"
+                                :min="0"
+                                :step="1"
+                                :max="5"
+                                v-model="formData.assignment"
+                            ></el-input-number>
+                            <div class="tip">0表示无拉新任务限制</div>
+                        </el-form-item>
+                        <el-form-item prop="totalQuota" label="白名单额度" v-if="formData.assignment > 0">
+                            <el-input-number
+                                type="number"
+                                :min="0"
+                                :step="1"
+                                v-model="formData.totalQuota"
+                                :disabled="!editQuota"
+                            ></el-input-number>
+                            <div class="tip">多少人拉新可获得积分</div>
+                        </el-form-item>
+                    </div>
+                    <div class="inline-wrapper">
+                        <el-form-item prop="timeDelay" label="延迟销售" v-if="formData.assignment > 0">
+                            <el-radio v-model="formData.timeDelay" :label="true">是</el-radio>
+                            <el-radio v-model="formData.timeDelay" :label="false">否</el-radio>
+                        </el-form-item>
+                        <el-form-item
+                            prop="saleTime"
+                            label="销售时间"
+                            v-if="formData.assignment > 0 && formData.timeDelay"
+                            style="margin-left: 22px"
+                        >
+                            <el-date-picker
+                                v-model="formData.saleTime"
+                                type="datetime"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="销售时间"
+                            ></el-date-picker>
+                        </el-form-item>
+                    </div>
+
                     <el-form-item label="分享海报" v-if="formData.assignment > 0">
                         <single-upload v-model="formData.shareBg"></single-upload>
                     </el-form-item>
                     <el-form-item label="注册海报" v-if="formData.assignment > 0">
                         <single-upload v-model="formData.registerBg"></single-upload>
                     </el-form-item>
-                    <el-form-item prop="couponPayment" label="支付方式">
-                        <el-radio-group v-model="formData.couponPayment">
-                            <el-radio :label="true">兑换券</el-radio>
-                            <el-radio :label="false">支付宝/微信</el-radio>
-                        </el-radio-group>
-                    </el-form-item>
                     <el-form-item class="form-submit">
                         <el-button @click="onSave" :loading="saving" type="primary" v-if="!formData.id">
                             保存
@@ -331,6 +363,9 @@ export default {
                             res.properties = res.properties || [];
                             res.privileges = res.privileges || [];
                             this.formData = res;
+                            if (res.totalQuota !== res.vipQuota) {
+                                this.editQuota = false;
+                            }
                             resolve();
                         })
                         .catch(e => {
@@ -375,43 +410,6 @@ export default {
                 }
             });
         });
-        // this.formData = {
-        //     name: 'OASISPUNK绿洲朋克',
-        //     pic: ['https://awesomeadmin.oss-cn-hangzhou.aliyuncs.com/image/2021-10-21-16-44-52kZqxuwhH.gif'],
-        //     minter: '管理员',
-        //     minterId: 1,
-        //     minterAvatar: 'https://awesomeadmin.oss-cn-hangzhou.aliyuncs.com/image/avatar_male.png',
-        //     detail:
-        //         '<div class="content-item" data-v-38285332="">\n<div data-v-38285332="">RAEX绿洲数字藏品中心首次携手星火爱心公益基金及火链Labs,联合发行公益型数字藏品: OASISPUNK绿洲朋克。OASISPUNK绿洲朋克是完全使用算法合成的加密人物头像,仅铸造发行3100枚,每一枚全都不同,更有稀缺度之分。绿洲朋克共分为3种类型:初代目(1500枚),次代目(1500枚),旗帜版(100枚)。每售出一枚绿洲朋克,收益所得将捐赠一定比例给&ldquo;星火爱心公益基金&rdquo;,用于扶贫助困类公益项目,同时买家将收到由星火爱心公益基金颁发的捐款证明,获得投身公益事业的荣誉感。欢迎你来到绿洲元宇宙,共建绿洲生态,共享绿洲文明荣耀。</div>\n</div>',
-        //     type: 'BLIND_BOX',
-        //     source: 'OFFICIAL',
-        //     sale: 0,
-        //     stock: 0,
-        //     total: 23,
-        //     likes: 0,
-        //     onShelf: true,
-        //     salable: true,
-        //     price: 0.01,
-        //     properties: [],
-        //     canResale: false,
-        //     royalties: 0,
-        //     serviceCharge: 0,
-        // };
-        // this.blindBoxItems = [
-        //     {
-        //         collectionId: 212,
-        //         total: 3,
-        //         rare: true
-        //     },
-        //     {
-        //         collectionId: 207,
-        //         total: 6
-        //     },
-        //     {
-        //         collectionId: 201,
-        //         total: 14
-        //     }
-        // ];
     },
     computed: {
         canEdit() {
@@ -586,7 +584,60 @@ export default {
                         }
                     }
                 ],
-                category: [{ required: true, message: '请填写分类' }]
+                category: [{ required: true, message: '请填写分类' }],
+                saleTime: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (this.formData.timeDelay) {
+                                if (!value) {
+                                    callback(new Error('请填写销售时间'));
+                                } else if (isBefore(parse(value, 'yyyy-MM-dd HH:mm:ss', new Date()), new Date())) {
+                                    callback(new Error('销售时间不能小于当前时间'));
+                                } else if (this.formData.scheduleSale) {
+                                    if (
+                                        isBefore(
+                                            parse(value, 'yyyy-MM-dd HH:mm:ss', new Date()),
+                                            parse(this.formData.startTime, 'yyyy-MM-dd HH:mm:ss', new Date())
+                                        )
+                                    ) {
+                                        callback(new Error('销售时间不能小于发布时间'));
+                                    }
+                                }
+                            }
+                            callback();
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                timeDelay: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (this.formData.assignment > 0) {
+                                if (value === '' || value === undefined) {
+                                    callback(new Error('请选择是否延迟销售'));
+                                    return;
+                                }
+                            }
+                            callback();
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                totalQuota: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (this.formData.assignment > 0) {
+                                if (value === '' || value === undefined) {
+                                    callback(new Error('请输入白名单额度'));
+                                    return;
+                                }
+                            }
+
+                            callback();
+                        },
+                        trigger: 'blur'
+                    }
+                ]
             },
             typeOptions: [
                 { label: '默认', value: 'DEFAULT' },
@@ -614,7 +665,8 @@ export default {
             privelegeRules: {
                 detail: [{ required: true, message: '请填写内容' }],
                 remark: [{ required: true, message: '请填写说明' }]
-            }
+            },
+            editQuota: true
         };
     },
     methods: {
@@ -628,6 +680,9 @@ export default {
             });
         },
         submit() {
+              if (this.editQuota && this.formData.totalQuota) {
+                this.formData.vipQuota = this.formData.totalQuota;
+            }
             if (this.formData.id) {
                 this.saving = true;
                 this.$http

+ 12 - 4
src/main/vue/src/views/CollectionEdit.vue

@@ -247,12 +247,13 @@
                             ></el-input-number>
                             <div class="tip">0表示无拉新任务限制</div>
                         </el-form-item>
-                        <el-form-item prop="vipQuota" label="白名单额度" v-if="formData.assignment > 0">
+                        <el-form-item prop="totalQuota" label="白名单额度" v-if="formData.assignment > 0">
                             <el-input-number
                                 type="number"
                                 :min="0"
                                 :step="1"
-                                v-model="formData.vipQuota"
+                                v-model="formData.totalQuota"
+                                :disabled="!editQuota"
                             ></el-input-number>
                             <div class="tip">多少人拉新可获得积分</div>
                         </el-form-item>
@@ -352,6 +353,9 @@ export default {
                             res.properties = res.properties || [];
                             res.privileges = res.privileges || [];
                             this.formData = res;
+                            if (res.totalQuota !== res.vipQuota) {
+                                this.editQuota = false;
+                            }
                             resolve();
                         })
                         .catch(e => {
@@ -582,7 +586,7 @@ export default {
                         trigger: 'blur'
                     }
                 ],
-                vipQuota: [
+                totalQuota: [
                     {
                         validator: (rule, value, callback) => {
                             if (this.formData.assignment > 0) {
@@ -618,7 +622,8 @@ export default {
             },
             customUrl: resolveUrl(this.$baseUrl, 'upload/3dModel'),
             scale: 1,
-            yOffset: 0
+            yOffset: 0,
+            editQuota: true
         };
     },
     methods: {
@@ -636,6 +641,9 @@ export default {
             if (data.model3d) {
                 data.model3d.url = data.model3d.url + '?scale=' + this.scale + '&yOffset=' + this.yOffset;
             }
+            if (this.editQuota && data.totalQuota) {
+                data.vipQuota = data.totalQuota;
+            }
 
             this.saving = true;
             this.$http