Sfoglia il codice sorgente

Merge branch 'dev' of xiongzhu/9th into master

panhui 3 anni fa
parent
commit
243f805c40

+ 20 - 7
src/main/comos/src/views/product/List.vue

@@ -10,15 +10,13 @@
                 :ellipsis="false"
                 :ellipsis="false"
                 line-width="16"
                 line-width="16"
                 line-height="2"
                 line-height="2"
-                @change="getData(true)"
+                @click-tab="changeTab"
                 :class="{ trans: source == 'TRANSFER' }"
                 :class="{ trans: source == 'TRANSFER' }"
             >
             >
                 <van-tab
                 <van-tab
                     :title="item.label"
                     :title="item.label"
-                    :name="
-                        item.type === 'select' ? (sort === item.value[0] ? item.value[1] : item.value[0]) : item.value
-                    "
-                    :title-class="item.type === 'select' && sort === item.value[0] ? '' : 'asc'"
+                    :name="item.value"
+                    :title-class="item.type === 'select' && sortDes ? sortDes : ''"
                     :key="index"
                     :key="index"
                     v-for="(item, index) in selectOptions"
                     v-for="(item, index) in selectOptions"
                 >
                 >
@@ -64,6 +62,7 @@ export default {
             list: [],
             list: [],
             empty: false,
             empty: false,
             sort: 'id,desc',
             sort: 'id,desc',
+            sortDes: '',
             type: '',
             type: '',
             source: '',
             source: '',
             minterId: '',
             minterId: '',
@@ -82,7 +81,7 @@ export default {
                 },
                 },
                 {
                 {
                     label: '价格',
                     label: '价格',
-                    value: ['price,desc', 'price,asc'],
+                    value: 'price',
                     type: 'select'
                     type: 'select'
                 }
                 }
             ],
             ],
