<template> <div class="page"> <template v-if="data === null"> <img class="loading" src="../static/svg/icon-loading.svg" /> </template> <template v-else> <div class="swipe" v-if="curItem"> <div class="show"> <img :src="curItem.imagePath" /> </div> <div class="list"> <div class="item" :class="{ on: curItem.nftItemId === item.nftItemId }" :key="index" @click="select(item)" v-for="(item, index) in listData"> <img :src="item.imagePath" /> </div> </div> </div> <div class="desc line" v-if="nftMetaData.description"> <div class="title">Description</div> <div class="desc-content" v-html="nftMetaData.description"></div> </div> <div class="prop line" v-if="nftMetaData.properties && nftMetaData.properties.length"> <div class="title">Properties</div> <div class="prop-content"> <div class="prop-item" v-for="(filedValueItem, filedValueIndex) in nftMetaData.properties" :key="filedValueIndex"> {{ filedValueItem.name }} <div class="prop-name"> {{ filedValueItem.value }} </div> {{ filedValueItem.description }} </div> </div> </div> <div class="about line" v-if="nftMetaData.about"> <div class="title">About</div> <div class="about-content" v-html="nftMetaData.about"></div> </div> <div style="height: 150px"></div> <div class="buy"> <div class="random"> <img src="../static/img/icon_nft_random.png" /> <span>Randomly Get Different Styles of NFTs</span> </div> <template v-if="data.salePlans.length"> <div v-for="(item, index) in data.salePlans" :key="index"> <template v-if="item.itemCount == 1"> <template v-if="purchaseStatus !== 0"> <div class="btn" :class="{ disable: !(data.perUserBuyLimit - data.userBuyCount >= 1 && data.itemTotalCount - data.itemSoldCount >= 1) }" @click="goBuy(data.perUserBuyLimit - data.userBuyCount >= 1 && data.itemTotalCount - data.itemSoldCount >= 1)"> <div class="l">BUY {{ item.itemCount }}</div> <FontZoom width="210"> <template v-if="item.currencyCode !== 'USD'"> <template v-if="item.price.length + item.currencyInfo.tokenSymbol.length >= 30"> <div class="tr"> <div><img class="icon" :src="item.currencyInfo.iconPath" /> {{ item.price | floatPrice(4) }}</div> <div>{{ item.currencyInfo.tokenSymbol }} (${{ item.usdPrice | floatPrice(2) }})</div> </div> </template> <template v-else> <img class="icon" :src="item.currencyInfo.iconPath" /> {{ item.price | floatPrice(4) }} {{ item.currencyInfo.tokenSymbol }} (${{ item.usdPrice | floatPrice(2) }}) </template> </template> <template v-else> ${{ item.usdPrice | floatPrice(2) }} </template> </FontZoom> </div> </template> <template v-else> <div class="btn disable"> <div class="l">BUY {{ item.itemCount }}</div> <FontZoom width="210"> <template v-if="item.currencyCode !== 'USD'"> <img class="icon" :src="item.currencyInfo.iconPath" /> {{ item.price | floatPrice(4) }} {{ item.currencyInfo.tokenSymbol }} (${{ item.usdPrice | floatPrice(2) }}) </template> <template v-else> ${{ item.usdPrice | floatPrice(2) }} </template> </FontZoom> </div> </template> </template> </div> </template> <template v-else> <template v-if="purchaseStatus !== 0"> <div class="btn" @click="goBuy()">BUY 1</div> </template> <template v-else> <div class="btn disable">BUY 1</div> </template> </template> <div class="sale"> <div class="l">SOLD: {{ data.itemSoldCount || 0 }}/{{ data.itemTotalCount }}</div> <div class="r" v-if="data.perUserBuyLimit < data.itemTotalCount">Buy Limit: {{ data.userBuyCount || 0 }}/{{ data.perUserBuyLimit }}</div> </div> </div> </template> <van-popup round v-model="loginLayer" position="bottom"> <div class="login"> <div class="title">In order to purchase the NFT, you need to</div> <div class="btn" @click="login"> <button-login @success="loginSuccess" @error="loginError"> </button-login> <div class="text">Login Twitter</div> </div> </div> </van-popup> <!-- loading --> <div class="loginLoading" v-if="loading"> <van-loading color="#1D9BF0"></van-loading> </div> <div class="loginLoadingBg" v-if="loading"></div> </div> </template> <script> import Api from '../http/api'; import FontZoom from './FontZoom'; import ButtonLogin from './buttonLogin'; import Report from './../log-center/log'; import { Toast } from 'vant'; import { postRequest } from '../http'; import { getStorage, storageKey } from '../utils/help'; export default { name: 'mobileBuyNft', components: { FontZoom, ButtonLogin, }, data() { return { data: null, curItem: null, listData: [], nftMetaData: {}, loading: false, loginLayer: false, }; }, props: { purchaseStatus: { type: Number, default: 0, }, }, filters: { floatPrice(price, num) { if (price.indexOf('.') >= 0) { let reg = new RegExp(`^\\D*(\\d*(?:\\.\\d{0,${num}})?).*$`, 'g'); price = price.replace(reg, '$1'); } return price; }, }, created() { this.getSaleInfo(); // report Report.log({ pageSource: Report.pageSource.nftPurchasePage, params: { eventData: { businessType: Report.businessType.pageView, }, extParams: { userAgent: window.navigator.userAgent, }, }, }); }, methods: { select(item) { this.curItem = item; this.nftMetaData = JSON.parse(item['metadata']); }, getSaleInfo() { postRequest(Api.getNftMysteryBoxSaleInfo, { params: { nftProjectId: this.$route.params.id, }, }).then((res) => { let { code, data } = res; if (code === 0) { this.data = data; this.listData = data.showItems; this.curItem = data.showItems[0]; this.nftMetaData = JSON.parse(data.showItems[0]['metadata']); // set title document.title = data['nftProjectName'] + ` NFT`; } }); }, goBuy(isNext = true) { if (isNext === false) return; let userInfo = getStorage(storageKey.userInfo); if (userInfo) { this.loginSuccess(userInfo, false); } else { this.loginLayer = true; // report Report.log({ pageSource: Report.pageSource.nftLoginPage, params: { eventData: { businessType: Report.businessType.pageView, }, extParams: { userAgent: window.navigator.userAgent, }, }, }); } // report Report.log({ pageSource: Report.pageSource.nftPurchasePage, params: { eventData: { businessType: Report.businessType.buttonClick, objectType: Report.objectType.buyNftButton, }, extParams: { userAgent: window.navigator.userAgent, }, }, }); }, login() { this.loading = true; Report.log({ pageSource: Report.pageSource.nftLoginPage, params: { eventData: { businessType: Report.businessType.buttonClick, objectType: Report.objectType.loginTwitterButton, }, extParams: { userAgent: window.navigator.userAgent, }, }, }); }, loginSuccess(userInfo, isReport = true) { this.$router.push({ name: 'Payment', query: { nftProjectId: this.$route.params.id, account: this.$route.params.account, }, }); if (isReport) { Report.log({ pageSource: Report.pageSource.nftLoginPage, params: { eventData: { businessType: Report.businessType.buttonClick, objectType: Report.objectType.loginTwitterButton, }, extParams: { 'login-result': 'sucess', userAgent: window.navigator.userAgent, }, }, }); } }, loginError() { Toast('login fail'); this.loading = false; Report.log({ pageSource: Report.pageSource.nftLoginPage, params: { eventData: { businessType: Report.businessType.buttonClick, objectType: Report.objectType.loginTwitterButton, }, extParams: { 'login-result': 'fail', userAgent: window.navigator.userAgent, }, }, }); }, }, }; </script> <style lang="scss" scoped> .page { width: 100%; height: 100%; background-color: #fff; .loading { position: absolute; transform: translate(-50%, -50%); top: 50%; left: 50%; margin: auto; width: 40px; border-radius: 50%; } } .swipe { .show { overflow: hidden; width: 18rem; height: 18rem; margin: 1rem auto; border-radius: 6px; background-color: #efefef; img { width: 100%; height: 100%; } } .list { height: 64px; margin: 0 16px; font-size: 0; overflow-x: auto; white-space: nowrap; &::-webkit-scrollbar { display: none; } .item { display: inline-block; overflow: hidden; opacity: 0.2; width: 58px; height: 58px; margin: 0 3px; border-radius: 4px; background-color: #efefef; img { width: 100%; height: 100%; } &:first-child { margin-left: 0; } &:last-child { margin-right: 0; } &.on { opacity: 1; } } } } .line { border: 1px solid #e3e3e3; border-radius: 10px; padding: 14px; margin: 0 16px 12px 16px; box-sizing: border-box; .title { font-weight: 600; font-size: 14px; } } .desc { margin-top: 10px; .desc-content { font-weight: 500; font-size: 14px; color: #929292; span { color: #1d9bf0; } } } .prop { .prop-content { display: flex; flex-wrap: wrap; margin-top: 12px; .prop-item { width: 48%; min-height: 88px; background: #f8f8f8; border-radius: 10px; display: flex; flex-direction: column; justify-content: center; padding: 8px; box-sizing: border-box; align-items: center; font-weight: 500; font-size: 12px; color: #929292; margin-bottom: 10px; .prop-name { font-weight: 700; font-size: 17px; margin-top: 6px; margin-bottom: 8px; color: #000; word-break: break-all; } } .prop-item:nth-child(odd) { margin-right: 8px; } } } .about-content { margin-top: 22px; .section { font-weight: 400; font-size: 14px; margin-bottom: 20px; } } .buy { position: fixed; left: 0; bottom: 0; width: 100%; box-sizing: border-box; background-color: #fff; padding: 10px 16px 25px 16px; border-top: solid 1px #e3e3e3; .random { color: #8c7d43; font-size: 14px; height: 30px; img { width: 20px; height: 20px; vertical-align: middle; } } .btn { display: flex; font-size: 16px; color: #ffffff; align-items: center; justify-content: space-between; width: 100%; height: 50px; padding: 0 14px; font-weight: 700; border-radius: 50px; background: #1d9bf0; &.disable { background: #cdcdcd; cursor: not-allowed; } .icon { width: 22px; margin-right: 5px; } .l { white-space: nowrap; } } .sale { display: flex; justify-content: space-between; color: #868686; font-size: 12px; line-height: 14px; padding: 10px 0; letter-spacing: 0.3px; } .tr { text-align: right; } } .login { box-sizing: border-box; padding: 38px 16px; width: 100%; .title { font-size: 16px; font-weight: 500; margin-bottom: 20px; } .btn { position: relative; display: flex; align-items: center; justify-content: center; height: 50px; border-radius: 50px; background: #1d9bf0; .text { font-size: 18px; font-weight: 700; color: #ffffff; } } } .loginLoading { position: absolute; z-index: 9991; display: flex; align-items: center; justify-content: center; top: 0; left: 0; width: 100%; height: 100%; } .loginLoadingBg { position: absolute; z-index: 9990; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba($color: #000, $alpha: 0.1); } </style>