소스 검색

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

panhui 4 년 전
부모
커밋
2b69556fd3
35개의 변경된 파일1026개의 추가작업 그리고 196개의 파일을 삭제
  1. 1 0
      src/main/java/com/izouma/nineth/security/WebSecurityConfig.java
  2. 7 7
      src/main/java/com/izouma/nineth/service/OrderService.java
  3. 6 1
      src/main/java/com/izouma/nineth/service/UserService.java
  4. 25 1
      src/main/java/com/izouma/nineth/web/OrderNotifyController.java
  5. 2 2
      src/main/java/com/izouma/nineth/web/OrderPayController.java
  6. 7 0
      src/main/java/com/izouma/nineth/web/UserController.java
  7. 3 0
      src/main/nine-space/.eslintrc.js
  8. 1 0
      src/main/nine-space/package.json
  9. 6 0
      src/main/nine-space/public/index.html
  10. 8 0
      src/main/nine-space/src/main.js
  11. 22 1
      src/main/nine-space/src/router/index.js
  12. 1 1
      src/main/nine-space/src/views/Discover.vue
  13. 46 15
      src/main/nine-space/src/views/Submit.vue
  14. 25 0
      src/main/nine-space/yarn.lock
  15. 1 1
      src/main/pc-space/src/App.vue
  16. BIN
      src/main/pc-space/src/assets/img/888.jpg
  17. BIN
      src/main/pc-space/src/assets/img/copy_icon@3x.png
  18. BIN
      src/main/pc-space/src/assets/img/icon-dianzan@3x (1).png
  19. BIN
      src/main/pc-space/src/assets/img/icon-dianzan@3x.png
  20. BIN
      src/main/pc-space/src/assets/img/icon_inter@3x (3).png
  21. BIN
      src/main/pc-space/src/assets/img/icon_inter@3x.png
  22. BIN
      src/main/pc-space/src/assets/img/icon_jiage@3x.png
  23. BIN
      src/main/pc-space/src/assets/img/nav_logo@3x.png
  24. BIN
      src/main/pc-space/src/assets/img/renzheng_icon@3x.png
  25. BIN
      src/main/pc-space/src/assets/img/蒙版@3x.png
  26. 91 18
      src/main/pc-space/src/components/PageHeader.vue
  27. 154 0
      src/main/pc-space/src/components/goodsInfo.vue
  28. 2 2
      src/main/pc-space/src/main.js
  29. 5 55
      src/main/pc-space/src/styles/app.less
  30. 201 1
      src/main/pc-space/src/views/Casting.vue
  31. 298 8
      src/main/pc-space/src/views/Home.vue
  32. 108 77
      src/main/pc-space/src/views/Index.vue
  33. 2 2
      src/main/resources/templates/WeixinPayHtml.ftlh
  34. 1 1
      src/main/vue/src/views/BlindBoxEdit.vue
  35. 3 3
      src/main/vue/src/views/UserEdit.vue

+ 1 - 0
src/main/java/com/izouma/nineth/security/WebSecurityConfig.java

@@ -88,6 +88,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/user/forgotPassword").permitAll()
                 .antMatchers("/user/forgotPassword").permitAll()
                 .antMatchers("/sysConfig/get/*").permitAll()
                 .antMatchers("/sysConfig/get/*").permitAll()
                 .antMatchers("/sysConfig/getDecimal/*").permitAll()
                 .antMatchers("/sysConfig/getDecimal/*").permitAll()
+                .antMatchers("/user/code2openId").permitAll()
                 // all other requests need to be authenticated
                 // all other requests need to be authenticated
                 .anyRequest().authenticated().and()
                 .anyRequest().authenticated().and()
                 // make sure we use stateless session; session won't be used to
                 // make sure we use stateless session; session won't be used to

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

@@ -193,7 +193,7 @@ public class OrderService {
         return result.getMwebUrl() + "&redirect_url=" + new URLCodec().encode(wxPayProperties.getReturnUrl());
         return result.getMwebUrl() + "&redirect_url=" + new URLCodec().encode(wxPayProperties.getReturnUrl());
     }
     }
 
 