@@ -106,6 +105,8 @@ export default {
         if (this.$route.query.source) {
         if (this.$route.query.source) {
             this.source = this.$route.query.source;
             this.source = this.$route.query.source;
             this.salable = true;
             this.salable = true;
+            this.sort = 'price';
+            this.sortDes = 'asc';
         }
         }
 
 
         if (this.$route.query.minterId) {
         if (this.$route.query.minterId) {
@@ -121,7 +122,19 @@ export default {
         }
         }
     },
     },
     methods: {
     methods: {
+        changeTab(info) {
+            this.$nextTick(() => {
+                if (info.name === 'price') {
+                    this.sortDes = this.sortDes == 'desc' ? 'asc' : 'desc';
+                }
+                this.getData(true);
+            });
+        },
         beforeData() {
         beforeData() {
+            let sort = this.sort;
+            if (sort == 'price') {
+                sort = 'price,' + this.sortDes;
+            }
             return {
             return {
                 query: {
                 query: {
                     type: this.type,
                     type: this.type,
@@ -131,7 +144,7 @@ export default {
                     minterId: this.minterId,
                     minterId: this.minterId,
                     salable: this.salable || ''
                     salable: this.salable || ''
                 },
                 },
-                sort: this.sort === 'id,desc' ? this.sortOptions[this.title] || this.sort : this.sort
+                sort: sort === 'id,desc' ? this.sortOptions[this.title] || sort : sort
             };
             };
         },
         },
         goSearch() {
         goSearch() {

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

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import com.izouma.nineth.converter.FileObjectListConverter;
 import com.izouma.nineth.converter.FileObjectListConverter;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
 
 
@@ -17,6 +18,7 @@ import java.util.List;
 @Entity
 @Entity
 @AllArgsConstructor
 @AllArgsConstructor
 @NoArgsConstructor
 @NoArgsConstructor
+@Builder
 @JsonInclude(JsonInclude.Include.NON_NULL)
 @JsonInclude(JsonInclude.Include.NON_NULL)
 @JsonIgnoreProperties(value = {"hibernateLazyInitializer"}, ignoreUnknown = true)
 @JsonIgnoreProperties(value = {"hibernateLazyInitializer"}, ignoreUnknown = true)
 public class ActivityMaterial extends BaseEntity {
 public class ActivityMaterial extends BaseEntity {

+ 1 - 0
src/main/java/com/izouma/nineth/enums/AssetStatus.java

@@ -6,6 +6,7 @@ public enum AssetStatus {
     TRANSFERRED("已转让"),
     TRANSFERRED("已转让"),
     GIFTING("转赠中"),
     GIFTING("转赠中"),
     GIFTED("已转赠"),
     GIFTED("已转赠"),
+    REDEEMED("已兑换")
     ;
     ;
 
 
     private final String description;
     private final String description;

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

@@ -75,4 +75,6 @@ public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationE
     List<Asset> findByStatusIn(Iterable<AssetStatus> statuses);
     List<Asset> findByStatusIn(Iterable<AssetStatus> statuses);
 
 
     List<Asset> findByFromAssetId(Long id);
     List<Asset> findByFromAssetId(Long id);
+
+    List<Asset> findAllByCollectionIdAndUserIdAndStatus(Long collectionId, Long userId, AssetStatus status);
 }
 }

+ 111 - 13
src/main/java/com/izouma/nineth/service/ActivityOrderService.java

@@ -1,19 +1,23 @@
 package com.izouma.nineth.service;
 package com.izouma.nineth.service;
 
 
-import com.izouma.nineth.domain.ActivityCollection;
-import com.izouma.nineth.domain.ActivityOrder;
+import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.AssetStatus;
+import com.izouma.nineth.enums.OrderStatus;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.exception.BusinessException;
-import com.izouma.nineth.repo.ActivityCollectionRepo;
-import com.izouma.nineth.repo.ActivityOrderRepo;
+import com.izouma.nineth.repo.*;
 import com.izouma.nineth.utils.JpaUtils;
 import com.izouma.nineth.utils.JpaUtils;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Optional;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 
+@Slf4j
 @Service
 @Service
 @AllArgsConstructor
 @AllArgsConstructor
 public class ActivityOrderService {
 public class ActivityOrderService {
@@ -21,23 +25,117 @@ public class ActivityOrderService {
     private ActivityOrderRepo         activityOrderRepo;
     private ActivityOrderRepo         activityOrderRepo;
     private ActivityCollectionRepo    activityCollectionRepo;
     private ActivityCollectionRepo    activityCollectionRepo;
     private ActivityCollectionService activityCollectionService;
     private ActivityCollectionService activityCollectionService;
+    private AssetRepo                 assetRepo;
+    private OrderRepo                 orderRepo;
+    private CollectionRepo            collectionRepo;
+    private ActivityMaterialRepo      activityMaterialRepo;
+    private CollectionService         collectionService;
+    private AssetService              assetService;
+    private UserRepo                  userRepo;
 
 
     public Page<ActivityOrder> all(PageQuery pageQuery) {
     public Page<ActivityOrder> all(PageQuery pageQuery) {
         return activityOrderRepo.findAll(JpaUtils.toSpecification(pageQuery, ActivityOrder.class), JpaUtils.toPageRequest(pageQuery));
         return activityOrderRepo.findAll(JpaUtils.toSpecification(pageQuery, ActivityOrder.class), JpaUtils.toPageRequest(pageQuery));
     }
     }
 
 
 
 
-    public void created(List<Long> assetId, Long mintActivityId) {
-        ActivityCollection collection = activityCollectionRepo.findById(mintActivityId)
-                .orElseThrow(new BusinessException("活动不存在"));
+    public void created(User user, Long mintActivityId) {
+        try {
+            ActivityCollection activity = activityCollectionRepo.findById(mintActivityId)
+                    .orElseThrow(new BusinessException("活动不存在"));
 
 
-        int stock = Optional.ofNullable(activityCollectionService.increaseStock(mintActivityId, -1))
-                .map(Math::toIntExact)
-                .orElseThrow(new BusinessException("很遗憾,活动已无库存"));
+            //库存
+            int stock = Optional.ofNullable(activityCollectionService.increaseStock(mintActivityId, -1))
+                    .map(Math::toIntExact)
+                    .orElseThrow(new BusinessException("很遗憾,活动已无库存"));
+            if (stock < 0) {
+                throw new BusinessException("活动已无库存");
+            }
 
 
-        if (stock < 0) {
-            throw new BusinessException("活动已无库存");
-        }
+            //数量
+            List<Asset> assets = assetRepo.findAllByCollectionIdAndUserIdAndStatus(activity.getCollectionId(), user.getId(),
+                    AssetStatus.NORMAL);
+            if (assets.size() < activity.getNum()) {
+                throw new BusinessException("数量不足,无法领取");
+            }
+
+            //兑换后的
+            Collection award = collectionRepo.findById(activity.getAwardCollectionId())
+                    .orElseThrow(new BusinessException("无藏品"));
+
+            int awardStock = Optional.ofNullable(collectionService.decreaseStock(activity.getAwardCollectionId(), 1))
+                    .map(Math::toIntExact)
+                    .orElseThrow(new BusinessException("兑换藏品无库存"));
+            if (awardStock < 0) {
+                throw new BusinessException("兑换藏品无库存");
+            }
+
+            //指定账户
+            User newOwner = userRepo.findByIdAndDelFalse(1590945L).orElseThrow(new BusinessException("无法兑换"));
+
+            List<Asset> consumption = assets.stream().limit(activity.getNum()).collect(Collectors.toList());
+            //消耗资产
+            consumption.forEach(asset -> {
+                if (asset.isPublicShow()) {
+//                    if (asset.isConsignment()) {
+//                        asset.setConsignment(false);
+//                    }
 
 
+                    if (asset.getPublicCollectionId() != null) {
+                        List<Order> orders = orderRepo.findByCollectionId(asset.getPublicCollectionId());
+                        if (orders.stream().anyMatch(o -> o.getStatus() != OrderStatus.CANCELLED)) {
+                            throw new BusinessException("已有订单不可兑换");
+                        }
+                        Collection collection = collectionRepo.findById(asset.getPublicCollectionId())
+                                .orElseThrow(new BusinessException("无展示记录"));
+                        List<Long> collectionIds = collectionRepo.findAllByAssetId(collection.getAssetId());
+                        if (CollectionUtils.isNotEmpty(collectionIds)) {
+                            log.info("删除collection {}", collectionIds);
+                            collectionRepo.deleteAllByIdIn(collectionIds);
+                        } else {
+                            log.info("删除collection {}", collection.getId());
+                            collectionRepo.delete(collection);
+                        }
+                    }
+//
+//                asset.setPublicShow(false);
+//                asset.setPublicCollectionId(null);
+                }
+//            asset.setStatus(AssetStatus.REDEEMED);
+//            assetRepo.save(asset);
+            });
+
+            //收集记录
+            ActivityOrder order = activityOrderRepo.save(ActivityOrder.builder()
+                    .userId(user.getId())
+                    .phone(user.getPhone())
+                    .activityCollection(activity.getCollectionName())
+                    .activityCollectionId(mintActivityId)
+                    .build());
+
+            //兑换详情
+            consumption.forEach(asset -> {
+                activityMaterialRepo.save(
+                        ActivityMaterial.builder()
+                                .orderId(order.getId())
+                                .assetId(asset.getId())
+                                .category(asset.getCategory())
+                                .collectionId(asset.getCollectionId())
+                                .name(asset.getName())
+                                .number(asset.getNumber())
+                                .pic(asset.getPic())
+                                .build());
+                // 转赠
+                assetService.transfer(asset, asset.getPrice(), newOwner, "转赠", null);
+            });
+
+            //发放新的
+            assetService.createAsset(award, user, order.getId(), null, "兑换",
+                    award.getTotal() > 1 ? collectionService.getNextNumber(award.getId()) : null);
+
+        } catch (Exception e) {
+            // 错了加库存
+            activityCollectionService.increaseStock(mintActivityId, 1);
+            throw e;
+        }
     }
     }
 }
 }

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

@@ -370,11 +370,16 @@ public class AssetService {
                 case "转让":
                 case "转让":
                     userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "作品交易——买入" : "作品交易——售出");
                     userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "作品交易——买入" : "作品交易——售出");
                     break;
                     break;
+                case "兑换":
+                    userHistory.setDescription("兑换");
                 case "空投":
                 case "空投":
                     userHistory.setDescription("空投");
                     userHistory.setDescription("空投");
                     break;
                     break;
                 case "转赠":
                 case "转赠":
                     userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "他人赠送" : "作品赠送");
                     userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "他人赠送" : "作品赠送");
+                    if (userHistory.getToUserId().equals(1590945L)) {
+                        userHistory.setDescription("活动收集销毁");
+                    }
                     break;
                     break;
             }
             }
             return userHistory;
             return userHistory;

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

@@ -474,10 +474,11 @@ public class OrderService {
                         Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
                         Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
                         assetService.transfer(asset, order.getPrice(), user, "转让", order.getId());
                         assetService.transfer(asset, order.getPrice(), user, "转让", order.getId());
                         List<Long> collectionIds = collectionRepo.findAllByAssetId(collection.getAssetId());
                         List<Long> collectionIds = collectionRepo.findAllByAssetId(collection.getAssetId());
-                        log.info("删除collection {}", collectionIds);
                         if (CollectionUtils.isNotEmpty(collectionIds)) {
                         if (CollectionUtils.isNotEmpty(collectionIds)) {
+                            log.info("删除collection {}", collectionIds);
                             collectionRepo.deleteAllByIdIn(collectionIds);
                             collectionRepo.deleteAllByIdIn(collectionIds);
                         } else {
                         } else {
+                            log.info("删除collection {}", collection.getId());
                             collectionRepo.delete(collection);
                             collectionRepo.delete(collection);
                         }
                         }
 
 

+ 47 - 4
src/main/nine-space/src/views/account/Register.vue

@@ -24,6 +24,21 @@
                 </template>
                 </template>
             </van-field>
             </van-field>
 
 
+            <van-field
+                name="图形验证码"
+                placeholder="请输入图形验证码"
+                v-model="form.captcha"
+                :maxlength="6"
+                :rules="[{ required: true, message: '请输入图形验证码' }]"
+            >
+                <template #left-icon>
+                    <img :src="require('@assets/svgs/login_icon_code.svg')" class="icon" />
+                </template>
+                <template #button>
+                    <van-image @click="getCode" :src="codeImg" width="68" height="32" fit="contain" />
+                </template>
+            </van-field>
+
             <van-field
             <van-field
                 type="digit"
                 type="digit"
                 name="验证码"
                 name="验证码"
@@ -135,15 +150,43 @@ export default {
                 password: '',
                 password: '',
                 password2: '',
                 password2: '',
                 code: '',
                 code: '',
-                inviteCode: this.$store.state.inviteCode || ''
+                inviteCode: this.$store.state.inviteCode || '',
+                captchaKey: '',
+                captcha: ''
             },
             },
+            codeImg: '',
             checked: false
             checked: false
         };
         };
     },
     },
