253 lines
6.0 KiB
Vue
253 lines
6.0 KiB
Vue
<template>
|
|
<div class="card" >
|
|
<img v-if="data.id" class="bg-img" src="@/assets/main/card/card_border.png" alt="">
|
|
<div v-if="data.id" class="anim-border">
|
|
<img class="card-main-img" :src="require(`@/assets/main/card/${data.skelName}.png`)" alt=""/>
|
|
<div class="name-label" :class="{'bottom': !data.showBuy}">{{data.name}}</div>
|
|
<div class="info-div" v-if="data.showBuy" @click="buyItem" :class="{'gray': !showLight}">
|
|
<img class='buy-icon' src="@/assets/main/card/icon_buy.png" alt=""/>
|
|
<div class="price-label">
|
|
<span :class="{'price': data.price !== data.priceDiscount}">{{priceDiscountShow}} {{data.currency}}</span>
|
|
<span v-if="data.price!==data.priceDiscount" class="price-old">{{priceShow}} {{data.currency}}</span>
|
|
</div>
|
|
</div>
|
|
<div class="class-div">
|
|
<img :src="require('@/assets/main/card/class_'+data.class+'.png')" alt="">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Vue } from 'vue-property-decorator'
|
|
import { ISpineData } from '@/utils/SpineRender'
|
|
import { BlockChain } from '@/utils/blockchain'
|
|
import { AppModule } from '@/store/modules/app'
|
|
import { buyBox } from '@/api/Mall'
|
|
import { Message } from 'element-ui'
|
|
import { EventBus, NEED_LOGIN, PRESALE_BEGIN, PRESALE_ERROR, PRESALE_ORDER_GET } from '@/utils/event-bus'
|
|
import { UserModule } from '@/store/modules/user'
|
|
import { getNonce } from '@/api/User'
|
|
import ChainManager from '@/utils/ChainManager'
|
|
|
|
declare module 'vue/types/vue' {
|
|
interface Vue {
|
|
data: ISpineData
|
|
}
|
|
}
|
|
|
|
@Component({
|
|
name: 'NftItem',
|
|
components: {
|
|
},
|
|
props: ['data']
|
|
})
|
|
export default class extends Vue {
|
|
chainManger = new ChainManager()
|
|
|
|
get walletCollected() {
|
|
return AppModule.walletConnected
|
|
}
|
|
|
|
get showLight() {
|
|
return !this.accountId || this.canBuy
|
|
}
|
|
|
|
get canBuy() {
|
|
return !this.data.stopBuy && AppModule.presaleStatus === 2
|
|
}
|
|
|
|
get priceDiscountShow() {
|
|
const v = Math.pow(10, this.data.decimals!)
|
|
return (this.data.priceDiscount! / v).toFixed(3)
|
|
}
|
|
|
|
get priceShow() {
|
|
const v = Math.pow(10, this.data.decimals!)
|
|
return (this.data.price! / v).toFixed(3)
|
|
}
|
|
|
|
get accountId() {
|
|
return AppModule.accountId
|
|
}
|
|
|
|
get logined() {
|
|
return !!UserModule.token && !!AppModule.step
|
|
}
|
|
|
|
async buyItem() {
|
|
console.log('on click item: ', this.data.id)
|
|
if (!this.logined) {
|
|
await this.chainManger.login()
|
|
}
|
|
if (!this.canBuy) {
|
|
Message({
|
|
message: 'Can`t buy current time',
|
|
type: 'warning',
|
|
duration: 5 * 1000
|
|
})
|
|
return
|
|
}
|
|
if (!AppModule.canBuy) {
|
|
Message({
|
|
message: 'Can`t buy current time.',
|
|
type: 'warning',
|
|
duration: 5 * 1000
|
|
})
|
|
return
|
|
}
|
|
if (!this.data.directBuy) {
|
|
return
|
|
}
|
|
if (this.data.stopBuy) {
|
|
return
|
|
}
|
|
EventBus.$emit(PRESALE_BEGIN)
|
|
const account = AppModule.accountId
|
|
try {
|
|
const price = this.chainManger.bc.parsePrice(this.data.priceDiscount!, this.data.decimals!)
|
|
const { nonce, signature } = await this.chainManger.bc.signPresale({
|
|
type: this.data.recordId!,
|
|
paymentTokenAddress: this.data.coinAddress!,
|
|
price,
|
|
buyerAddress: account
|
|
})
|
|
const buyData = {
|
|
buyer_address: AppModule.accountId,
|
|
type: this.data.recordId,
|
|
price,
|
|
payment_token_address: this.data.coinAddress,
|
|
nonce,
|
|
signature
|
|
}
|
|
await this.chainManger.bc.increaseAllowance(this.data.coinAddress!, price)
|
|
const res: any = await buyBox(buyData)
|
|
const orderId = res.order_id
|
|
localStorage.setItem('tmp_presale_order_id', orderId)
|
|
EventBus.$emit(PRESALE_ORDER_GET, orderId)
|
|
} catch (err) {
|
|
console.log('buy error: ', err)
|
|
EventBus.$emit(PRESALE_ERROR, err)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
// rect: 297x389
|
|
$width: 14em;
|
|
$height: 18.33em;
|
|
.bg-img {
|
|
width: $width;
|
|
height: $height;
|
|
}
|
|
.anim-border {
|
|
width: $width;
|
|
height: $height;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
overflow: hidden;
|
|
}
|
|
.card-main-img {
|
|
position: absolute;
|
|
bottom: 0;
|
|
max-height: 100%;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
margin: auto;
|
|
}
|
|
|
|
.info-div {
|
|
background-image: url('../../assets/main/card/name_bg.png');
|
|
width: 100%;
|
|
height: $height * 0.29;
|
|
position: absolute;
|
|
bottom: $height * 0.025;
|
|
left: 0;
|
|
right: 0;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
background-size: contain;
|
|
background-repeat: no-repeat;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.class-div{
|
|
position: absolute;
|
|
top: 8px;
|
|
right: 8px;
|
|
width: $width*42/297;
|
|
height: $height*42/389;
|
|
}
|
|
.class-div img {
|
|
width: 100%;
|
|
}
|
|
.name-img {
|
|
height: $height * 39 / 389;
|
|
width: auto;
|
|
position: absolute;
|
|
right: $width * 9 / 297;
|
|
bottom: $height * 100 / 389;
|
|
}
|
|
.name-label {
|
|
font-family: 'title',serif;
|
|
color: white;
|
|
text-transform:capitalize;
|
|
font-size: $width * 40 / 390;
|
|
position: absolute;
|
|
right: $width * 20 / 297;
|
|
bottom: $height * 70 / 389;
|
|
}
|
|
.price-label {
|
|
color: black;
|
|
height: $height * 29 / 389;
|
|
font-weight: bold;
|
|
width: $width * 145 / 297;
|
|
background-image: url('../../assets/main/card/price_bg.png');
|
|
background-size: contain;
|
|
background-repeat: no-repeat;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-direction: column;
|
|
margin-right: $width * 40 / 297;
|
|
margin-bottom: $width * 10 / 297;
|
|
}
|
|
.price-label span {
|
|
font-size: $width * 20 / 297;
|
|
}
|
|
.price-label .price{
|
|
color: red;
|
|
margin-top: 9px;
|
|
text-shadow: black 0.1em 0.1em 0.2em
|
|
}
|
|
.price-label .price-old{
|
|
text-decoration:line-through;
|
|
font-size: $width * 15 / 297;
|
|
color: white;
|
|
text-shadow: black 0.1em 0.1em 0.2em
|
|
}
|
|
.buy-icon {
|
|
width: $width * 44 / 297;
|
|
height: $height * 52 / 389;
|
|
margin-left: $width * 40 / 297;
|
|
margin-bottom: $height * 12 / 389;
|
|
}
|
|
|
|
.gray {
|
|
-webkit-filter: grayscale(100%);
|
|
-moz-filter: grayscale(100%);
|
|
-ms-filter: grayscale(100%);
|
|
-o-filter: grayscale(100%);
|
|
|
|
filter: grayscale(100%);
|
|
}
|
|
.bottom {
|
|
bottom: $height * 10 / 389;
|
|
}
|
|
|
|
</style>
|