-    public Object payOrderWeixin(Long id) throws WxPayException {
+    public Object payOrderWeixin(Long id, String openId) throws WxPayException {
         Order order = orderRepo.findByIdAndDelFalse(id).orElseThrow(new BusinessException("订单不存在"));
         Order order = orderRepo.findByIdAndDelFalse(id).orElseThrow(new BusinessException("订单不存在"));
         if (order.getStatus() != OrderStatus.NOT_PAID) {
         if (order.getStatus() != OrderStatus.NOT_PAID) {
             throw new BusinessException("订单状态错误");
             throw new BusinessException("订单状态错误");
@@ -210,7 +210,7 @@ public class OrderService {
         request.setSpbillCreateIp("180.102.110.170");
         request.setSpbillCreateIp("180.102.110.170");
         request.setNotifyUrl(wxPayProperties.getNotifyUrl());
         request.setNotifyUrl(wxPayProperties.getNotifyUrl());
         request.setTradeType(WxPayConstants.TradeType.JSAPI);
         request.setTradeType(WxPayConstants.TradeType.JSAPI);
-        request.setOpenid(SecurityUtils.getAuthenticatedUser().getOpenId());
+        request.setOpenid(openId);
         request.setSignType("MD5");
         request.setSignType("MD5");
         JSONObject body = new JSONObject();
         JSONObject body = new JSONObject();
         body.put("action", "payOrder");
         body.put("action", "payOrder");
@@ -221,7 +221,7 @@ public class OrderService {
         return wxPayService.<WxPayMpOrderResult>createOrder(request);
         return wxPayService.<WxPayMpOrderResult>createOrder(request);
     }
     }
 
 
-    public void notifyAlipay(Long orderId, Map<String, String> params) {
+    public void notifyAlipay(Long orderId, PayMethod payMethod, String transactionId) {
         Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
         Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
         if (order.getStatus() == OrderStatus.NOT_PAID) {
         if (order.getStatus() == OrderStatus.NOT_PAID) {
             if (order.getType() == CollectionType.BLIND_BOX) {
             if (order.getType() == CollectionType.BLIND_BOX) {
@@ -278,8 +278,8 @@ public class OrderService {
 
 
                 order.setStatus(OrderStatus.PROCESSING);
                 order.setStatus(OrderStatus.PROCESSING);
                 order.setPayTime(LocalDateTime.now());
                 order.setPayTime(LocalDateTime.now());
-                order.setTransactionId(MapUtils.getString(params, "trade_no"));
-                order.setPayMethod(PayMethod.ALIPAY);
+                order.setTransactionId(transactionId);
+                order.setPayMethod(payMethod);
                 orderRepo.save(order);
                 orderRepo.save(order);
                 assetService.createAsset(order, winItem);
                 assetService.createAsset(order, winItem);
 
 
@@ -287,8 +287,8 @@ public class OrderService {
             } else {
             } else {
                 order.setStatus(OrderStatus.PROCESSING);
                 order.setStatus(OrderStatus.PROCESSING);
                 order.setPayTime(LocalDateTime.now());
                 order.setPayTime(LocalDateTime.now());
-                order.setTransactionId(MapUtils.getString(params, "trade_no"));
-                order.setPayMethod(PayMethod.ALIPAY);
+                order.setTransactionId(transactionId);
+                order.setPayMethod(payMethod);
                 orderRepo.save(order);
                 orderRepo.save(order);
                 assetService.createAsset(order);
                 assetService.createAsset(order);
             }
             }

+ 6 - 1
src/main/java/com/izouma/nineth/service/UserService.java

@@ -154,7 +154,7 @@ public class UserService {
             throw new BusinessException("账号或密码错误");
             throw new BusinessException("账号或密码错误");
         }
         }
         if (StringUtils.isNoneEmpty(user.getPassword()) &&
         if (StringUtils.isNoneEmpty(user.getPassword()) &&
-                new BCryptPasswordEncoder().matches(password, user.getPassword())) {
+                !new BCryptPasswordEncoder().matches(password, user.getPassword())) {
             throw new BusinessException("账号或密码错误");
             throw new BusinessException("账号或密码错误");
         }
         }
 
 
@@ -185,6 +185,11 @@ public class UserService {
         return user;
         return user;
     }
     }
 
 
+    public String code2openId(String code) throws WxErrorException {
+        WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
+        return wxMpService.oauth2getUserInfo(accessToken, null).getOpenId();
+    }
+
     public User loginMa(String code) {
     public User loginMa(String code) {
         try {
         try {
             WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(code);
             WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(code);

+ 25 - 1
src/main/java/com/izouma/nineth/web/OrderNotifyController.java

@@ -4,13 +4,19 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.internal.util.AlipaySignature;
 import com.alipay.api.internal.util.AlipaySignature;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
 import com.izouma.nineth.config.AlipayProperties;
 import com.izouma.nineth.config.AlipayProperties;
+import com.izouma.nineth.enums.PayMethod;
 import com.izouma.nineth.service.OrderService;
 import com.izouma.nineth.service.OrderService;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.collections.MapUtils;
 import org.springframework.stereotype.Controller;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 
@@ -29,6 +35,7 @@ public class OrderNotifyController {
 
 
     private final AlipayProperties alipayProperties;
     private final AlipayProperties alipayProperties;
     private final OrderService     orderService;
     private final OrderService     orderService;
+    private final WxPayService     wxPayService;
 
 
     @PostMapping("/order/alipay")
     @PostMapping("/order/alipay")
     @ResponseBody
     @ResponseBody
@@ -60,11 +67,28 @@ public class OrderNotifyController {
             switch (action) {
             switch (action) {
                 case "payOrder":
                 case "payOrder":
                     Long orderId = body.getLong("orderId");
                     Long orderId = body.getLong("orderId");
-                    orderService.notifyAlipay(orderId, params);
+                    orderService.notifyAlipay(orderId, PayMethod.ALIPAY, MapUtils.getString(params, "trade_no"));
                     break;
                     break;
             }
             }
             return "success";
             return "success";
         }
         }
         return "error";
         return "error";
     }
     }
+
+    @PostMapping(value = "/order/weixin", produces = "application/xml")
+    @ResponseBody
+    public String wxNotify(@RequestBody String xmlData) throws WxPayException {
+        log.info("微信支付回调: {}", xmlData);
+        final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
+        notifyResult.checkResult(wxPayService, "MD5", true);
+        JSONObject attach = JSONObject.parseObject(notifyResult.getAttach());
+        String action = attach.getString("action");
+        switch (action) {
+            case "payOrder":
+                Long orderId = attach.getLong("orderId");
+                orderService.notifyAlipay(orderId, PayMethod.WEIXIN, notifyResult.getTransactionId());
+                break;
+        }
+        return WxPayNotifyResponse.success("OK");
+    }
 }
 }

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

@@ -46,7 +46,7 @@ public class OrderPayController {
 
 
     @RequestMapping(value = "/weixin")
     @RequestMapping(value = "/weixin")
     @ResponseBody
     @ResponseBody
-    public Object payOrderWeixin(@RequestParam Long id) throws WxPayException {
-        return orderService.payOrderWeixin(id);
+    public Object payOrderWeixin(@RequestParam Long id, @RequestParam String openId) throws WxPayException {
+        return orderService.payOrderWeixin(id, openId);
     }
     }
 }
 }

+ 7 - 0
src/main/java/com/izouma/nineth/web/UserController.java

@@ -17,6 +17,7 @@ import com.izouma.nineth.utils.SecurityUtils;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
+import me.chanjar.weixin.common.error.WxErrorException;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -114,6 +115,12 @@ public class UserController extends BaseController {
         throw new BusinessException("获取用户信息失败");
         throw new BusinessException("获取用户信息失败");
     }
     }
 
 
+    @PostMapping("/code2openId")
+    @ApiOperation(value = "获取OpenId")
+    public String code2openId(@RequestParam String code) throws WxErrorException {
+        return userService.code2openId(code);
+    }
+
     @PreAuthorize("hasRole('ADMIN')")
     @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/setPasswordAdmin")
     @PostMapping("/setPasswordAdmin")
     public String setPasswordAdmin(@RequestParam Long userId, @RequestParam String password) {
     public String setPasswordAdmin(@RequestParam Long userId, @RequestParam String password) {

+ 3 - 0
src/main/nine-space/.eslintrc.js

@@ -14,5 +14,8 @@ module.exports = {
         'no-empty': ['error', { allowEmptyCatch: true }],
         'no-empty': ['error', { allowEmptyCatch: true }],
         'vue/custom-event-name-casing': 0,
         'vue/custom-event-name-casing': 0,
         'vue/no-parsing-error': ['error']
         'vue/no-parsing-error': ['error']
+    },
+    globals: {
+        wx: true
     }
     }
 };
 };

+ 1 - 0
src/main/nine-space/package.json

@@ -19,6 +19,7 @@
     "lodash": "^4.17.21",
     "lodash": "^4.17.21",
     "mathjs": "^9.5.1",
     "mathjs": "^9.5.1",
     "qrcode": "^1.4.4",
     "qrcode": "^1.4.4",
+    "query-string": "^7.0.1",
     "register-service-worker": "^1.7.1",
     "register-service-worker": "^1.7.1",
     "swiper": "^6.8.1",
     "swiper": "^6.8.1",
     "vant": "^3.2.3",
     "vant": "^3.2.3",

+ 6 - 0
src/main/nine-space/public/index.html

@@ -12,6 +12,7 @@
         <meta name="full-screen" content="yes" />
         <meta name="full-screen" content="yes" />
         <meta name="x5-fullscreen" content="true" />
         <meta name="x5-fullscreen" content="true" />
         <meta name="theme-color" content="#000000" />
         <meta name="theme-color" content="#000000" />
+        <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
         <title>第九空间</title>
         <title>第九空间</title>
     </head>
     </head>
     <body>
     <body>
@@ -24,4 +25,9 @@
         <div id="app"></div>
         <div id="app"></div>
         <!-- built files will be auto injected -->
         <!-- built files will be auto injected -->
     </body>
     </body>
+    <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
+<script>
+  // VConsole will be exported to `window.VConsole` by default.
+  var vConsole = new window.VConsole();
+</script>
 </html>
 </html>

+ 8 - 0
src/main/nine-space/src/main.js

@@ -14,6 +14,7 @@ import LikeButton from './components/LikeButton.vue';
 import Driver from './components/Driver.vue';
 import Driver from './components/Driver.vue';
 import common from './mixins/common';
 import common from './mixins/common';
 import VueClipboard from 'vue-clipboard2';
 import VueClipboard from 'vue-clipboard2';
+import queryString from 'query-string';
 // import VConsole from 'vconsole';
 // import VConsole from 'vconsole';
 // const vConsole = new VConsole();
 // const vConsole = new VConsole();
 
 
@@ -29,3 +30,10 @@ createApp(App)
     .use(store)
     .use(store)
     .use(router)
     .use(router)
     .mount('#app');
     .mount('#app');
+
+let query = queryString.parse(location.search);
+if (query.code) {
+    http.http.post('/user/code2openId', { code: query.code }).then(res => {
+        localStorage.setItem('openId', res);
+    });
+}

+ 22 - 1
src/main/nine-space/src/router/index.js

@@ -2,7 +2,26 @@ import { createRouter, createWebHistory } from 'vue-router';
 import store from '../store';
 import store from '../store';
 import { Page } from './Page';
 import { Page } from './Page';
 import { Dialog } from 'vant';
 import { Dialog } from 'vant';
+import http from '../plugins/http';
 
 
+console.log(http);
+function jsapiSign() {
+    http.http
+        .get('/wx/jsapiSign', { url: location.origin + location.pathname })
+        .then(res => {
+            res.debug = false;
+            res.jsApiList = [
+                'chooseWXPay',
+                'updateAppMessageShareData',
+                'updateTimelineShareData',
+                'hideAllNonBaseMenuItem',
+                'scanQRCode'
+            ];
+            wx.config(res);
+        })
+        .catch(e => {});
+}
+jsapiSign();
 const routes = [
 const routes = [
     {
     {
         path: '/',
         path: '/',
@@ -343,5 +362,7 @@ router.beforeEach((to, from, next) => {
         next();
         next();
     }
     }
 });
 });
-
+router.afterEach((to, from) => {
+    jsapiSign();
+});
 export default router;
 export default router;

+ 1 - 1
src/main/nine-space/src/views/Discover.vue

@@ -205,7 +205,7 @@ export default {
     background-color: @bg3;
     background-color: @bg3;
 }
 }
 
 
-/deep/ .mySwiper {
+::v-deep(.mySwiper) {
     width: calc(100vw - 32px);
     width: calc(100vw - 32px);
     height: calc(41vw - 13px);
     height: calc(41vw - 13px);
     padding-top: 12px;
     padding-top: 12px;

+ 46 - 15
src/main/nine-space/src/views/Submit.vue

@@ -149,24 +149,55 @@ export default {
     },
     },
     methods: {
     methods: {
         submit() {
         submit() {
-            if (this.payType === 'ALIPAY') {
-                this.$http
-                    .post('/order/create?collectionId=' + this.$route.query.id + '&qty=1')
-                    .then(res => {
-                        this.orderId = res.id;
-                        this.$router.replace('/submit?orderId=' + res.id);
-                        this.$nextTick(() => {
+            this.$toast.loading('加载中');
+            this.$http
+                .post('/order/create?collectionId=' + this.$route.query.id + '&qty=1')
+                .then(res => {
+                    this.$toast.clear();
+                    this.orderId = res.id;
+                    this.$router.replace('/submit?orderId=' + res.id);
+                    this.$nextTick(() => {
+                        if (this.payType === 'ALIPAY') {
                             document.location.replace(path.resolve(this.$baseUrl, 'payOrder/alipay?id=' + res.id));
                             document.location.replace(path.resolve(this.$baseUrl, 'payOrder/alipay?id=' + res.id));
-                        });
-                    })
-                    .catch(e => {
-                        if (e) {
-                            this.$toast(e.error);
+                        } else if (this.payType === 'WEIXIN') {
+                            if (/MicroMessenger/i.test(navigator.userAgent)) {
+                                this.$toast.loading('加载中');
+                                this.$http
+                                    .post('/payOrder/weixin', { id: res.id, openId: localStorage.getItem('openId') })
+                                    .then(res => {
+                                        console.log({
+                                            ...res,
+                                            package: res.package || res.packageValue
+                                        });
+                                        wx.chooseWXPay({
+                                            ...res,
+                                            package: res.package || res.packageValue,
+                                            timestamp: res.timeStamp,
+                                            success: function (res) {
+                                                this.$toast.success('支付成功');
+                                                setTimeout(() => {
+                                                    this.$router.replace('/orders');
+                                                }, 1000);
+                                            },
+                                            fail(e) {
+                                                console.log(e);
+                                                this.$toast('支付失败,请稍后再试');
+                                            }
+                                        });
+                                    });
+                            } else {
+                                document.location.replace(
+                                    path.resolve(this.$baseUrl, 'payOrder/weixin_h5?id=' + res.id)
+                                );
+                            }
                         }
                         }
                     });
                     });
-            } else {
-                this.wait();
-            }
+                })
+                .catch(e => {
+                    if (e) {
+                        this.$toast(e.error);
+                    }
+                });
         }
         }
     }
     }
 };
 };

+ 25 - 0
src/main/nine-space/yarn.lock

@@ -4293,6 +4293,11 @@ fill-range@^7.0.1:
   dependencies:
   dependencies:
     to-regex-range "^5.0.1"
     to-regex-range "^5.0.1"
 
 
+filter-obj@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
+  integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs=
+
 finalhandler@~1.1.2:
 finalhandler@~1.1.2:
   version "1.1.2"
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
   resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
@@ -7379,6 +7384,16 @@ query-string@^4.1.0:
     object-assign "^4.1.0"
     object-assign "^4.1.0"
     strict-uri-encode "^1.0.0"
     strict-uri-encode "^1.0.0"
 
 
+query-string@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.0.1.tgz#45bd149cf586aaa582dffc7ec7a8ad97dd02f75d"
+  integrity sha512-uIw3iRvHnk9to1blJCG3BTc+Ro56CBowJXKmNNAm3RulvPBzWLRqKSiiDk+IplJhsydwtuNMHi8UGQFcCLVfkA==
+  dependencies:
+    decode-uri-component "^0.2.0"
+    filter-obj "^1.1.0"
+    split-on-first "^1.0.0"
+    strict-uri-encode "^2.0.0"
+
 querystring-es3@^0.2.0:
 querystring-es3@^0.2.0:
   version "0.2.1"
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
   resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@@ -8138,6 +8153,11 @@ spdy@^4.0.2:
     select-hose "^2.0.0"
     select-hose "^2.0.0"
     spdy-transport "^3.0.0"
     spdy-transport "^3.0.0"
 
 
+split-on-first@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+  integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
 split-string@^3.0.1, split-string@^3.0.2:
 split-string@^3.0.1, split-string@^3.0.2:
   version "3.1.0"
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
   resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
@@ -8244,6 +8264,11 @@ strict-uri-encode@^1.0.0:
   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
   integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
   integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
 
 
+strict-uri-encode@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+  integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
+
 string-width@^2.0.0:
 string-width@^2.0.0:
   version "2.1.1"
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"

+ 1 - 1
src/main/pc-space/src/App.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
     <div id="app">
     <div id="app">
-        <router-view style="min-width: 1200px" />
+        <router-view />
     </div>
     </div>
 </template>
 </template>

BIN
src/main/pc-space/src/assets/img/888.jpg


BIN
src/main/pc-space/src/assets/img/copy_icon@3x.png


BIN
src/main/pc-space/src/assets/img/icon-dianzan@3x (1).png


BIN
src/main/pc-space/src/assets/img/icon-dianzan@3x.png


BIN
src/main/pc-space/src/assets/img/icon_inter@3x (3).png


BIN
src/main/pc-space/src/assets/img/icon_inter@3x.png


BIN
src/main/pc-space/src/assets/img/icon_jiage@3x.png


BIN
src/main/pc-space/src/assets/img/nav_logo@3x.png


BIN
src/main/pc-space/src/assets/img/renzheng_icon@3x.png


BIN
src/main/pc-space/src/assets/img/蒙版@3x.png


+ 91 - 18
src/main/pc-space/src/components/PageHeader.vue

@@ -1,32 +1,105 @@
 <template>
 <template>
     <div class="container">
     <div class="container">
-        <div class="header"></div>
-        <div class="center-item">
-            <router-link to="/Home" class="link">我的</router-link>
-            <router-link to="/casting" class="link">铸造</router-link>
+        <div class="header">
+            <img class="logo" src="../assets/img/nav_logo@3x.png" alt="" />
+            <div class="content">
+                <div class="tabs">
+                    <div
+                        class="tab"
+                        :class="{ active: active === item }"
+                        v-for="(item, index) in tabs"
+                        :key="index"
+                        @click="tab(item)"
+                    >
+                        {{ item }}
+                        <div class="slip" :class="{ active: item === active }"></div>
+                    </div>
+                </div>
+                <div class="login">[登录]</div>
+                <div class="login login1">中文</div>
+            </div>
         </div>
         </div>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
-export default {};
+export default {
+    data() {
+        return {
+            tabs: ['铸造者', '收藏探索', '数字盲盒', '我的NFT', '了解更多'],
+            active: ''
+        };
+    },
+    methods: {
+        tab(item) {
+            this.active = item;
+            if (item === '铸造者') {
+                this.$router.push('/casting');
+            }
+        }
+    }
+};
 </script>
 </script>
 <style lang="less" scoped>
 <style lang="less" scoped>
 .container {
 .container {
-    background: #000;
+    height: 90px;
+    background: #0f1111;
     .header {
     .header {
-        background: #fff;
-    }
-    .center-item {
-        padding: 0 80px;
-        .link {
-            &:first-child {
-                font-size: 12px;
-                color: #ffffff;
-                line-height: 17px;
-            }
+        display: flex;
+        align-items: center;
+        .logo {
+            width: 170px;
+            height: 60px;
+            padding: 15px 538px 15px 30px;
         }
         }
-        &:not(:last-child) {
-            border-right: 1px solid #acacac;
+        .content {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .tabs {
+                display: flex;
+                align-items: center;
+                padding-top: 10px;
+                cursor: pointer;
+                .tab {
+                    width: 130px;
+                    font-size: 18px;
+                    font-weight: bold;
+                    text-align: center;
+                    color: #939599;
+                    line-height: 28px;
+                    &.active {
+                        color: #ffffff;
+                        font-weight: bold;
+                    }
+                    .slip {
+                        width: 26px;
+                        margin: 0 auto;
+                        padding-bottom: 13px;
+                        &.active {
+                            border-bottom: 2px solid #fff;
+                            border-radius: 2px;
+                        }
+                    }
+                }
+            }
+            .login {
+                width: 83px;
+                height: 30px;
+                border-radius: 4px;
+                border: 1px solid;
+                border-image: linear-gradient(135deg, rgba(0, 255, 203, 1), rgba(0, 110, 255, 1)) 1 1;
+                line-height: 30px;
+                text-align: center;
+                color: #00ffcb;
+                font-size: 16px;
+                margin: 0 30px 0 30px;
+                .login1 {
+                    border: 1px solid #939599;
+                    color: #939599;
+                    border-image: linear-gradient(0);
+                    margin: 0;
+                }
+            }
         }
         }
     }
     }
 }
 }

+ 154 - 0
src/main/pc-space/src/components/goodsInfo.vue

@@ -0,0 +1,154 @@
+<template>
+    <div>
+        <div class="box">
+            <div class="content" v-for="(item, index) in list" :key="index">
+                <img class="imgBox" src="../assets/img/888.jpg" alt="" />
+                <div class="introduce">{{ item.name }}</div>
+                <div class="price">
+                    <img class="img1" src="../assets/img/icon_jiage@3x.png" alt="" />
+                    <div class="num">{{ item.price }}</div>
+                </div>
+                <div class="border"></div>
+                <div class="fans">
+                    <div class="text">
+                        <div class="text1 name1">
+                            <img class="text2" src="../assets/img/888.jpg" alt="" />
+                            <div class="text3">铸造者</div>
+                        </div>
+                        <div class="text1">
+                            <img class="text2" src="../assets/img/888.jpg" alt="" />
+                            <div class="text3">持有者</div>
+                        </div>
+                    </div>
+                    <div class="text">
+                        <div class="text1">
+                            <img class="text2 text4" src="../assets/img/icon-dianzan@3x.png" alt="" />
+                            <div class="text3">16</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="all">
+            <img class="img1" src="../assets/img/icon_inter@3x.png" alt="" />
+            <div class="name">查看更多</div>
+            <img class="img1" src="../assets/img/icon_inter@3x (3).png" alt="" />
+        </div>
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            list: [
+                { name: '游戏《百分之一》精美皮肤-恶…', price: '320' },
+                { name: '游戏《百分之一》精美皮肤-恶…', price: '320' },
+                { name: '游戏《百分之一》精美皮肤-恶…', price: '320' },
+                { name: '游戏《百分之一》精美皮肤-恶…', price: '320' }
+            ]
+        };
+    }
+};
+</script>
+<style lang="less" scoped>
+.box {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding-left: 10px;
+    .content {
+        width: 276px;
+        height: 416px;
+        background: #1c1e26;
+        margin-bottom: 32px;
+
+        border: 1px solid;
+        margin-right: 32px;
+        border-image: linear-gradient(135deg, rgba(0, 255, 203, 1), rgba(0, 110, 255, 1)) 1 1;
+        .imgBox {
+            height: 266px;
+            width: 100%;
+            // border-radius: 8px 8px 0px 0px;
+        }
+        .introduce {
+            padding: 10px 16px 6px;
+            font-size: 14px;
+            font-weight: 400;
+            color: #939599;
+            line-height: 20px;
+        }
+        .price {
+            display: flex;
+            align-items: center;
+            padding: 0 0 16px 16px;
+            .img1 {
+                width: 10px;
+                height: 11px;
+                margin-top: 10px;
+            }
+            .num {
+                font-size: 30px;
+                font-family: OSP-DIN, OSP;
+                font-weight: normal;
+                color: #00ffcb;
+                line-height: 30px;
+            }
+        }
+        .border {
+            height: 1px;
+            background: #494a4d;
+            border-radius: 1px;
+            margin: 0 16px;
+        }
+        .fans {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding: 19px 16px 20px;
+            .text {
+                display: flex;
+                align-items: center;
+                .text1 {
+                    display: flex;
+                    align-items: center;
+                    &.name1 {
+                        margin-right: 22px;
+                    }
+                    .text2 {
+                        width: 20px;
+                        height: 20px;
+                        border-radius: 50%;
+                        margin-right: 4px;
+                        &.text4 {
+                            width: 18px;
+                            height: 18px;
+                        }
+                    }
+                    .text3 {
+                        font-size: 14px;
+                        font-weight: 400;
+                        color: #939599;
+                        line-height: 24px;
+                    }
+                }
+            }
+        }
+    }
+}
+.all {
+    display: flex;
+    align-content: center;
+    justify-content: center;
+    .img1 {
+        width: 32px;
+        height: 24px;
+    }
+    .name {
+        font-size: 16px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        margin: 0 10px;
+    }
+}
+</style>

