瀏覽代碼

编号乱序

xiongzhu 3 年之前
父節點
當前提交
079db5c12d

+ 28 - 0
src/main/java/com/izouma/nineth/converter/IntArrayConverter.java

@@ -0,0 +1,28 @@
+package com.izouma.nineth.converter;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Converter
+public class IntArrayConverter implements AttributeConverter<List<Integer>, String> {
+    @Override
+    public String convertToDatabaseColumn(List<Integer> integers) {
+        if (integers != null && !integers.isEmpty())
+            return StringUtils.join(integers, ",");
+        return null;
+    }
+
+    @Override
+    public List<Integer> convertToEntityAttribute(String s) {
+        if (StringUtils.isNotEmpty(s)) {
+            return Arrays.stream(s.split(",")).map(Integer::parseInt).collect(Collectors.toList());
+        }
+        return new ArrayList<>();
+    }
+}

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

@@ -287,6 +287,7 @@ public class Collection extends CollectionBaseEntity {
     @Column(columnDefinition = "bigint default 1 not null")
     private Long companyId = 1L;
 
+
     @ApiModelProperty("bit 0: 蚂蚁链, bit 1: 华储链")
     @Column(columnDefinition = "int default 3 not null")
     private int chainFlag;
@@ -301,4 +302,6 @@ public class Collection extends CollectionBaseEntity {
     private String newsPic;
 
     private LocalDateTime newsCreatedTime;
+
+    private boolean messNumber;
 }

+ 26 - 0
src/main/java/com/izouma/nineth/domain/NumberSeq.java

@@ -0,0 +1,26 @@
+package com.izouma.nineth.domain;
+
+
+import com.izouma.nineth.converter.IntArrayConverter;
+import lombok.Data;
+
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.List;
+
+@Data
+@Entity
+public class NumberSeq {
+
+    @Id
+    private Long id;
+
+    private int total;
+
+    @Convert(converter = IntArrayConverter.class)
+    @Column(columnDefinition = "text(65535)")
+    private List<Integer> numbers;
+
+}

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

@@ -0,0 +1,9 @@
+package com.izouma.nineth.repo;
+
+
+import com.izouma.nineth.domain.NumberSeq;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface NumberSeqRepo extends JpaRepository<NumberSeq, Long> {
+
+}

+ 38 - 10
src/main/java/com/izouma/nineth/service/AssetService.java

@@ -1,6 +1,7 @@
 package com.izouma.nineth.service;
 
 import com.google.common.collect.Lists;
+import com.google.common.hash.Hashing;
 import com.izouma.nineth.TokenHistory;
 import com.izouma.nineth.config.Constants;
 import com.izouma.nineth.config.GeneralProperties;
@@ -35,6 +36,7 @@ import org.springframework.stereotype.Service;
 
 import javax.persistence.criteria.Predicate;
 import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
@@ -70,6 +72,7 @@ public class AssetService {
     private AssetLockRepo           assetLockRepo;
     private UserBalanceService      userBalanceService;
     private PhotoAssetRepo          photoAssetRepo;
+    private NumberSeqRepo           numberSeqRepo;
 
     public Page<Asset> all(PageQuery pageQuery) {
 
@@ -149,6 +152,9 @@ public class AssetService {
 
     public Asset createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type,
                              Integer number, boolean safeFlag) {
+        if (collection.isMessNumber() && number != null) {
+            number = getMessedNumber(collection.getId(), number, collection.getTotal());
+        }
         Asset asset = Asset.create(collection, user);
         asset.setTokenId(TokenUtils.genTokenId());
         asset.setNumber(number);
@@ -247,12 +253,34 @@ public class AssetService {
         return asset;
     }
 
+    public synchronized int getMessedNumber(Long collectionId, int number, int total) {
+        NumberSeq numberSeq = numberSeqRepo.findById(collectionId).orElse(null);
+        if (numberSeq == null || numberSeq.getTotal() != total) {
+            numberSeq = new NumberSeq();
+            numberSeq.setId(collectionId);
+            numberSeq.setTotal(total);
+            Map<Integer, Integer> map = new HashMap<>();
+            for (int i = 0; i < total; i++) {
+                map.put(i, Hashing.md5().hashString(collectionId + ":" + i, StandardCharsets.UTF_8).asInt());
+            }
+            numberSeq.setNumbers(map.entrySet().stream()
+                    .sorted(Map.Entry.comparingByValue())
+                    .map(Map.Entry::getKey)
+                    .collect(Collectors.toList()));
+            numberSeqRepo.save(numberSeq);
+        }
+        return numberSeq.getNumbers().get(number);
+    }
+
     public Asset createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type,
                              Integer number, Integer holdDays, boolean safeFlag) {
         Collection blindBox = collectionRepo.findDetailById(winItem.getBlindBoxId())
                 .orElseThrow(new BusinessException("盲盒不存在"));
         Collection collection = collectionRepo.findDetailById(winItem.getCollectionId())
                 .orElseThrow(new BusinessException("藏品不存在"));
+        if (collection.isMessNumber() && number != null) {
+            number = getMessedNumber(collection.getId(), number, collection.getTotal());
+        }
         winItem.setCollection(collection);
         Asset asset = Asset.create(winItem, user, holdDays);
         asset.setTokenId(TokenUtils.genTokenId());
@@ -875,16 +903,16 @@ public class AssetService {
             if (tags.isEmpty()) return new PageImpl<>(Collections.emptyList());
             return assetRepo.findAll((Specification<Asset>) (root, query, criteriaBuilder) ->
                     query.distinct(true).where(
-                            // where userId=some id
-                            criteriaBuilder.equal(root.get("userId"), userId),
-                            // and (lockTo is null or (lockTo is not null and lockTo < now))
-                            criteriaBuilder.or(criteriaBuilder.isNull(root.get("lockTo")),
-                                    criteriaBuilder.and(criteriaBuilder.isNotNull(root.get("lockTo")),
-                                            criteriaBuilder.lessThan(root.get("lockTo"), LocalDateTime.now()))),
-                            // and status = 'NORMAL'
-                            criteriaBuilder.equal(root.get("status"), AssetStatus.NORMAL),
-                            // and has some tagId
-                            root.join("tags").get("id").in(tags.stream().map(Tag::getId).toArray()))
+                                    // where userId=some id
+                                    criteriaBuilder.equal(root.get("userId"), userId),
+                                    // and (lockTo is null or (lockTo is not null and lockTo < now))
+                                    criteriaBuilder.or(criteriaBuilder.isNull(root.get("lockTo")),
+                                            criteriaBuilder.and(criteriaBuilder.isNotNull(root.get("lockTo")),
+                                                    criteriaBuilder.lessThan(root.get("lockTo"), LocalDateTime.now()))),
+                                    // and status = 'NORMAL'
+                                    criteriaBuilder.equal(root.get("status"), AssetStatus.NORMAL),
+                                    // and has some tagId
+                                    root.join("tags").get("id").in(tags.stream().map(Tag::getId).toArray()))
                             .getRestriction(), pageable);
         } else {
             return assetRepo.findByUserIdAndStatusAndNameLike(userId, AssetStatus.NORMAL,

+ 22 - 20
src/main/vue/src/views/CollectionEdit.vue

@@ -188,6 +188,9 @@
                             <el-option label="蚂蚁链" :value="1" :key="1"></el-option>
                         </el-select>
                     </el-form-item>
+                    <el-form-item prop="messNumber" label="编号乱序">
+                        <el-switch v-model="formData.messNumber" active-text="是" inactive-text="否"></el-switch>
+                    </el-form-item>
                     <!-- <el-form-item prop="likes" label="点赞">
                         <el-input-number v-model="formData.likes"></el-input-number>
                     </el-form-item> -->
@@ -338,19 +341,19 @@
                     </el-form-item>
                     <el-form-item prop="newsId" label="新闻">
                         <el-select v-model="formData.newsId" placeholder="请选择">
-                        <el-option
-                            v-for="item in newsOptions"
-                            :key="item.id"
-                            :label="item.title"
-                            :value="item.id"
-                            class="minter-item"
-                        >
-<!--                            <el-image :src="item.pic" fit="cover" class="avatar"></el-image>-->
-                            <div class="content">
-                                <div class="name">{{ item.title }}</div>
-                                <div class="id">#{{ item.subTitle }}</div>
-                            </div>
-                        </el-option>
+                            <el-option
+                                v-for="item in newsOptions"
+                                :key="item.id"
+                                :label="item.title"
+                                :value="item.id"
+                                class="minter-item"
+                            >
+                                <!--                            <el-image :src="item.pic" fit="cover" class="avatar"></el-image>-->
+                                <div class="content">
+                                    <div class="name">{{ item.title }}</div>
+                                    <div class="id">#{{ item.subTitle }}</div>
+                                </div>
+                            </el-option>
                         </el-select>
                     </el-form-item>
                     <el-form-item class="form-submit">
@@ -435,12 +438,10 @@ export default {
                 }
                 return resolve();
             }),
-            this.$http
-                .post('/news/all', { size: 10000, query: { del: false } }, { body: 'json' })
-                .then(res => {
-                    this.newsOptions = res.content;
-                    return Promise.resolve();
-                }),
+            this.$http.post('/news/all', { size: 10000, query: { del: false } }, { body: 'json' }).then(res => {
+                this.newsOptions = res.content;
+                return Promise.resolve();
+            }),
             this.$http
                 .post('/privilegeOption/all', { size: 10000, query: { del: false } }, { body: 'json' })
                 .then(res => {
@@ -484,7 +485,8 @@ export default {
                 assignment: 0,
                 couponPayment: false,
                 chainFlag: 3,
-                vip: false
+                vip: false,
+                messNumber: false
             },
             rules: {
                 name: [

+ 5 - 1
src/main/vue/src/views/CompanyCollectionEdit.vue

@@ -188,6 +188,9 @@
                             <el-option label="蚂蚁链" :value="1" :key="1"></el-option>
                         </el-select>
                     </el-form-item>
+                    <el-form-item prop="messNumber" label="编号乱序">
+                        <el-switch v-model="formData.messNumber" active-text="是" inactive-text="否"></el-switch>
+                    </el-form-item>
                     <!-- <el-form-item prop="likes" label="点赞">
                         <el-input-number v-model="formData.likes"></el-input-number>
                     </el-form-item> -->
@@ -459,7 +462,8 @@ export default {
                 scanCode: false,
                 noSoldOut: true,
                 assignment: 0,
-                couponPayment: false
+                couponPayment: false,
+                messNumber: false
             },
             rules: {
                 name: [

+ 38 - 6
src/test/java/com/izouma/nineth/CommonTest.java

@@ -1,23 +1,22 @@
+
 package com.izouma.nineth;
 
 import com.alibaba.excel.EasyExcel;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.serializer.SerializerFeature;
-import com.alipay.api.AlipayApiException;
-import com.alipay.api.internal.util.AlipaySignature;
 import com.fasterxml.jackson.annotation.JsonView;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.github.kevinsawicki.http.HttpRequest;
 import com.google.common.base.Splitter;
+import com.google.common.hash.Hashing;
 import com.izouma.nineth.config.Constants;
 import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.SandPaySettle;
 import com.izouma.nineth.dto.UserWithdraw;
 import com.izouma.nineth.service.IdentityAuthService;
-import com.izouma.nineth.service.UserService;
 import com.izouma.nineth.utils.*;
 import com.izouma.nineth.web.BaseController;
 import io.ipfs.api.IPFS;
@@ -76,7 +75,6 @@ import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.RoundingMode;
-import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -90,10 +88,8 @@ import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
-import java.text.NumberFormat;
 import java.time.Duration;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.util.List;
@@ -101,8 +97,10 @@ import java.util.*;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
 import static java.nio.file.StandardOpenOption.CREATE;
@@ -753,4 +751,38 @@ public class CommonTest {
     public void resolve() {
         System.out.println(UrlUtils.resolve("http://www.baidu.com", "123", "456"));
     }
+
+    @Test
+    public void hash() {
+        long t = System.currentTimeMillis();
+        Map<Integer, Integer> map = new HashMap<>();
+        for (int i = 0; i < 5000; i++) {
+            map.put(i, Hashing.md5().hashString(i + "abcd", StandardCharsets.UTF_8).asInt());
+        }
+        AtomicInteger i = new AtomicInteger();
+        map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(e -> {
+            System.out.println(i.incrementAndGet() + ":" + e.getKey() + " : " + e.getValue());
+        });
+        System.out.println(System.currentTimeMillis() - t);
+    }
+
+
+    public int randomize(int number, int total) {
+        Map<Integer, Integer> map = new HashMap<>();
+        for (int i = 0; i < total; i++) {
+            map.put(i, Hashing.md5().hashString(i + "abcd", StandardCharsets.UTF_8).asInt());
+        }
+        int i = 0;
+        Map<Integer, Integer> sorted = new HashMap<>();
+        for (Integer integer : map.entrySet().stream().sorted(Map.Entry.comparingByValue()).map(Map.Entry::getKey).collect(Collectors.toList())) {
+            sorted.put(integer, i++);
+        }
+        return sorted.get(number);
+    }
+
+
+    @Test
+    public void testrandomize() {
+        System.out.println(randomize(6, 1000));
+    }
 }