478 lines
14 KiB
Vue
478 lines
14 KiB
Vue
<template>
|
|
<div class="cards">
|
|
<div class="card-top" v-if="nftData">
|
|
<div class="card-img" @click="toDetail">
|
|
<ImgCard :nftData="nftData" />
|
|
<!-- <LazyLoadImg :src="nftData.image" :src-placeholder="placeholderImg" alt="图片"/> -->
|
|
</div>
|
|
<div class="card-name">
|
|
<div>
|
|
<span v-if="nftData.type == 1">GENESIS HERO</span>
|
|
<span v-if="nftData.type == 11">GOLD CARD</span>
|
|
<span v-if="nftData.type == 12">Legacy Heroes</span>
|
|
<span v-if="nftData.type == 13">Founder's Tag</span>
|
|
</div>
|
|
<div class="no-sell" v-show="nftData.on_sale == 1" @click="cancelNft(nftData)">
|
|
<img src="@/assets/img/marketplace/On_SeLL.png" alt="">
|
|
</div>
|
|
</div>
|
|
<div class="card-price">
|
|
<div class="sell-price">
|
|
<div v-show="nftData.on_sale == 1">
|
|
<span class="price-col">
|
|
{{ nftPrice }}
|
|
<!-- {{cardPrice(nftData)}} -->
|
|
</span>
|
|
<img :src="icon" alt="">
|
|
</div>
|
|
<div v-if="LOCKER_ADDRESS.toLowerCase() == nftData.owner_address.toLowerCase() || FOUNDER_ADDRESS.toLowerCase() == nftData.owner_address.toLowerCase()">
|
|
<span class="expected" v-if="nftData.type == 13">+{{contribution(nftData.quality, nftData.type)}}/d</span>
|
|
<span class="expected" v-if="nftData.type == 1 || nftData.type == 12">+{{contribution(nftData.detail.quality, nftData.type)}}/d</span>
|
|
<img src="@/assets/img/marketplace/totalContribution.png" alt="">
|
|
</div>
|
|
</div>
|
|
<div v-if="LOCKER_ADDRESS.toLowerCase() == nftData.owner_address.toLowerCase() || FOUNDER_ADDRESS.toLowerCase() == nftData.owner_address.toLowerCase()" class="link-staking" @click="unStake(nftData)">
|
|
<img src="@/assets/img/marketplace/Staking.png" alt="">
|
|
</div>
|
|
<div v-if="LOCKER_ADDRESS.toLowerCase() != nftData.owner_address.toLowerCase() && (nftData.type == 1 || nftData.type == 12) && nftData.on_sale == 0" class="link-below" @click="lockToGame('convert')">
|
|
Stake
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-btn" v-if="nftData.type != 13 && LOCKER_ADDRESS.toLowerCase() != nftData.owner_address.toLowerCase()">
|
|
<div class="card-sell" v-if="nftData.on_sale == 0" @click="sellNft(nftData)">List</div>
|
|
<div class="card-cancel" v-if="nftData.on_sale == 1" @click="cancelNft(nftData)">Cancel listing</div>
|
|
</div>
|
|
<div class="card-btn" v-else>
|
|
<div class="card-cancel" v-if="LOCKER_ADDRESS.toLowerCase() == nftData.owner_address.toLowerCase() || FOUNDER_ADDRESS.toLowerCase() == nftData.owner_address.toLowerCase()" @click="unStake(nftData)">Unstake</div>
|
|
<div class="card-sell" v-else @click="lockToGame('founder')">Stake</div>
|
|
</div>
|
|
<SellDialog :sellDialogVisible="sellDialogVisible" :floorPrice="floorPrice" :sellDataArr="sellDataArr" @handleClose="sellHandleClose" />
|
|
<LoadingDialog :loadingDialogVisible="loadingDialogVisible" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, toRaw, onMounted, getCurrentInstance, inject } from "vue"
|
|
const message = inject('$message')
|
|
import SellDialog from "@/components/Dialogs/sellDialog.vue"
|
|
import { apiGetPrice, nftDetail } from "@/utils/marketplace"
|
|
import ImgCard from "@/components/common/imgCard.vue"
|
|
import LoadingDialog from "@/components/Dialogs/loadingDialog.vue"
|
|
import { priceCalculated } from "@/configs/priceCalculate"
|
|
import LazyLoadImg from "@/components/lazyloadimg"
|
|
import placeholderImg from '@/assets/img/marketplace/GenesisHeroes_NFT.png'
|
|
import {createModal} from "@/utils/model.util";
|
|
import ConfirmDialog from "@/components/Dialogs/confirmDialog.vue"
|
|
import { timeFormat, contribution } from "@/configs/priceCalculate"
|
|
import { Locker } from "@/components/chain/contract/Locker"
|
|
const emit = defineEmits(['renewMyNft'])
|
|
import {formatPrice} from "@/components/chain/utils"
|
|
import { useMarketplaceStore } from "@/store/marketplace"
|
|
const marketplaceStore = useMarketplaceStore()
|
|
import { useRouter } from "vue-router";
|
|
import { BlockChain } from "@/components/chain/BlockChain"
|
|
const router = useRouter();
|
|
const { proxy } = getCurrentInstance();
|
|
const props = defineProps({
|
|
nftData: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
});
|
|
const LOCKER_ADDRESS = ref(import.meta.env.VUE_APP_LOCKER_ADDRESS)
|
|
const FOUNDER_ADDRESS = ref(import.meta.env.VUE_APP_FOUNDER_ADDRESS)
|
|
|
|
// 获取地板价
|
|
const floorPrice = ref('0')
|
|
const getFloorPrice = async (val) => {
|
|
const data = {
|
|
net_id: val.net_id,
|
|
contract_address: val.contract_address,
|
|
item_id: val.item_id,
|
|
quality: val.detail.quality,
|
|
}
|
|
let res = await apiGetPrice(data)
|
|
if(res.lowest_price_goods) {
|
|
floorPrice.value = res.lowest_price_goods.event.data.buy[0].amount
|
|
} else {
|
|
floorPrice.value = '0'
|
|
}
|
|
return floorPrice.value
|
|
}
|
|
|
|
// 获取nft信息
|
|
const getNftData = async (val) => {
|
|
let nftDetailData = {}
|
|
const { errcode, errmsg, data } = await nftDetail(toRaw(val).contract_address,toRaw(val).token_id)
|
|
if(errcode == 0) {
|
|
nftDetailData = data
|
|
} else {
|
|
// alert('0000')
|
|
}
|
|
return nftDetailData
|
|
}
|
|
|
|
const sellDialogVisible = ref(false)
|
|
const sellDataArr = ref([])
|
|
// 出售NFT
|
|
const sellNft = async (val) => {
|
|
sellDataArr.value = val
|
|
floorPrice.value = await getFloorPrice(val)
|
|
sellDialogVisible.value = true
|
|
}
|
|
|
|
// 取消出售
|
|
const cancelNft = async (val) => {
|
|
let orderIds = await getNftData(val)
|
|
try {
|
|
const bc = new BlockChain()
|
|
let res = await bc.market.cancelOrder([orderIds.event.data.id])
|
|
if(res.result) {
|
|
let timer = setTimeout(() => {
|
|
message.success('Your item has been unlisted.')
|
|
emit('renewMyNft')
|
|
clearTimeout(timer);
|
|
}, 2000);
|
|
}
|
|
} catch (e) {
|
|
if(e.message.indexOf('rejected') > -1) {
|
|
message.error('User rejected the request')
|
|
} else {
|
|
message.error('Your item has failed to be unlisted.')
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const loadingDialogVisible = ref(false)
|
|
// 下链使用
|
|
const lockToGame = async(type) => {
|
|
if(type == 'founder') {
|
|
const confirmResult = await createModal(ConfirmDialog, {
|
|
title: '',
|
|
message: `Are you sure you want to stake?`
|
|
}).show()
|
|
if (confirmResult.errcode == 0) {
|
|
loadingDialogVisible.value = true
|
|
unlockMainConfirm()
|
|
}
|
|
} else if(type == 'convert') {
|
|
const confirmResult = await createModal(ConfirmDialog, {
|
|
title: '',
|
|
message: 'Are you sure you want to stake?'
|
|
}).show()
|
|
if (confirmResult.errcode == 0) {
|
|
loadingDialogVisible.value = true
|
|
lockToGameConfirm()
|
|
}
|
|
}
|
|
}
|
|
const lockToGameConfirm = async () => {
|
|
try {
|
|
const bc = new BlockChain()
|
|
let res = await bc.locker.lock(toRaw(props.nftData).contract_address, [toRaw(props.nftData).token_id])
|
|
message.success('lockToGame success')
|
|
// router.go(-1)
|
|
emit('renewMyNft')
|
|
loadingDialogVisible.value = false
|
|
// router.push('/assets')
|
|
} catch (e) {
|
|
if(e.message.indexOf('rejected') > -1) {
|
|
message.error('User rejected the request')
|
|
} else {
|
|
message.error('lockToGame fail.')
|
|
}
|
|
loadingDialogVisible.value = false
|
|
}
|
|
}
|
|
|
|
const unlockMainConfirm = async () => {
|
|
try {
|
|
const bc = new BlockChain()
|
|
let res = await bc.locker.lockMain(toRaw(props.nftData).contract_address, [toRaw(props.nftData).token_id])
|
|
message.success('lockToGame success')
|
|
// router.go(-1)
|
|
emit('renewMyNft')
|
|
loadingDialogVisible.value = false
|
|
// router.push('/assets')
|
|
} catch (e) {
|
|
if(e.message.indexOf('rejected') > -1) {
|
|
message.error('User rejected the request')
|
|
} else {
|
|
message.error('lockToGame fail.')
|
|
}
|
|
loadingDialogVisible.value = false
|
|
}
|
|
}
|
|
|
|
|
|
// 获取出售中价格价格
|
|
const nftPrice = ref('-')
|
|
const icon = ref('')
|
|
const cardPrice = async (val) => {
|
|
let nftData = await getNftData(toRaw(val))
|
|
// console.log(nftData)
|
|
if (nftData?.event?.data) {
|
|
const data = formatPrice(nftData?.event?.data)
|
|
icon.value = data.icon
|
|
nftPrice.value = data.tokenAmount
|
|
}
|
|
|
|
}
|
|
|
|
// 赎回
|
|
const unStake = async (data) => {
|
|
if(marketplaceStore.userGold < 0) {
|
|
const confirmResult = await createModal(ConfirmDialog, {
|
|
title: '',
|
|
message: 'Unstake Failed - Negative in-game gold balance. Please adjust your balance to continue.'
|
|
}).show()
|
|
} else {
|
|
if(toRaw(data).type == 13) {
|
|
founderLock(toRaw(data))
|
|
} else if(toRaw(data).type == 1 || toRaw(data).type == 12) {
|
|
heroLock(data)
|
|
}
|
|
}
|
|
}
|
|
const heroLock = async (data) => {
|
|
loadingDialogVisible.value = true
|
|
try {
|
|
const bc = new BlockChain()
|
|
let res = await bc.locker.unlockOrMintGameNft(toRaw(data).contract_address,[toRaw(data).token_id])
|
|
if(res) {
|
|
let timer = setTimeout(() => {
|
|
message.success('Unstake success.')
|
|
loadingDialogVisible.value = false
|
|
emit('renewMyNft')
|
|
clearTimeout(timer);
|
|
}, 2000);
|
|
}
|
|
} catch (e) {
|
|
loadingDialogVisible.value = false
|
|
if(e.message.indexOf('rejected') > -1) {
|
|
message.error('User rejected the request')
|
|
} else if (e.message.indexOf('select wallet') > -1) {
|
|
message.error('user cancel select wallet')
|
|
} else {
|
|
message.error('Unstake fail')
|
|
}
|
|
}
|
|
}
|
|
const founderLock = async (data) => {
|
|
loadingDialogVisible.value = true
|
|
try {
|
|
const bc = new BlockChain()
|
|
let res = await bc.locker.unlockMain(toRaw(data).contract_address,[toRaw(data).token_id])
|
|
if(res) {
|
|
let timer = setTimeout(() => {
|
|
message.success('Unstake success.')
|
|
loadingDialogVisible.value = false
|
|
emit('renewMyNft')
|
|
clearTimeout(timer);
|
|
}, 2000);
|
|
}
|
|
} catch (e) {
|
|
loadingDialogVisible.value = false
|
|
if(e.message.indexOf('rejected') > -1) {
|
|
message.error('User rejected the request')
|
|
} else if (e.message.indexOf('select wallet') > -1) {
|
|
message.error('user cancel select wallet')
|
|
} else {
|
|
message.error('Unstake fail')
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// 去详情页面
|
|
const toDetail = () => {
|
|
if(props.nftData.type == 13) {
|
|
marketplaceStore.detailData = {nft: props.nftData}
|
|
router.push('/detail')
|
|
} else {
|
|
router.push(`/detail/${props.nftData.contract_address}/${props.nftData.token_id}`)
|
|
}
|
|
}
|
|
|
|
// 关闭弹窗
|
|
const sellHandleClose = (val) => {
|
|
sellDialogVisible.value = false
|
|
sellDataArr.value = []
|
|
if(val) {
|
|
let timer = setTimeout(() => {
|
|
emit('renewMyNft')
|
|
clearTimeout(timer);
|
|
}, 2000);
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
cardPrice(toRaw(props.nftData))
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.cards {
|
|
background: #2d2738;
|
|
border-radius: 20px;
|
|
color: #fff;
|
|
// padding: 20px;
|
|
overflow: hidden;
|
|
.card-top {
|
|
padding: 30px 30px 20px 30px;
|
|
box-sizing: border-box;
|
|
.card-img {
|
|
width: 240px;
|
|
height: 360px;
|
|
margin: 0 auto;
|
|
:deep(.card-img-common) {
|
|
li {
|
|
width: 100%;
|
|
height: 100%;
|
|
.img-top {
|
|
width: 100px;
|
|
height: 30px;
|
|
top: 20px;
|
|
left: 20px;
|
|
}
|
|
.img-btm {
|
|
bottom: 12px;
|
|
left: 20px;
|
|
>div {
|
|
width: 80px;
|
|
height: 30px;
|
|
}
|
|
div:nth-child(1) {
|
|
}
|
|
div:nth-child(2) {
|
|
margin-left: 8px;
|
|
}
|
|
}
|
|
.founder {
|
|
position: absolute;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 260px;
|
|
height: 260px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.card-name {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
height: 46px;
|
|
margin: 20px 0;
|
|
font-family: 'Poppins';
|
|
font-weight: 600;
|
|
font-size: 20px;
|
|
box-sizing: border-box;
|
|
color: #F3F0FF;
|
|
.no-sell {
|
|
width: 138px;
|
|
height: 46px;
|
|
img {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
}
|
|
.card-price {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
>div {
|
|
display: flex;
|
|
// justify-content: center;
|
|
align-items: center;
|
|
width: 94px;
|
|
height: 44px;
|
|
font-family: 'Poppins';
|
|
font-weight: 400;
|
|
font-size: 14px;
|
|
border-radius: 10px;
|
|
}
|
|
.sell-price {
|
|
div {
|
|
display: flex;
|
|
align-items: center;
|
|
text-align: left;
|
|
span {
|
|
font-family: 'Poppins';
|
|
font-weight: 600;
|
|
font-size: 20px;
|
|
}
|
|
.price-col {
|
|
color: #9A50FF;
|
|
}
|
|
.expected {
|
|
color: #00DEFF;
|
|
}
|
|
}
|
|
img {
|
|
width: 25px;
|
|
height: 25px;
|
|
margin-left: 10px;
|
|
}
|
|
}
|
|
.link-staking {
|
|
img {
|
|
width: 140px;
|
|
height: 48px;
|
|
}
|
|
}
|
|
.enabled {
|
|
justify-content: center;
|
|
border: 2px solid #ffd45f;
|
|
color: #FEC25D;
|
|
}
|
|
.link-below {
|
|
justify-content: center;
|
|
color: #FF6271;
|
|
border: 2px solid #ff6978;
|
|
}
|
|
}
|
|
}
|
|
.card-btn {
|
|
width: 95%;
|
|
height: 50px;
|
|
margin: 0 auto;
|
|
margin-bottom: 5px;
|
|
border-radius: 10px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
padding-bottom: 8px;
|
|
>div {
|
|
height: 57px;
|
|
background: #1778f1;
|
|
border-radius: 12px;
|
|
text-align: center;
|
|
}
|
|
.card-sell, .card-cancel {
|
|
width: 100%;
|
|
line-height: 57px;
|
|
color: #fff;
|
|
font-weight: 700;
|
|
font-size: 28px;
|
|
}
|
|
.card-cancel {
|
|
background: #ff6271;
|
|
}
|
|
.card-cat {
|
|
width: 71px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
margin-left: 3px;
|
|
img {
|
|
width: 43px;
|
|
height: 39px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style> |