+ 2 - 2
src/main/pc-space/src/main.js

@@ -6,8 +6,8 @@ import http from './plugins/http';
 import ElementUI from 'element-ui';
 import ElementUI from 'element-ui';
 ElementUI.Dialog.props.closeOnClickModal.default = false;
 ElementUI.Dialog.props.closeOnClickModal.default = false;
 import './styles/common.less';
 import './styles/common.less';
-import './styles/font.less';
-// import './styles/app.less';
+// import './styles/font.less';
+import './styles/app.less';
 
 
 Vue.prototype.$colors = {
 Vue.prototype.$colors = {
     prim: '#FF7F1F',
     prim: '#FF7F1F',

+ 5 - 55
src/main/pc-space/src/styles/app.less

@@ -15,9 +15,6 @@ a {
     }
     }
 }
 }
 
 
-.el-dialog__wrapper {
-    // z-index: 200000 !important;
-}
 
 
 .hideSelect.el-select-dropdown {
 .hideSelect.el-select-dropdown {
     border-width: 0px;
     border-width: 0px;
@@ -26,7 +23,7 @@ a {
 }
 }
 
 
 .center-content {
 .center-content {
-    .center-content();
+    // .center-content();
 }
 }
 
 
 .el-dialog {
 .el-dialog {
@@ -34,7 +31,8 @@ a {
     border-radius: 8px !important;
     border-radius: 8px !important;
 
 
     .btns {
     .btns {
-        .flex();
+        display: flex;
+        align-items: center;
         justify-content: flex-end;
         justify-content: flex-end;
         .el-button {
         .el-button {
             min-width: 100px;
             min-width: 100px;
@@ -46,7 +44,8 @@ a {
 
 
 .el-dialog {
 .el-dialog {
     max-height: 70vh;
     max-height: 70vh;
-    .flex-col();
+    display: flex;
+    flex-direction: column;
     .el-dialog__header {
     .el-dialog__header {
         flex-shrink: 0;
         flex-shrink: 0;
     }
     }
@@ -161,38 +160,6 @@ body {
     }
     }
 }
 }
 
 
-.search {
-    .el-input__suffix-inner {
-        display: flex;
-        flex-direction: row-reverse;
-
-        .el-icon-search {
-            color: #c0c4cc;
-            font-size: 14;
-            cursor: pointer;
-            transition: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
-
-            &:hover {
-                color: #909399;
-            }
-        }
-    }
-
-    .el-input-group__append,
-    .el-input-group__prepend {
-        background-color: @warn;
-        padding: 0 10px;
-        color: #fff;
-        border-color: @warn;
-    }
-
-    &.el-input-group--append {
-        .el-input__inner {
-            border-color: @warn;
-            background-color: transparent;
-        }
-    }
-}
 
 
 .btn-block {
 .btn-block {
     display: block;
     display: block;
@@ -203,23 +170,6 @@ body {
     margin-top: 20px;
     margin-top: 20px;
 }
 }
 
 
-.el-dialog__title {
-    font-weight: bold;
-    // font-size: 16px !important;
-}
-
-.swiper-pagination-bullet {
-    background-color: rgba(0, 0, 0, 0.6);
-}
-.swiper-pagination-bullet-active {
-    background-color: @prim;
-}
-.animate__animated.animate__bounce {
-    --animate-duration: 2s;
-}
-:root {
-    --swiper-theme-color: @prim;
-}
 /* This changes all the animations globally */
 /* This changes all the animations globally */
 // :root {
 // :root {
 //     --animate-duration: 800ms;
 //     --animate-duration: 800ms;

+ 201 - 1
src/main/pc-space/src/views/Casting.vue

@@ -1,3 +1,203 @@
 <template>
 <template>
-    <div>铸造</div>
+    <div class="container">
+        <div class="title">游戏数字资产的链上开创者们</div>
+        <div class="tabs">
+            <div
+                class="tab"
+                :class="{ active: active === item }"
+                v-for="(item, index) in tabs"
+                :key="index"
+                @click="tab(item)"
+            >
+                {{ item }}
+            </div>
+        </div>
+        <div class="border"></div>
+        <el-input placeholder="请输入内容" v-model="input" clearable> </el-input>
+        <div class="content">
+            <img class="imgBox" src="../assets/img/888.jpg" alt="" />
+            <img class="img" src="../assets/img/888.jpg" alt="" />
+            <div class="text">
+                <div class="name">创作者姓名</div>
+                <img class="img1" src="../assets/img/renzheng_icon@3x.png" alt="" />
+            </div>
+            <div class="text">
+                <div class="name name1">338392</div>
+                <img class="img1 img2" src="../assets/img/copy_icon@3x.png" alt="" />
+            </div>
+            <div class="introduce">
+                介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍...
+            </div>
+            <div class="border"></div>
+            <div class="fans">
+                <div>
+                    <div class="text3">2111</div>
+                    <div class="text4">粉丝</div>
+                </div>
+                <div class="follow">关注</div>
+            </div>
+        </div>
+    </div>
 </template>
 </template>
+<script>
+export default {
+    data() {
+        return {
+            tabs: ['全部', '最新', '人气', '关注'],
+            active: '全部',
+            input: ''
+        };
+    },
+    methods: {
+        tab(item) {
+            this.active = item;
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.container {
+    background: #0f1111;
+    padding-left: 200px;
+    padding-bottom: 100px;
+    /deep/ .el-input__inner {
+        background: #0f1111;
+        width: 280px;
+        height: 42px;
+        color: #fff;
+        border-radius: 8px;
+        border: 1px solid #898989;
+        margin: 30px 0 50px;
+    }
+    .title {
+        height: 42px;
+        font-size: 32px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 42px;
+        padding: 60px 0;
+        text-align: left;
+    }
+    .tabs {
+        display: flex;
+        align-items: center;
+        padding-bottom: 30px;
+        text-align: center;
+        .tab {
+            width: 140px;
+            border: 1px solid #939599;
+            height: 42px;
+            font-size: 18px;
+            font-weight: bold;
+            color: #949699;
+            line-height: 42px;
+            &.active {
+                color: #ffffff;
+                background: linear-gradient(46deg, #00ffcb 0%, #006eff 100%);
+            }
+            &:first-child {
+                border-radius: 8px 0px 0px 8px;
+            }
+            &:last-child {
+                border-radius: 0px 8px 8px 0px;
+            }
+        }
+    }
+    .border {
+        height: 1px;
+        background: #494a4d;
+        border-radius: 1px;
+    }
+    .content {
+        width: 276px;
+        height: 416px;
+        background: #1c1e26;
+
+        margin-bottom: 32px;
+        border: 1px solid;
+        border-image: linear-gradient(135deg, rgba(0, 255, 203, 1), rgba(0, 110, 255, 1)) 1 1;
+        position: relative;
+        .imgBox {
+            height: 160px;
+            width: 100%;
+            // border-radius: 8px 8px 0px 0px;
+        }
+        .img {
+            padding: 5px;
+            width: 88px;
+            height: 88px;
+            background: #ffffff;
+            border-radius: 65px;
+            position: absolute;
+            top: 100px;
+            right: 90px;
+        }
+        .text {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            .name {
+                height: 24px;
+                font-size: 16px;
+                font-weight: bold;
+                color: #ffffff;
+                line-height: 24px;
+                margin-top: 50px;
+                padding-right: 6px;
+                &.name1 {
+                    font-size: 14px;
+                    font-weight: 400;
+                    color: #949699;
+                    line-height: 24px;
+                    margin-top: 0;
+                }
+            }
+            .img1 {
+                width: 18px;
+                height: 18px;
+                margin-top: 50px;
+                &.img2 {
+                    margin-top: 0;
+                }
+            }
+        }
+        .introduce {
+            padding: 10px 16px 16px;
+            height: 60px;
+            font-size: 14px;
+            font-weight: 400;
+            color: #939599;
+            line-height: 20px;
+        }
+        .fans {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding: 10px 16px 20px;
+            .text3 {
+                font-size: 16px;
+                font-weight: 400;
+                color: #ffffff;
+                line-height: 24px;
+            }
+            .text4 {
+                font-size: 14px;
+                font-weight: 400;
+                color: #939599;
+                line-height: 24px;
+            }
+            .follow {
+                width: 70px;
+                height: 26px;
+                color: #00ffcb;
+                font-size: 14px;
+                border-radius: 16px;
+                border: 1px solid;
+                text-align: center;
+                line-height: 26px;
+                border-image: linear-gradient(135deg, rgba(0, 255, 203, 1), rgba(0, 110, 255, 1)) 1 1;
+            }
+        }
+    }
+}
+</style>

+ 298 - 8
src/main/pc-space/src/views/Home.vue

@@ -1,16 +1,306 @@
 <template>
 <template>
-    <div class="container">我的</div>
+    <div>
+        <div class="container">
+            <div class="title">游戏数字资产的链上开创者们</div>
+            <div class="title2">全球领先的游戏数字藏品NFT集结地</div>
+            <div class="btn">立即探索</div>
+        </div>
+        <div class="introduce">
+            <div class="introduce2">
+                <img class="img1" src="../assets/img/888.jpg" alt="" />
+                <div>
+                    <div class="name">本期推荐:创作者姓名</div>
+                    <div class="name name1">作者简介</div>
+                    <div class="name2">
+                        介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍介绍…
+                    </div>
+                </div>
+            </div>
+            <img class="img2" src="../assets/img/888.jpg" alt="" />
+            <img class="img2" src="../assets/img/888.jpg" alt="" />
+            <img class="img2" src="../assets/img/888.jpg" alt="" />
+        </div>
+        <div class="hot">最HOT收藏品</div>
+        <goods-info></goods-info>
+        <div class="hot">官方活动</div>
+        <div class="imgBox">
+            <img class="imgBox1" src="../assets/img/888.jpg" alt="" />
+            <img class="imgBox1" src="../assets/img/888.jpg" alt="" />
+        </div>
+        <div class="all">
+            <img class="img1" src="../assets/img/icon_inter@3x.png" alt="" />
+            <div class="name">查看更多</div>
+            <img class="img1" src="../assets/img/icon_inter@3x (3).png" alt="" />
+        </div>
+        <!-- <div> -->
+        <div class="describe">
+            <div class="box">
+                <div class="box1">
+                    <div class="text1">发现</div>
+                    <div class="text2">和你一起探索,全球最有才华的开发者铸造开创性NFT数字游戏藏品</div>
+                </div>
+            </div>
+            <div class="box">
+                <div class="box1">
+                    <div class="text1">交易</div>
+                    <div class="text2">方便快捷-无需数字钱包,人民币支付即可购买和出售游戏资产收藏品</div>
+                </div>
+            </div>
+        </div>
+        <div class="describe">
+            <div class="box">
+                <div class="box1">
+                    <div class="text1">收集</div>
+                    <div class="text2">用稀有和独特的数字宝藏增加库存,成为全球首批游戏数字资产收藏家</div>
+                </div>
+            </div>
+            <div class="box">
+                <div class="box1">
+                    <div class="text1">使命</div>
+                    <div class="text2">让每个游戏资产都能获得“电子身份证”,让每位收藏家都能获得区块链“数字指纹”</div>
+                </div>
+            </div>
+        </div>
+        <!-- </div> -->
+        <div class="space">为什么叫第九空间</div>
+        <div class="space2">一切数据皆可复制的时代,第九空间NFT让你拥有一份独家数字藏品,让你拥有一份唯一游戏权益</div>
+        <div class="th">
+            <div>
+                <div class="words1">我们始终坚信</div>
+                <div class="words2">未来的虚拟世界将演变成同具价值的数字世界</div>
+            </div>
+            <div class="border"></div>
+            <div>
+                <div class="words1">我们始终坚信</div>
+                <div class="words2">未来的虚拟世界将演变成同具价值的数字世界</div>
+            </div>
+            <div class="border"></div>
+            <div>
+                <div class="words1">我们始终坚信</div>
+                <div class="words2">未来的虚拟世界将演变成同具价值的数字世界</div>
+            </div>
+            <div class="border"></div>
+            <div>
+                <div class="words1">我们始终坚信</div>
+                <div class="all">
+                    <img class="img1" src="../assets/img/icon_inter@3x.png" alt="" />
+                    <div class="name">了解更多</div>
+                    <img class="img1" src="../assets/img/icon_inter@3x (3).png" alt="" />
+                </div>
+            </div>
+        </div>
+    </div>
 </template>
 </template>
 <script>
 <script>
+import goodsInfo from '../components/goodsInfo.vue';
 export default {
 export default {
+    components: { goodsInfo },
     data() {
     data() {
-        return {
-            list: '666'
-        };
+        return {};
     },
     },
-    mounted() {
-        console.log(this.list);
-    }
+    mounted() {}
 };
 };
 </script>
 </script>
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+.container {
+    padding-left: 17.5%;
+    .title {
+        height: 42px;
+        font-size: 32px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 42px;
+        padding: 130px 0 24px 10px;
+        text-align: left;
+    }
+    .title2 {
+        font-size: 30px;
+        font-weight: 400;
+        color: #939599;
+        line-height: 42px;
+        padding-left: 10px;
+    }
+    .btn {
+        width: 136px;
+        height: 44px;
+        line-height: 44px;
+        text-align: center;
+        margin: 50px 0 183px 10px;
+        font-size: 24px;
+        color: #00ffcb;
+        border: 1px solid;
+        border-image: linear-gradient(135deg, rgba(0, 255, 203, 1), rgba(0, 110, 255, 1)) 1 1;
+    }
+}
+.introduce {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    .introduce2 {
+        display: flex;
+        align-items: center;
+        .img1 {
+            width: 180px;
+            height: 180px;
+            border-radius: 8px;
+            margin-right: 16px;
+        }
+        .name {
+            font-size: 16px;
+            font-weight: bold;
+            color: #ffffff;
+            line-height: 24px;
+            &.name1 {
+                margin: 10px 0 4px 0;
+            }
+        }
+        .name2 {
+            font-size: 14px;
+            font-weight: 400;
+            color: #939599;
+            line-height: 20px;
+            width: 254px;
+            height: 100px;
+            overflow: hidden;
+            text-overflow: ellipsis;
+        }
+    }
+    .img2 {
+        width: 220px;
+        height: 180px;
+        border-radius: 8px;
+        margin-left: 30px;
+    }
+}
+.hot {
+    font-size: 24px;
+    width: 100%;
+    text-align: center;
+    font-weight: 400;
+    color: #ffffff;
+    line-height: 34px;
+    margin: 100px 0 50px;
+}
+.imgBox {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    .imgBox1 {
+        width: 585px;
+        height: 260px;
+        border-radius: 8px;
+        margin-right: 30px;
+    }
+}
+.all {
+    display: flex;
+    align-content: center;
+    justify-content: center;
+    margin: 40px 0 60px;
+    .img1 {
+        width: 32px;
+        height: 24px;
+    }
+    .name {
+        font-size: 16px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 24px;
+        margin: 0 10px;
+    }
+}
+.describe {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    .box {
+        width: 580px;
+        height: 114px;
+        background: #0f1111;
+        border-radius: 8px;
+        border: 1px solid;
+        margin-right: 30px;
+        margin-bottom: 30px;
+        border-image: linear-gradient(
+                174deg,
+                rgba(0, 255, 203, 0.6),
+                rgba(0, 209, 220, 0.1),
+                rgba(0, 151, 240, 0.1),
+                rgba(0, 110, 255, 0.5)
+            )
+            1 1;
+        .box1 {
+            margin: 30px 0 0 40px;
+            .text1 {
+                font-size: 18px;
+                font-weight: bold;
+                color: #ffffff;
+                line-height: 24px;
+                margin-bottom: 6px;
+            }
+            .text2 {
+                font-size: 14px;
+                font-weight: 400;
+                color: #939599;
+                line-height: 24px;
+            }
+        }
+    }
+}
+.space {
+    height: 34px;
+    font-size: 24px;
+    text-align: center;
+    margin: 100px 0 8px;
+    font-weight: 400;
+    color: #ffffff;
+    line-height: 34px;
+}
+.space2 {
+    font-size: 16px;
+    font-weight: 400;
+    text-align: center;
+    color: #939599;
+    line-height: 24px;
+    margin-bottom: 60px;
+}
+.th {
+    display: flex;
+    justify-content: center;
+    .border {
+        width: 1px;
+        height: 115px;
+        background: #494a4d;
+        margin: 0 30px 100px;
+    }
+    .words1 {
+        font-size: 18px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 25px;
+        margin: 12px 0;
+    }
+    .words2 {
+        width: 240px;
+        font-size: 16px;
+        font-weight: 400;
+        color: #939599;
+        line-height: 24px;
+    }
+    .all {
+        display: flex;
+        align-content: center;
+        .img1 {
+            width: 32px;
+            height: 24px;
+        }
+        .name {
+            font-size: 16px;
+            font-weight: 400;
+            color: #ffffff;
+            line-height: 24px;
+            margin: 0 10px;
+        }
+    }
+}
+</style>

+ 108 - 77
src/main/pc-space/src/views/Index.vue

@@ -7,7 +7,45 @@
                     <router-view />
                     <router-view />
                 </keep-alive>
                 </keep-alive>
             </el-main>
             </el-main>
-            <el-footer height="246px">Footer</el-footer>
+            <el-footer>
+                <div class="footer">
+                    <div class="footer-l">
+                        <img class="logo" src="../assets/img/nav_logo@3x.png" alt="" />
+                        <div>
+                            <div class="text1">加入创造者生态</div>
+                            <div class="text2">让我们成为一批游戏NFT的弄潮儿</div>
+                            <div class="text2">若您合您的团队想要铸造NFT,请联系:NFT@space.com</div>
+                        </div>
+                    </div>
+                    <div class="footer-r">
+                        <div class="slogan">
+                            <img class="logo1" src="../assets/img/copy_icon@3x.png" alt="" />
+                            <img class="logo1" src="../assets/img/copy_icon@3x.png" alt="" />
+                            <img class="logo1" src="../assets/img/copy_icon@3x.png" alt="" />
+                            <img class="logo1" src="../assets/img/copy_icon@3x.png" alt="" />
+                        </div>
+                        <div class="content">
+                            <div class="content1">
+                                <img class="logo2" src="../assets/img/copy_icon@3x.png" alt="" />
+                                <div class="name">联系我们</div>
+                            </div>
+                            <div class="content1">
+                                <img class="logo2" src="../assets/img/copy_icon@3x.png" alt="" />
+                                <div class="name">联系我们</div>
+                            </div>
+                            <div class="content1">
+                                <img class="logo2" src="../assets/img/copy_icon@3x.png" alt="" />
+                                <div class="name">联系我们</div>
+                            </div>
+                            <div class="content1">
+                                <img class="logo2" src="../assets/img/copy_icon@3x.png" alt="" />
+                                <div class="name">联系我们</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="copyright">© 2012 - 2021 **** 版权所有</div>
+            </el-footer>
         </el-container>
         </el-container>
     </el-container>
     </el-container>
 </template>
 </template>
@@ -19,94 +57,87 @@ export default {
 </script>
 </script>
 <style lang="less" scoped>
 <style lang="less" scoped>
 #app {
 #app {
-    min-height: 100vh;
+    // min-height: 100vh;
+}
+.el-main {
+    min-height: 1000px;
+    background: #0f1111;
+    // padding-left: 200px;
 }
 }
 .el-footer {
 .el-footer {
-    // background-color: @warn;
-    background: #ccc;
-    padding: 0;
     position: relative;
     position: relative;
-    // .flex-col();
-    // display: flex;
-    // flex-direction: column;
-    &::before {
-        content: '';
-        height: 6px;
-        display: block;
-        // background-color: @prim;
-    }
-
-    .footer-content {
-        justify-content: center;
-        // padding-bottom: 55px;
-        padding-top: 42px;
-        // .flex();
-        // .left {
-        //     min-width: 240px;
-        // }
-        .name {
-            font-size: 12px;
-            font-weight: 600;
-            color: #ffffff;
-            line-height: 17px;
-            text-align: center;
+    background: #0f1111;
+    height: 170px !important;
+    .footer {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        height: 170px;
+        line-height: 170px;
+        padding: 0 220px;
+        .footer-l {
+            display: flex;
+            .logo {
+                width: 170px;
+                height: 60px;
+                margin: 9px 30px 0 0;
+            }
+            .text1 {
+                font-size: 18px;
+                font-weight: 400;
+                color: #ffffff;
+                line-height: 25px;
+                margin-bottom: 15px;
+            }
+            .text2 {
+                font-size: 12px;
+                font-weight: 400;
+                color: #939599;
+                line-height: 17px;
+            }
         }
         }
-        .center {
-            width: 438px;
-            // .flex();
-            .center-item {
-                padding: 0 80px;
-                .link {
-                    &:first-child {
+        .footer-r {
+            .slogan {
+                display: flex;
+                align-items: center;
+                justify-content: flex-end;
+                margin-bottom: 40px;
+                .logo1 {
+                    width: 24px;
+                    height: 24px;
+                    margin-left: 40px;
+                }
+            }
+            .content {
+                display: flex;
+                align-items: center;
+                .content1 {
+                    display: flex;
+                    margin-left: 40px;
+                    .logo2 {
+                        width: 16px;
+                        height: 16px;
+                    }
+                    .name {
                         font-size: 12px;
                         font-size: 12px;
+                        font-weight: 400;
                         color: #ffffff;
                         color: #ffffff;
-                        line-height: 17px;
+                        line-height: 16px;
+                        margin-left: 10px;
                     }
                     }
-                    display: block;
-                    font-size: 12px;
-                    color: #acacac;
-                    line-height: 17px;
-                    margin-top: 12px;
-                    cursor: pointer;
-
-                    &:hover {
-                        // color: @prim;
-                        text-decoration: underline;
-                    }
-                }
-
-                &:not(:last-child) {
-                    border-right: 1px solid #acacac;
                 }
                 }
             }
             }
         }
         }
-        position: relative;
     }
     }
 }
 }
-.el-aside {
-    background-color: #d3dce6;
-    color: #333;
-    text-align: center;
-    line-height: 200px;
-}
-
-.el-main {
-    background-color: #e9eef3;
-    color: #333;
+.copyright {
+    width: 100%;
     text-align: center;
     text-align: center;
-    line-height: 160px;
-}
-
-body > .el-container {
-    margin-bottom: 40px;
-}
-
-.el-container:nth-child(5) .el-aside,
-.el-container:nth-child(6) .el-aside {
-    line-height: 260px;
-}
-
-.el-container:nth-child(7) .el-aside {
-    line-height: 320px;
+    background: #0f1111;
+    height: 36px;
+    line-height: 36px;
+    font-size: 12px;
+    font-weight: 400;
+    color: #565b66;
 }
 }
 </style>
 </style>

+ 2 - 2
src/main/resources/templates/WeixinPayHtml.ftlh

@@ -55,9 +55,9 @@
         </#if>
         </#if>
     </div>
     </div>
 </#if>
 </#if>
-<#if !weixin && form??>
+<#if !weixin && payUrl??>
     <script>
     <script>
-        window.location = "${payUrl?no_esc}";
+        document.location.replace("${payUrl?no_esc}");
     </script>
     </script>
 </#if>
 </#if>
 <!-- 引入 Vue 和 Vant 的 JS 文件 -->
 <!-- 引入 Vue 和 Vant 的 JS 文件 -->

+ 1 - 1
src/main/vue/src/views/BlindBoxEdit.vue

@@ -495,7 +495,7 @@ export default {
         }
         }
     },
     },
     watch: {
     watch: {
-        'addItemForm.id'(val) {
+        'addItemForm.collectionId'(val) {
             if (val) {
             if (val) {
                 this.$set(this.addItemForm, 'max', (this.collections.find(i => i.id === val) || {}).stock || 0);
                 this.$set(this.addItemForm, 'max', (this.collections.find(i => i.id === val) || {}).stock || 0);
             }
             }

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

@@ -22,14 +22,14 @@
                     style="max-width: 500px"
                     style="max-width: 500px"
                 >
                 >
                     <el-form-item prop="avatar" label="头像">
                     <el-form-item prop="avatar" label="头像">
-                        <crop-upload v-model="formData.avatar" :disabled="formData.id"></crop-upload>
+                        <crop-upload v-model="formData.avatar" :disabled="!!formData.id"></crop-upload>
                     </el-form-item>
                     </el-form-item>
                     <el-form-item prop="username" label="用户名">
                     <el-form-item prop="username" label="用户名">
-                        <el-input v-model="formData.username" :disabled="formData.id"></el-input>
+                        <el-input v-model="formData.username" :disabled="!!formData.id"></el-input>
                         <div class="gen" @dblclick="gen"></div>
                         <div class="gen" @dblclick="gen"></div>
                     </el-form-item>
                     </el-form-item>
                     <el-form-item prop="nickname" label="昵称">
                     <el-form-item prop="nickname" label="昵称">
-                        <el-input v-model="formData.nickname" :disabled="formData.id"></el-input>
+                        <el-input v-model="formData.nickname" :disabled="!!formData.id"></el-input>
                     </el-form-item>
                     </el-form-item>
                     <el-form-item v-if="formData.id" label="密码">
                     <el-form-item v-if="formData.id" label="密码">
                         <el-button type="primary" plain @click="resetPassword" size="mini">重置 </el-button>
                         <el-button type="primary" plain @click="resetPassword" size="mini">重置 </el-button>