+    mounted() {
+        this.getCode();
+    },
     methods: {
     methods: {
+        getCode() {
+            this.$http.get('/captcha/get').then(res => {
+                this.form.captchaKey = res.key;
+                this.codeImg = res.image;
+            });
+        },
         sendPhone() {
         sendPhone() {
-            this.$refs.form.validate('手机号码').then(() => {
-                this.sendMsg(this.form.phone);
+            this.$refs.form.validate(['手机号码', '图形验证码']).then(() => {
+                // this.sendMsg(this.form.phone);
+                this.$http
+                    .get('/sms/sendCaptchaVerify', {
+                        phone: this.form.phone,
+                        captchaKey: this.form.captchaKey,
+                        captcha: this.form.captcha
+                    })
+                    .then(res => {
+                        this.isSend = true;
+                        this.setTime(60);
+                        this.msgCode = res;
+                        this.$toast.success('发送成功');
+                    })
+                    .catch(e => {
+                        this.$toast(e.error);
+                        this.setTime(0);
+                    });
             });
             });
         },
         },
         submit() {
         submit() {
@@ -164,7 +207,7 @@ export default {
                 .then(() => {
                 .then(() => {
                     this.$toast.success('注册成功');
                     this.$toast.success('注册成功');
                     setTimeout(() => {
                     setTimeout(() => {
-                        this.$router.back();
+                        this.$router.push('/home');
                     }, 1500);
                     }, 1500);
                 })
                 })
                 .catch(e => {
                 .catch(e => {

+ 65 - 9
src/main/nine-space/src/views/product/List.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
     <div class="follow">
     <div class="follow">
-        <van-sticky ref="top" :offset-top="bar.value.show ? 46 : 0">
+        <van-sticky ref="top" class="list-top" :offset-top="bar.value.show ? 46 : 0">
             <div class="top" v-if="!minterId">
             <div class="top" v-if="!minterId">
                 <div class="name">{{ title || pageName }}</div>
                 <div class="name">{{ title || pageName }}</div>
                 <img v-if="!title" src="@assets/icon-sosuo.png" alt="" @click="goSearch" class="search" />
                 <img v-if="!title" src="@assets/icon-sosuo.png" alt="" @click="goSearch" class="search" />
@@ -11,14 +11,13 @@
                 :ellipsis="false"
                 :ellipsis="false"
                 line-width="16"
                 line-width="16"
                 line-height="2"
                 line-height="2"
-                @change="getData(true)"
+                @click-tab="changeTab"
+                :class="{ trans: source == 'TRANSFER' }"
             >
             >
                 <van-tab
                 <van-tab
                     :title="item.label"
                     :title="item.label"
-                    :name="
-                        item.type === 'select' ? (sort === item.value[0] ? item.value[1] : item.value[0]) : item.value
-                    "
-                    :title-class="item.type === 'select' && sort === item.value[0] ? '' : 'asc'"
+                    :name="item.value"
+                    :title-class="item.type === 'select' && sortDes ? sortDes : ''"
                     :key="index"
                     :key="index"
                     v-for="(item, index) in selectOptions"
                     v-for="(item, index) in selectOptions"
                 >
                 >
@@ -31,6 +30,9 @@
                     </template>
                     </template>
                 </van-tab>
                 </van-tab>
             </van-tabs>
             </van-tabs>
+            <van-checkbox v-if="source == 'TRANSFER' && !title" @change="getData(true)" class="sala" v-model="salable"
+                >仅看在售</van-checkbox
+            >
         </van-sticky>
         </van-sticky>
 
 
         <van-list v-model:loading="loading" :finished="finished" finished-text="" @load="getData">
         <van-list v-model:loading="loading" :finished="finished" finished-text="" @load="getData">
@@ -60,6 +62,7 @@ export default {
             list: [],
             list: [],
             empty: false,
             empty: false,
             sort: 'soldOut;id,desc',
             sort: 'soldOut;id,desc',
+            sortDes: '',
             type: '',
             type: '',
             source: '',
             source: '',
             minterId: '',
             minterId: '',
@@ -78,11 +81,12 @@ export default {
                 },
                 },
                 {
                 {
                     label: '价格',
                     label: '价格',
-                    value: ['price,desc', 'price,asc'],
+                    value: 'price',
                     type: 'select'
                     type: 'select'
                 }
                 }
             ],
             ],
             url: '/collection/all',
             url: '/collection/all',
+            salable: false,
             title: ''
             title: ''
         };
         };
     },
     },
@@ -98,6 +102,9 @@ export default {
 
 
         if (this.$route.query.source) {
         if (this.$route.query.source) {
             this.source = this.$route.query.source;
             this.source = this.$route.query.source;
+            this.salable = true;
+            this.sort = 'price';
+            this.sortDes = 'asc';
         }
         }
 
 
         if (this.$route.query.minterId) {
         if (this.$route.query.minterId) {
@@ -113,16 +120,29 @@ export default {
         }
         }
     },
     },
     methods: {
     methods: {
+        changeTab(info) {
+            this.$nextTick(() => {
+                if (info.name === 'price') {
+                    this.sortDes = this.sortDes == 'desc' ? 'asc' : 'desc';
+                }
+                this.getData(true);
+            });
+        },
         beforeData() {
         beforeData() {
+            let sort = this.sort;
+            if (sort == 'price') {
+                sort = 'price,' + this.sortDes;
+            }
             return {
             return {
                 query: {
                 query: {
                     type: this.type,
                     type: this.type,
                     source: this.source,
                     source: this.source,
                     onShelf: true,
                     onShelf: true,
                     del: false,
                     del: false,
-                    minterId: this.minterId
+                    minterId: this.minterId,
+                    salable: this.salable || ''
                 },
                 },
-                sort: this.sortOptions[this.title] || this.sort
+                sort: this.sortOptions[this.title] || sort
             };
             };
         },
         },
         goSearch() {
         goSearch() {
@@ -195,7 +215,43 @@ export default {
     }
     }
 }
 }
 
 
+.list-top {
+    position: relative;
+}
 .van-tabs {
 .van-tabs {
     background-color: @bg;
     background-color: @bg;
 }
 }
+/deep/.trans {
+    .van-tab {
+        margin-right: 30px;
+    }
+}
+/deep/.sala {
+    position: absolute;
+    right: 16px;
+    top: 63px;
+    .van-checkbox__icon {
+        color: #fff;
+        transform: scale(0.6);
+
+        .van-icon {
+            border-color: @text3;
+        }
+
+        &.van-checkbox__icon--checked {
+            .van-icon {
+                border-width: 0;
+                .linear();
+                &::before {
+                    color: #fff;
+                }
+            }
+        }
+    }
+    .van-checkbox__label {
+        color: @text3;
+        margin-left: 0px;
+        font-size: @font1;
+    }
+}
 </style>
 </style>

+ 4 - 2
src/main/nine-space/src/views/product/Search.vue

@@ -89,9 +89,11 @@ export default {
                     type: this.type,
                     type: this.type,
                     source: this.source,
                     source: this.source,
                     minterId: this.minterId,
                     minterId: this.minterId,
-                    del: false
+                    del: false,
+                    salable: true
                 },
                 },
-                search: this.search
+                search: this.search,
+                sort: 'price,asc'
             };
             };
         }
         }
     }
     }

+ 21 - 0
src/test/java/com/izouma/nineth/service/ActivityOrderServiceTest.java

@@ -0,0 +1,21 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.ApplicationTests;
+import com.izouma.nineth.domain.User;
+import com.izouma.nineth.repo.UserRepo;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class ActivityOrderServiceTest extends ApplicationTests {
+
+    @Autowired
+    private ActivityOrderService activityOrderService;
+    @Autowired
+    private UserRepo             userRepo;
+
+    @Test
+    public void created() {
+        User user = userRepo.findById(7834L).orElse(null);
+        activityOrderService.created(user, 8847L);
+    }
+}