Просмотр исходного кода

Merge branch 'master' of http://git.izouma.com/xiongzhu/9th

xuqiang 4 лет назад
Родитель
Сommit
977be041b1

+ 2 - 1
src/main/java/com/izouma/nineth/enums/BannerType.java

@@ -4,7 +4,8 @@ public enum BannerType {
     HOME("首页"),
     DISCOVER("探索"),
     MINTER("铸造者"),
-    MARKET("市场");
+    MARKET("市场"),
+    PC_ACT("PC官方活动");
 
     private final String description;
 

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

@@ -93,4 +93,6 @@ public interface UserRepo extends JpaRepository<User, Long>, JpaSpecificationExe
     void updateMinterForAsset(Long userId);
 
     List<User> findByPhoneInAndDelFalse(Iterable<String> phone);
+
+    List<User> findByIdInAndDelFalse(Iterable<Long> userId);
 }

+ 9 - 1
src/main/java/com/izouma/nineth/security/JwtTokenUtil.java

@@ -15,6 +15,7 @@ import java.io.Serializable;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Optional;
 import java.util.function.Function;
 
 @Component
@@ -62,7 +63,14 @@ public class JwtTokenUtil implements Serializable {
 
     private Boolean isTokenExpired(String token) {
         final Date expiration = getExpirationDateFromToken(token);
-        return expiration.before(clock.now()) || !userTokenRepo.findById(getUsernameFromToken(token)).isPresent();
+        Optional<UserToken> userToken = userTokenRepo.findById(getUsernameFromToken(token));
+        if (!userToken.isPresent()) {
+            return true;
+        }
+        if (!token.equals(userToken.get().getToken())) {
+            return true;
+        }
+        return expiration.before(clock.now());
     }
 
     private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {

+ 29 - 12
src/main/java/com/izouma/nineth/service/AirDropService.java

@@ -1,32 +1,33 @@
 package com.izouma.nineth.service;
 
-import com.izouma.nineth.domain.AirDrop;
-import com.izouma.nineth.domain.Collection;
-import com.izouma.nineth.domain.Coupon;
-import com.izouma.nineth.domain.UserCoupon;
+import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.enums.AirDropType;
+import com.izouma.nineth.enums.CollectionType;
 import com.izouma.nineth.exception.BusinessException;
-import com.izouma.nineth.repo.AirDropRepo;
-import com.izouma.nineth.repo.CollectionRepo;
-import com.izouma.nineth.repo.CouponRepo;
-import com.izouma.nineth.repo.UserCouponRepo;
+import com.izouma.nineth.repo.*;
 import com.izouma.nineth.utils.JpaUtils;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 
 import javax.transaction.Transactional;
+import java.util.List;
 
 @Service
 @AllArgsConstructor
+@Slf4j
 public class AirDropService {
 
-    private AirDropRepo    airDropRepo;
-    private CouponRepo     couponRepo;
-    private UserCouponRepo userCouponRepo;
-    private CollectionRepo collectionRepo;
+    private AirDropRepo       airDropRepo;
+    private CouponRepo        couponRepo;
+    private UserCouponRepo    userCouponRepo;
+    private CollectionRepo    collectionRepo;
+    private UserRepo          userRepo;
+    private AssetService      assetService;
+    private CollectionService collectionService;
 
     public Page<AirDrop> all(PageQuery pageQuery) {
         return airDropRepo.findAll(JpaUtils.toSpecification(pageQuery, AirDrop.class), JpaUtils.toPageRequest(pageQuery));
@@ -50,6 +51,22 @@ public class AirDropService {
             if (collection.getStock() < record.getUserIds().size()) {
                 throw new BusinessException("藏品库存不足");
             }
+            List<User> users = userRepo.findByIdInAndDelFalse(record.getUserIds());
+            for (User user : users) {
+                try {
+                    if (collection.getType() == CollectionType.BLIND_BOX) {
+                        assetService.createAsset(collection, user, null, collection.getPrice(), "空投");
+                    } else {
+                        BlindBoxItem winItem = collectionService.draw(collection.getId());
+                        assetService.createAsset(winItem, user, null, collection.getPrice(), "空投");
+                    }
+                    collection.setStock(collection.getStock() - 1);
+                    collection.setSale(collection.getSale() + 1);
+                    collectionRepo.save(collection);
+                } catch (Exception e) {
+                    log.error("空投出错", e);
+                }
+            }
         }
         return airDropRepo.save(record);
     }

+ 86 - 0
src/main/java/com/izouma/nineth/service/AssetMintService.java

@@ -0,0 +1,86 @@
+package com.izouma.nineth.service;
+
+import com.alipay.api.AlipayClient;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.kevinsawicki.http.HttpRequest;
+import com.izouma.nineth.config.AlipayProperties;
+import com.izouma.nineth.config.WxPayProperties;
+import com.izouma.nineth.domain.Asset;
+import com.izouma.nineth.domain.User;
+import com.izouma.nineth.dto.NFT;
+import com.izouma.nineth.dto.NFTAccount;
+import com.izouma.nineth.event.CreateAssetEvent;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.*;
+import io.ipfs.api.IPFS;
+import io.ipfs.api.MerkleNode;
+import io.ipfs.api.NamedStreamable;
+import io.ipfs.multihash.Multihash;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+
+@Service
+@Slf4j
+@AllArgsConstructor
+public class AssetMintService {
+    private AssetRepo          assetRepo;
+    private UserRepo           userRepo;
+    private NFTService         nftService;
+    private ApplicationContext applicationContext;
+    private TokenHistoryRepo   tokenHistoryRepo;
+    private Environment        env;
+
+    public void mint(Asset asset, Long historyId) {
+        User user = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
+        if (StringUtils.isEmpty(user.getPublicKey())) {
+            NFTAccount account = nftService.createAccount(user.getUsername());
+            user.setNftAccount(account.getAccountId());
+            user.setKmsId(account.getAccountKmsId());
+            user.setPublicKey(account.getPublicKey());
+            userRepo.save(user);
+        }
+        try {
+            NFT nft = nftService.createToken(user.getNftAccount());
+            if (nft != null) {
+                asset.setTokenId(nft.getTokenId());
+                asset.setBlockNumber(nft.getBlockNumber());
+                asset.setTxHash(nft.getTxHash());
+                asset.setGasUsed(nft.getGasUsed());
+                if (asset.getIpfsUrl() == null) {
+                    asset.setIpfsUrl(ipfsUpload(asset.getPic().get(0).getUrl()));
+                }
+                assetRepo.save(asset);
+
+                tokenHistoryRepo.findById(historyId).ifPresent(tokenHistory -> {
+                    tokenHistory.setTokenId(nft.getTokenId());
+                    tokenHistoryRepo.save(tokenHistory);
+                });
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        applicationContext.publishEvent(new CreateAssetEvent(this, true, asset));
+    }
+
+    public String ipfsUpload(String url) {
+        try {
+            IPFS ipfs = new IPFS("112.74.34.84", 5001);
+            HttpRequest request = HttpRequest.get(url);
+            File file = File.createTempFile("ipfs", ".tmp");
+            request.receive(file);
+            NamedStreamable.FileWrapper file1 = new NamedStreamable.FileWrapper(file);
+            MerkleNode put = ipfs.add(file1).get(0);
+            Multihash multihash = ipfs.pin.add(put.hash).get(0);
+            log.info("上传ipfs成功 {}", multihash.toBase58());
+            return multihash.toBase58();
+        } catch (Exception e) {
+        }
+        return null;
+    }
+}

+ 14 - 53
src/main/java/com/izouma/nineth/service/AssetService.java

@@ -39,6 +39,8 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.context.ApplicationContext;
 import org.springframework.core.env.Environment;
 import org.springframework.data.domain.Page;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Service;
 import org.springframework.ui.Model;
 
@@ -49,6 +51,7 @@ import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.Future;
 
 @Service
 @AllArgsConstructor
@@ -69,16 +72,18 @@ public class AssetService {
     private WxPayProperties    wxPayProperties;
     private WxPayService       wxPayService;
     private Environment        env;
+    private AssetMintService   assetMintService;
 
     public Page<Asset> all(PageQuery pageQuery) {
         return assetRepo.findAll(JpaUtils.toSpecification(pageQuery, Asset.class), JpaUtils.toPageRequest(pageQuery));
     }
 
-    public Asset createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type) {
+    @Async
+    public Future<Asset> createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type) {
         Asset asset = Asset.create(collection, user);
         asset.setOrderId(orderId);
         asset.setPrice(price);
-        asset.setIpfsUrl(ipfsUpload(collection.getPic().get(0).getUrl()));
+        asset.setIpfsUrl(assetMintService.ipfsUpload(collection.getPic().get(0).getUrl()));
         assetRepo.save(asset);
 
         TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
@@ -90,15 +95,16 @@ public class AssetService {
                 .operation(type)
                 .price(price)
                 .build());
-        mint(asset, tokenHistory.getId());
-        return asset;
+        assetMintService.mint(asset, tokenHistory.getId());
+        return new AsyncResult<>(asset);
     }
 
-    public Asset createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type) {
+    @Async
+    public Future<Asset> createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type) {
         Asset asset = Asset.create(winItem, user);
         asset.setOrderId(orderId);
         asset.setPrice(price);
-        asset.setIpfsUrl(ipfsUpload(winItem.getPic().get(0).getUrl()));
+        asset.setIpfsUrl(assetMintService.ipfsUpload(winItem.getPic().get(0).getUrl()));
         assetRepo.save(asset);
         TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
                 .tokenId(asset.getTokenId())
@@ -109,55 +115,10 @@ public class AssetService {
                 .operation(type)
                 .price(price)
                 .build());
-        mint(asset, tokenHistory.getId());
-        return asset;
+        assetMintService.mint(asset, tokenHistory.getId());
+        return new AsyncResult<>(asset);
     }
 
-    public void mint(Asset asset, Long historyId) {
-        User user = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
-        if (StringUtils.isEmpty(user.getPublicKey())) {
-            NFTAccount account = nftService.createAccount(user.getUsername());
-            user.setNftAccount(account.getAccountId());
-            user.setKmsId(account.getAccountKmsId());
-            user.setPublicKey(account.getPublicKey());
-            userRepo.save(user);
-        }
-        try {
-            NFT nft = nftService.createToken(user.getNftAccount());
-            if (nft != null) {
-                asset.setTokenId(nft.getTokenId());
-                asset.setBlockNumber(nft.getBlockNumber());
-                asset.setTxHash(nft.getTxHash());
-                asset.setGasUsed(nft.getGasUsed());
-                asset.setIpfsUrl(ipfsUpload(asset.getPic().get(0).getUrl()));
-                assetRepo.save(asset);
-
-                tokenHistoryRepo.findById(historyId).ifPresent(tokenHistory -> {
-                    tokenHistory.setTokenId(nft.getTokenId());
-                    tokenHistoryRepo.save(tokenHistory);
-                });
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        applicationContext.publishEvent(new CreateAssetEvent(this, true, asset));
-    }
-
-    public String ipfsUpload(String url) {
-        try {
-            IPFS ipfs = new IPFS("112.74.34.84", 5001);
-            HttpRequest request = HttpRequest.get(url);
-            File file = File.createTempFile("ipfs", ".tmp");
-            request.receive(file);
-            NamedStreamable.FileWrapper file1 = new NamedStreamable.FileWrapper(file);
-            MerkleNode put = ipfs.add(file1).get(0);
-            Multihash multihash = ipfs.pin.add(put.hash).get(0);
-            log.info("上传ipfs成功 {}", multihash.toBase58());
-            return multihash.toBase58();
-        } catch (Exception e) {
-        }
-        return null;
-    }
 
     public void publicShow(Long id) {
         Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));

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

@@ -243,6 +243,9 @@ public class CollectionService {
                 throw new BusinessException("盲盒抽卡失败");
             }
         }
+        winItem.setStock(winItem.getStock() - 1);
+        winItem.setSale(winItem.getSale() + 1);
+        blindBoxItemRepo.save(winItem);
         return winItem;
     }
 

+ 52 - 17
src/main/java/com/izouma/nineth/service/OrderService.java

@@ -44,20 +44,21 @@ import java.util.*;
 @Slf4j
 public class OrderService {
 
-    private OrderRepo        orderRepo;
-    private CollectionRepo   collectionRepo;
-    private UserAddressRepo  userAddressRepo;
-    private UserRepo         userRepo;
-    private Environment      env;
-    private AlipayClient     alipayClient;
-    private AlipayProperties alipayProperties;
-    private WxPayService     wxPayService;
-    private WxPayProperties  wxPayProperties;
-    private AssetService     assetService;
-    private SysConfigService sysConfigService;
-    private BlindBoxItemRepo blindBoxItemRepo;
-    private AssetRepo        assetRepo;
-    private UserCouponRepo   userCouponRepo;
+    private OrderRepo         orderRepo;
+    private CollectionRepo    collectionRepo;
+    private UserAddressRepo   userAddressRepo;
+    private UserRepo          userRepo;
+    private Environment       env;
+    private AlipayClient      alipayClient;
+    private AlipayProperties  alipayProperties;
+    private WxPayService      wxPayService;
+    private WxPayProperties   wxPayProperties;
+    private AssetService      assetService;
+    private SysConfigService  sysConfigService;
+    private BlindBoxItemRepo  blindBoxItemRepo;
+    private AssetRepo         assetRepo;
+    private UserCouponRepo    userCouponRepo;
+    private CollectionService collectionService;
 
     public Page<Order> all(PageQuery pageQuery) {
         return orderRepo.findAll(JpaUtils.toSpecification(pageQuery, Order.class), JpaUtils.toPageRequest(pageQuery));
@@ -232,7 +233,7 @@ public class OrderService {
 
     }
 
-    public void notifyOrder(Long orderId, PayMethod payMethod, String transactionId) {
+    public void notifyOrder1(Long orderId, PayMethod payMethod, String transactionId) {
         Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
         Collection collection = collectionRepo.findById(order.getCollectionId())
                 .orElseThrow(new BusinessException("藏品不存在"));
@@ -294,7 +295,41 @@ public class OrderService {
                 order.setTransactionId(transactionId);
                 order.setPayMethod(payMethod);
                 orderRepo.save(order);
-                Asset asset = assetService.createAsset(winItem, user, order.getId(), order.getPrice(), "出售");
+                assetService.createAsset(winItem, user, order.getId(), order.getPrice(), "出售");
+            } else {
+                if (collection.getSource() == CollectionSource.TRANSFER) {
+                    Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
+                    assetService.transfer(asset, user);
+                    collectionRepo.delete(collection);
+                } else {
+                    order.setStatus(OrderStatus.PROCESSING);
+                    order.setPayTime(LocalDateTime.now());
+                    order.setTransactionId(transactionId);
+                    order.setPayMethod(payMethod);
+                    orderRepo.save(order);
+                    assetService.createAsset(collection, user, order.getId(), order.getPrice(), "出售");
+                }
+            }
+        } else if (order.getStatus() == OrderStatus.CANCELLED) {
+        }
+    }
+
+    @Transactional
+    public void notifyOrder(Long orderId, PayMethod payMethod, String transactionId) {
+        Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
+        Collection collection = collectionRepo.findById(order.getCollectionId())
+                .orElseThrow(new BusinessException("藏品不存在"));
+        User user = userRepo.findById(order.getUserId()).orElseThrow(new BusinessException("用户不存在"));
+        if (order.getStatus() == OrderStatus.NOT_PAID) {
+            if (order.getType() == CollectionType.BLIND_BOX) {
+                BlindBoxItem winItem = collectionService.draw(collection.getId());
+
+                order.setStatus(OrderStatus.PROCESSING);
+                order.setPayTime(LocalDateTime.now());
+                order.setTransactionId(transactionId);
+                order.setPayMethod(payMethod);
+                orderRepo.save(order);
+                assetService.createAsset(winItem, user, order.getId(), order.getPrice(), "出售");
             } else {
                 if (collection.getSource() == CollectionSource.TRANSFER) {
                     Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
@@ -306,7 +341,7 @@ public class OrderService {
                     order.setTransactionId(transactionId);
                     order.setPayMethod(payMethod);
                     orderRepo.save(order);
-                    Asset asset = assetService.createAsset(collection, user, order.getId(), order.getPrice(), "出售");
+                    assetService.createAsset(collection, user, order.getId(), order.getPrice(), "出售");
                 }
             }
         } else if (order.getStatus() == OrderStatus.CANCELLED) {

+ 25 - 0
src/main/java/com/izouma/nineth/web/OrderPayController.java

@@ -1,11 +1,17 @@
 package com.izouma.nineth.web;
 
+import com.alibaba.fastjson.JSON;
+import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
 import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.izouma.nineth.service.AssetService;
 import com.izouma.nineth.service.OrderService;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
 import org.apache.commons.codec.EncoderException;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
@@ -20,6 +26,7 @@ import java.util.regex.Pattern;
 public class OrderPayController {
     private final OrderService orderService;
     private final AssetService assetService;
+    private final WxMpService  wxMpService;
 
     @RequestMapping(value = "/alipay", method = RequestMethod.GET)
     public String payOrderAlipay(Long id, Model model, @RequestHeader(value = "User-Agent") String userAgent) {
@@ -41,6 +48,15 @@ public class OrderPayController {
         return orderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, openId);
     }
 
+    @RequestMapping(value = "/weixin_pc")
+    public String payOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
+        WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
+        WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
+        WxPayMpOrderResult payParams = (WxPayMpOrderResult) orderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
+        model.addAttribute("payParams", JSON.toJSONString(payParams));
+        return "PayOrderPC";
+    }
+
     @RequestMapping(value = "/gift/alipay", method = RequestMethod.GET)
     public String payGiftOrderAlipay(Long id, Model model, @RequestHeader(value = "User-Agent") String userAgent) {
         detectUA(userAgent, model);
@@ -55,6 +71,15 @@ public class OrderPayController {
         return "WeixinPayHtml";
     }
 
+    @RequestMapping(value = "/gift/weixin_pc")
+    public String payGiftOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
+        WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
+        WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
+        WxPayMpOrderResult payParams = (WxPayMpOrderResult) assetService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
+        model.addAttribute("payParams", JSON.toJSONString(payParams));
+        return "PayOrderPC";
+    }
+
     public void detectUA(String ua, Model model) {
         boolean weixin = Pattern.matches(".*(micromessenger).*", ua.toLowerCase());
         boolean ios = Pattern.matches(".*(ipad|iphone).*", ua.toLowerCase());

+ 2 - 2
src/main/pc-space/src/views/Home.vue

@@ -56,7 +56,7 @@
             <div class="hot">官方活动</div>
             <swiper class="mySwiper" ref="mySwiper" :options="swiperOptions">
                 <swiper-slide v-for="(item, index) in banners" :key="index">
-                    <el-image @click="goNext(item)" :src="item.pic" fit="fill" :lazy="true"></el-image>
+                    <el-image @click="goNext(item)" :src="item.pic" fit="cover" :lazy="true"></el-image>
                 </swiper-slide>
             </swiper>
             <more-title path="/collection"></more-title>
@@ -151,7 +151,7 @@ export default {
                 '/banner/all',
                 {
                     query: {
-                        type: 'HOME'
+                        type: 'PC_ACT'
                     },
                     sort: 'createdAt,desc'
                 },

+ 1 - 1
src/main/pc-space/vue.config.js

@@ -1,6 +1,6 @@
 const path = require('path');
 module.exports = {
-    publicPath: process.env.NODE_ENV === 'production' ? '/web/' : '/',
+    publicPath: process.env.NODE_ENV === 'production' ? '/9th/' : '/',
     devServer: {
         port: 8081,
         disableHostCheck: true

+ 117 - 0
src/main/resources/templates/PayOrderPC.ftlh

@@ -0,0 +1,117 @@
+<!doctype html>
+<html lang="zh-cmn-Hans">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>支付</title>
+    <link rel="stylesheet" type="text/css" href="https://res.wx.qq.com/open/libs/weui/2.1.4/weui.min.css"/>
+    <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
+    <script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>
+    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
+    <style>
+        body, html {
+            width: 100%;
+            height: 100%;
+        }
+    </style>
+</head>
+<body>
+<div id="dialog" style="display: none;">
+    <div class="weui-mask"></div>
+    <div class="weui-dialog">
+        <div class="weui-dialog__hd" id="dialogHeader"><strong class="weui-dialog__title"
+                                                               id="dialogHeaderContent">弹窗标题</strong></div>
+        <div class="weui-dialog__bd" id="dialogBody">弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内</div>
+        <div class="weui-dialog__ft" id="dialogFooter">
+            <a href="javascript:;" class="weui-dialog__btn weui-dialog__btn_default" id="dialogCancel">辅助操作</a>
+            <a href="javascript:;" class="weui-dialog__btn weui-dialog__btn_primary" id="dialogConfirm">主操作</a>
+        </div>
+    </div>
+</div>
+<script>
+    //var vConsole = new VConsole();
+    var payParams = ${payParams?no_esc};
+    payParams.package = payParams.packageValue;
+    payParams.timestamp = payParams.timeStamp;
+    payParams.success = function (res) {
+        showDialog({
+            title: '支付成功',
+            message: '',
+            confirm: function () {
+                hideDialog();
+                window.close();
+            }
+        });
+    };
+    payParams.cancel = function (e) {
+        console.log(e);
+        showDialog({
+            title: '支付取消',
+            message: '',
+            confirm: function () {
+                hideDialog();
+                window.close();
+            }
+        });
+    };
+    payParams.fail = function (e) {
+        console.log(e);
+        showDialog({
+            title: '支付取消',
+            message: '',
+            confirm: function () {
+                hideDialog();
+                window.close();
+            }
+        });
+    }
+    console.log(payParams);
+    window.onload = function () {
+        $.get('/wx/jsapiSign', {url: encodeURI(window.location.href.split('#')[0]),}, function (res) {
+            res.debug = false;
+            res.jsApiList = [
+                'chooseWXPay',
+                'updateAppMessageShareData',
+                'updateTimelineShareData',
+                'hideAllNonBaseMenuItem',
+                'scanQRCode',
+            ];
+            wx.config(res);
+        });
+        wx.ready(function (res) {
+            console.log('jssdk ready', res);
+            wx.chooseWXPay(payParams);
+        });
+    }
+
+    function showDialog(options) {
+        $('#dialogHeader').show();
+        $('#dialogHeaderContent').html(options.title || '提示');
+        if (options.showCancel === undefined) {
+            options.showCancel = false;
+        }
+        if (options.showCancel) {
+            $('#dialogCancel').show();
+            $('#dialogCancel').html(options.cancelText || '取消');
+            $('#dialogCancel').on('click', function () {
+                options.cancel ? options.cancel() : hideDialog();
+            })
+        } else {
+            $('#dialogCancel').hide();
+        }
+        $('#dialogConfirm').html(options.cancelText || '确定');
+        $('#dialogConfirm').on('click', function () {
+            options.confirm ? options.confirm() : hideDialog();
+        });
+        $('#dialogBody').html(options.message);
+        $('#dialog').show(200);
+    }
+
+    function hideDialog(){
+        $('#dialog').hide(200);
+    }
+</script>
+</body>
+</html>

+ 2 - 1
src/main/vue/src/views/BannerEdit.vue

@@ -125,7 +125,8 @@ export default {
                 { label: '首页', value: 'HOME' },
                 { label: '探索', value: 'DISCOVER' },
                 { label: '铸造者', value: 'MINTER' },
-                { label: '市场', value: 'MARKET' }
+                { label: '市场', value: 'MARKET' },
+                { label: 'PC官方活动', value: 'PC_ACT' }
             ]
         };
     },

+ 2 - 1
src/main/vue/src/views/BannerList.vue

@@ -111,7 +111,8 @@ export default {
                 { label: '首页', value: 'HOME' },
                 { label: '探索', value: 'DISCOVER' },
                 { label: '铸造者', value: 'MINTER' },
-                { label: '市场', value: 'MARKET' }
+                { label: '市场', value: 'MARKET' },
+                { label: 'PC官方活动', value: 'PC_ACT' }
             ],
             type: null
         };

+ 3 - 3
src/main/vue/src/views/CollectionEdit.vue

@@ -81,6 +81,9 @@
                             </el-table-column>
                         </el-table>
                     </el-form-item>
+                    <el-form-item>
+                        <el-button size="mini" @click="addProperty" :disabled="!canEdit"> 添加特性 </el-button>
+                    </el-form-item>
                     <el-form-item label="特权" prop="privileges" style="width: calc(100vw - 450px)">
                         <el-table :data="privilegeOptions">
                             <el-table-column prop="name" label="可选特权" width="150"></el-table-column>
@@ -106,9 +109,6 @@
                             </el-table-column>
                         </el-table>
                     </el-form-item>
-                    <el-form-item>
-                        <el-button size="mini" @click="addProperty" :disabled="!canEdit"> 添加特性 </el-button>
-                    </el-form-item>
                     <!-- <el-form-item prop="type" label="类型">
                         <el-select v-model="formData.type" clearable filterable placeholder="请选择">
                             <el-option

+ 3 - 0
src/test/java/com/izouma/nineth/CommonTest.java

@@ -1,5 +1,8 @@
 package com.izouma.nineth;
 
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.model.SetBucketCORSRequest;
 import com.github.kevinsawicki.http.HttpRequest;
 import com.izouma.nineth.config.Constants;
 import com.izouma.nineth.domain.BaseEntity;