修改双重登录

This commit is contained in:
yuyongdong 2024-07-18 17:56:07 +08:00
parent 1d1ebca377
commit 6396c2b01a
3 changed files with 826 additions and 50 deletions

View File

@ -3,6 +3,7 @@
<div class="content-left">
<div class="left-content-left">
<OverView :overviewValue="overviewValue" @clickOverviewChild="overviewChild" />
<Status :statusValue="statusValue" @clickStatusChild="statusChild" />
</div>
</div>
<div class="content-right">
@ -17,10 +18,7 @@
</li>
</div>
<div class="pages-no" v-show="nftList == undefined || nftList.length <= 0">
<div class="no-data-tips">
<span v-if="localWalletStore.walletType != 3">Please log into the wallet holding your Founders Tag to view details.</span>
</div>
<div class="no-data-img">
<div>
<img src="@/assets/img/marketplace/Empty_state.png" alt="">
</div>
<p>No NFT yet</p>
@ -33,9 +31,10 @@
<script setup>
import { ref, onMounted, toRaw, onUnmounted, watch } from "vue";
import OverView from "@/components/common/searchView/Overview.vue";
import Card from "./cenCard.vue";
import Status from "@/components/common/searchView/nftStatusRadio.vue";
import Card from "./myCard.vue";
import NftId from "@/configs/item.json"
import { apiHeroList } from "@/utils/marketplace"
import { apiAssetsState } from "@/utils/marketplace"
import {useMarketplaceStore} from "@/store/marketplace";
import {walletStore} from "@/store/wallet";
const marketplaceStore = useMarketplaceStore()
@ -79,29 +78,15 @@ const getMyAssets = async () => {
// nftList.value = []
const myADdress = localWalletStore.address
const data = {
// type: statusValue.value,
// page_size: '20',
// cursor: next_cursor.value,
// search_name: overviewValue.value
page_size: 20,
cursor: '',
search: {
name: ''
},
filter: {
item_ids: [],
hero_ranks: [],
},
sort: {
fields: []
}
type: statusValue.value,
page_size: '20',
cursor: next_cursor.value,
search_name: overviewValue.value
}
if(myADdress) {
try {
let nftListBox
let res = await apiHeroList( data)
// console.log(res,'----------------------')
// return
let res = await apiAssetsState(myADdress, data)
nftList.value = [...nftList.value, ...res.rows]
nftListBox = nftList.value.reduce((acc, obj) => {
const existingObj = acc.find(item => item.token_id == obj.token_id)
@ -111,8 +96,8 @@ const getMyAssets = async () => {
return acc
},[])
nftList.value = nftListBox
// marketplaceStore.cursorObj = res.page
// next_cursor.value = res.page.next_cursor
marketplaceStore.cursorObj = res.page
next_cursor.value = res.page.next_cursor
} catch(e) {
console.log(e)
}
@ -129,9 +114,9 @@ const handleScroll = () => {
if (scrollTop + windowHeight == scrollHeight) {
//
// console.log('scrollTop + windowHeight == scrollHeight',toRaw(marketplaceStore.cursorObj), scrollTop, windowHeight, scrollHeight)
// if(toRaw(marketplaceStore.cursorObj).remaining != 0) {
// getMyAssets()
// }
if(toRaw(marketplaceStore.cursorObj).remaining != 0) {
getMyAssets()
}
return false;
}
}
@ -147,11 +132,11 @@ watch(localWalletStore,() => {
onMounted(() => {
getMyAssets()
// window.addEventListener("scroll", handleScroll, true);
window.addEventListener("scroll", handleScroll, true);
})
onUnmounted(() => {
// window.removeEventListener('scroll', handleScroll)
window.removeEventListener('scroll', handleScroll)
})
</script>
@ -217,21 +202,7 @@ onUnmounted(() => {
.pages-no {
position: relative;
margin-top: 256px;
.no-data-tips {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 100%;
text-align: center;
color: #fff;
margin-bottom: 20px;
font-size: 28px;
}
.no-data-img {
position: absolute;
top: 50px;
left: 50%;
transform: translateX(-50%);
div {
margin: 0 auto;
width: 401px;
height: 322px;
@ -242,7 +213,7 @@ onUnmounted(() => {
}
p {
position: absolute;
top: 310px;
top: 260px;
left: 52%;
transform: translateX(-50%);
font-family: 'Poppins';

View File

@ -19,7 +19,7 @@
<div class="pages-no" v-show="nftList == undefined || nftList.length <= 0">
<div class="no-data-tips">
<span v-if="!localWalletStore.refreshToken">Please log into the wallet holding your Centralized Assets to view details.</span>
<div @click="passportLogin">Login</div>
<div v-if="!localWalletStore.refreshToken" @click="passportLogin">Login</div>
</div>
<div class="no-data-img">
<img src="@/assets/img/marketplace/Empty_state.png" alt="">
@ -77,7 +77,7 @@ const renewMyNft = async() => {
const next_cursor = ref()
const getMyAssets = async () => {
const myADdress = localWalletStore.address
const myADdress = localWalletStore.passportAddress
const data = {
type: 3,
page_size: '20',

View File

@ -0,0 +1,805 @@
<template>
<div class="detail">
<div class="bg-content">
<div class="detail-bg"></div>
<div v-if="detailData" class="detail-content">
<div class="content">
<div class="top-left">
<div class="top-left-img">
<ImgCard :nftData="detailData.nft" />
</div>
</div>
<div class="top-right">
<h2>{{ detailData.nft.name }}</h2>
<div class="top-right-owner">
<div>Owner:</div>
<div class="address">{{ detailData.nft.owner_address }}</div>
</div>
<div class="top-right-price" v-if="detailData.event">
<li>
<div>Price</div>
<div class="time">
<img src="@/assets/img/marketplace/time.png" alt="img">
<div>Time remaining: &nbsp;<StarTimer :getAddress="detailData.event.data.end_at" /></div>
</div>
</li>
<li>
<div class="price">
<span class="bold">{{ price }}&nbsp;</span>
<img :src="icon" alt="ICON">
<span>( $ {{ usd }} )</span>
</div>
</li>
</div>
<div class="back-time" v-if="localWalletStore.token && LOCKER_ADDRESS.toLowerCase() == detailData.nft.owner_address.toLowerCase()">
<img src="@/assets/img/marketplace/time.png" alt="">
<span>Time remaining : 6d:10h:22m</span>
</div>
<div class="top-right-btns">
<div v-if="localWalletStore.token && LOCKER_ADDRESS.toLowerCase() == detailData.nft.owner_address.toLowerCase()">
<div class="cancel" @click="localWalletStore.token == '' ? cardLogin() : backStaking()">Unstake</div>
</div>
<!--
1添加购物车
2移除购物车
3购买
4
-->
<div v-if="myAddress != detailData.nft.owner_address">
<div v-if="detailData.event != null" class="buy" @click="localWalletStore.token == '' ? cardLogin() : buyNow()">Buy Now</div>
<div class="add" v-if="detailData.event != null && detailData.in_shopcart == 0" @click="localWalletStore.token == '' ? cardLogin() : addCart()">
<span>Add to cart </span>
<img src="@/assets/img/marketplace/Add_shopping_cart.png" alt="">
</div>
<div class="remove" v-if="detailData.in_shopcart == 1" @click="localWalletStore.token == '' ? cardLogin() : clearCart()">
<span>Remove from cart</span>
<img src="@/assets/img/marketplace/Move_out.png" alt="">
</div>
</div>
<!--
1上架
2下架
3使用
-->
<div v-else>
<div class="sell" @click="beginSell" v-if="detailData.nft.on_sale == 0">List</div>
<div class="cancel" @click="cancelSell" v-if="detailData.nft.on_sale == 1">Cancel listing</div>
<div class="redeem" @click="lockToGame('convert')" v-if="detailData.nft.on_sale == 0 && detailData.nft.type == 1">Convert</div>
<div class="redeem" @click="lockToGame('redeem')" v-if="detailData.nft.on_sale == 0 && detailData.nft.type == 11">Redeem</div>
</div>
</div>
<div class="info">
<h2>Info</h2>
<li>
<div>Contract address</div>
<div class="contract-address">
<div>{{ detailData.nft.contract_address}}</div>
<span><a :href="contractBlankUrl" target="_blank">{{ sliceAddress(detailData.nft.contract_address) }}</a></span>
</div>
</li>
<li>
<div>Token ID</div>
<div>
<a :href="contractTokenUrl" target="_blank">{{ detailData.nft.token_id }}</a>
</div>
</li>
<li>
<div>Blockchain</div>
<div>lmmutascan</div>
</li>
<li>
<div>Metadata</div>
<div><a :href="detailData.nft.meta_url" target="_blank">{{ sliceAddress(detailData.nft.meta_url) }}</a></div>
</li>
<li>
<div>Royalties</div>
<div>2%</div>
</li>
</div>
</div>
</div>
<div class="content">
<div v-if="detailData.nft.type == 1" class="btm-left">
<h2>Property</h2>
<div class="btm-detail">
<li v-for="(item, val, index) in nftAbilities" :key="index">
<div v-show="val == 'quality'">
<h5>Tier</h5>
<p>{{ item }}</p>
</div>
<div v-show="val == 'max_mining_days'">
<h5>Active Days</h5>
<p>{{ item }}</p>
</div>
<div v-show="val == 'wealth'">
<h5>Wealth Value</h5>
<p>{{ parseInt(item) }}</p>
</div>
<div v-show="val == 'lucky'">
<h5>Luck Value</h5>
<p>{{ parseInt(item) }}</p>
</div>
<div v-show="val == 'hp'">
<h5>HP</h5>
<p>{{ parseInt(item) }}</p>
</div>
<div v-show="val == 'atk'">
<h5>Attack</h5>
<p>{{ parseInt(item) }}</p>
</div>
<div v-show="val == 'def'">
<h5>Defense</h5>
<p>{{ Number(item).toFixed(2) }}%</p>
</div>
<div v-show="val == 'block'">
<h5>Block Rate</h5>
<p>{{ Number(item).toFixed(2) }}%</p>
</div>
<div v-show="val == 'crit'">
<h5>Crit Rate</h5>
<p>{{ Number(item).toFixed(2) }}%</p>
</div>
</li>
</div>
</div>
<div v-else class="btm-left">
<h2>Property</h2>
<div class="gold-content">
<div class="left">
<h4>Gold Amount</h4>
<p>{{ detailData.nft.detail.gold_coins }}</p>
</div>
<div class="right">
<div class="right-img">
<img src="@/assets/img/marketplace/Icon_!.png" alt="">
</div>
<div class="right-tips">
A Gold Card is equivalent to 100,000 Gold. Once redeemed, 100,000 Gold will be credited to your Counter Fire game account.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<Footer />
<BuyDialog :buyDialogVisible="buyDialogVisible" :buyDataArr="buyDataArr" @handleClose="BuyHandleClose" />
<SellDialog v-if="detailData" :sellDialogVisible="sellDialogVisible" :floorPrice="floorPrice" :sellDataArr="detailData.nft" @handleClose="sellHandleClose" />
<LoadingDialog :loadingDialogVisible="loadingDialogVisible" />
</div>
</template>
<script setup>
import { ref, toRaw, onMounted , inject} from "vue"
const message = inject('$message')
import { useRouter } from "vue-router";
import BuyDialog from "@/components/Dialogs/buyDialog.vue"
import ConfirmDialog from "@/components/Dialogs/confirmDialog.vue"
import LoadingDialog from "@/components/Dialogs/loadingDialog.vue"
import ImgCard from "@/components/common/imgCard.vue"
import StarTimer from "@/components/common/starTimer.vue"
import SellDialog from "@/components/Dialogs/sellDialog.vue"
import Footer from "@/components/common/footer.vue"
import { nftDetail, apiGetPrice } from "@/utils/marketplace"
import {priceCalculated} from "@/configs/priceCalculate.js"
import { BlockChain } from "@/components/chain/BlockChain"
import {walletStore} from "@/store/wallet";
import { useMarketplaceStore } from "@/store/marketplace"
import LazyLoadImg from "@/components/lazyloadimg"
import {formatPrice} from "@/components/chain/utils"
import {createModal} from "@/utils/model.util";
const router = useRouter();
const localWalletStore = walletStore()
const marketplaceList = useMarketplaceStore()
const props = defineProps({
address: String,
tokenid: String
})
import placeholderImg from '@/assets/img/marketplace/GenesisHeroes_NFT.png'
const detailData = ref(null)
const myAddress = localWalletStore.address
const contractBlankUrl = ref()
const contractTokenUrl = ref()
const nftAbilities = ref()
const icon = ref('')
const usd = ref('')
const price = ref('')
const loadingDialogVisible = ref(false)
const LOCKER_ADDRESS = ref(import.meta.env.VUE_APP_LOCKER_ADDRESS)
//
const cardLogin = async () => {
await new BlockChain().connect()
}
//
const buyDialogVisible = ref(false)
const buyDataArr = ref([])
const buyNow = async () => {
detailData.value['icon'] = icon.value
detailData.value['tokenAmount'] = price.value
buyDataArr.value = []
buyDataArr.value.push(detailData.value)
buyDialogVisible.value = true
return
const buyResult = await createModal(BuyDialog, {
buyDataArr: buyDataArr.value,
}).show()
console.log(buyResult.errcode)
if(buyResult.errcode == 0) {
message.success('buy success')
} else if(buyResult.errcode == 1) {
if(buyResult.err.message.indexOf() > -1) {
message.error('User rejected the request')
} else {
message.error('buy fail')
}
}
}
const BuyHandleClose = () => {
buyDialogVisible.value = false
}
//
const addCart = async () => {
const data = {
net_id: import.meta.env.VUE_APP_NET_ID,
tokens: [
{
token_id: detailData.value.nft.token_id,
contract_address: detailData.value.nft.contract_address,
}
]
}
try {
const { errcode, errmsg } = await marketplaceList.addCartListState(data)
// console.log(errcode, errmsg)
if(errcode == 0) {
message.success('success! Add from cart')
marketplaceList.getCartList = await marketplaceList.getCartListState()
getDetail()
}
} catch (e) {
message.error('fail! Add from cart')
}
}
//
const clearCart = async () => {
// TODO:
const data = {
net_id: import.meta.env.VUE_APP_NET_ID,
tokens: [
{
token_id: detailData.value.nft.token_id,
contract_address: detailData.value.nft.contract_address,
}
]
}
try {
const { errcode, errmsg } = await marketplaceList.delCartListState(data)
if(errcode == 0) {
message.success('success! Remove from cart')
marketplaceList.getCartList = await marketplaceList.getCartListState()
getDetail()
}
} catch (e) {
// console.log(e)
}
}
// 使
const lockToGame = async(type) => {
if(type == 'redeem') {
const confirmResult = await createModal(ConfirmDialog, {
title: '',
message: `Redeem ${detailData.value.nft.detail.gold_coins} Gold to your game account. Do you wish to proceed?`
}).show()
if (confirmResult.errcode == 0) {
loadingDialogVisible.value = true
lockToGameConfirm()
}
} else if(type == 'convert') {
const confirmResult = await createModal(ConfirmDialog, {
title: '',
message: 'After converting, you will be able to use the hero in the game. At the end of Season 1, the hero will automatically be returned to your wallet or Immutable Passport. Do you want to proceed?'
}).show()
if (confirmResult.errcode == 0) {
loadingDialogVisible.value = true
lockToGameConfirm()
}
}
}
const lockToGameConfirm = async () => {
try {
await new BlockChain().locker.lock(detailData.value.nft.contract_address, [detailData.value.nft.token_id])
message.success('lockToGame success')
loadingDialogVisible.value = false
router.go(-1)
} catch (e) {
if(e.message.indexOf('rejected') > -1) {
message.error('User rejected the request')
} else {
message.error('lockToGame fail.')
}
loadingDialogVisible.value = false
}
}
//
const backStaking = () => {
console.log('---')
}
//
const floorPrice = ref('0')
const sellDialogVisible = ref(false)
const beginSell = async() => {
if (detailData.value.event) return
floorPrice.value = await getFloorPrice()
sellDialogVisible.value = true
}
//
const cancelSell = async() => {
// console.log('cancelSell', detailData.value.event)
if (!detailData.value.event) return
try {
let res = await new BlockChain().market.cancelOrder([detailData.value.event.data.id])
if(res.result) {
let timer = setTimeout(() => {
getDetail()
message.success('Your item has been unlisted.')
clearTimeout(timer)
}, 2000);
}
} catch (e) {
// try {
// let res = await new BlockChain().market.cancelOrdersOnChain([detailData.value.event.data.id])
// if(res.result) {
// let timer = setTimeout(() => {
// getDetail()
// clearTimeout(timer)
// }, 2000);
// }
// } catch (e2) {
// // console.log('cancelSell fail', e.message)
// }
if(e.message.indexOf('rejected') > -1) {
message.error('User rejected the request')
} else {
message.error('Your item has failed to be unlisted.')
}
}
}
//
const sliceAddress = (address) => {
if (!address) return "-";
if (address.length >= 10) {
return `${address.substring(0, 6)}......${address.slice(-4)}`;
}
return address;
}
//
const getFloorPrice = async () => {
const data = {
net_id: detailData.value.nft.net_id,
contract_address: detailData.value.nft.contract_address,
item_id: detailData.value.nft.item_id,
quality: detailData.value.nft.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
}
//
const sellHandleClose = (val) => {
if(val) {
let timer = setTimeout(() => {
getDetail()
clearTimeout(timer)
}, 2000);
sellDialogVisible.value = false
} else {
sellDialogVisible.value = false
}
}
const getDetail = async () => {
let { errcode, errmsg, data} = await nftDetail(props.address, props.tokenid)
contractBlankUrl.value = `${import.meta.env.VUE_APP_EXPLORER_URL}/address/${data.nft.contract_address}`
contractTokenUrl.value = `${import.meta.env.VUE_APP_EXPLORER_URL}/token/${data.nft.contract_address}/instance/${data.nft.token_id}`
if (errcode) {
// console.log(errmsg)
//TODO::
return
}
const nftData = data.nft
nftData.event = data.event
nftAbilities.value = data.nft.detail
detailData.value = data
if (data.event?.data) {
const _data = formatPrice(data.event?.data)
icon.value = _data.icon
usd.value = _data.usd
price.value = _data.tokenAmount
}
}
console.log(location.pathname.length)
onMounted(() => {
if(location.pathname.length > 8) {
getDetail()
} else {
console.log('中心化')
}
})
</script>
<style lang="scss" scoped>
.detail {
width: 100%;
box-sizing: border-box;
background: #000;
.bg-content {
width: 100%;
height: 100%;
background: url('@/assets/img/marketplace/BG01.png') no-repeat;
background-size: 100% 100%;
}
.detail-bg {
width: 100%;
height: 84px;
}
.detail-content {
width: 100%;
height: 100%;
.content {
width: 1266px;
margin: 0 auto;
padding-top: 76px;
display: flex;
justify-content: space-between;
color: #fff;
.top-left {
width: 453px;
.top-left-img {
height: 678px;
:deep(.card-img-common) {
.img-top {
width: 120px;
height: 35px;
top: 20px;
left: 20px;
font-size: 18px;
}
.img-btm {
bottom: 35px;
left: 65px;
>div {
width: 120px;
height: 43px;
font-size: 18px;
}
div:nth-child(2) {
margin-left: 15px;
}
}
}
}
}
.top-right {
width: 719px;
h2 {
font-size: 42px;
font-family: 'Poppins';
font-weight: bold;
}
.top-right-owner {
display: flex;
font-family: 'Poppins';
font-weight: bold;
font-size: 30px;
.address {
margin-left: 20px;
}
}
.top-right-price {
width: 719px;
height: 133px;
display: flex;
flex-direction: column;
justify-content: space-between;
background: #2d2738;
border-radius: 20px;
margin-top: 10px;
color: #BB7FFF;
padding: 15px 20px;
box-sizing: border-box;
li {
display: flex;
justify-content: space-between;
>div {
display: flex;
font-size: 28px;
color: #9950FD;
}
.time {
display: flex;
align-items: center;
justify-content: end;
font-size: 18px;
img {
width: 25px;
height: 28px;
margin-right: 5px;
}
div {
display: flex;
align-items: center;
}
}
.price {
display: flex;
align-items: center;
span {
font-family: 'Poppins';
font-weight: 400;
font-size: 24px;
color: #BB7FFF;
}
.bold {
font-weight: bold;
font-size: 48px;
}
img {
width: 30px;
height: 30px;
margin-right: 20px;
}
}
}
}
.back-time {
width: 340px;
height: 40px;
line-height: 40px;
background: #272130;
border-radius: 20px;
font-family: 'Poppins';
font-weight: 300;
font-size: 18px;
color: #9A50FF;
display: flex;
align-items: center;
img {
width: 20px;
height: 25px;
margin-right: 6px;
margin-left: 24px;
}
}
.top-right-btns {
div {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
>div {
width: 348px;
height: 57px;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Poppins';
font-weight: bold;
font-size: 28px;
color: #FFFFFF;
border-radius: 12px;
cursor: pointer;
}
.buy {
background: #6336d7;
}
.add {
background: #1778f1;
span {
height: 100%;
line-height: 57px;
border-radius: 12px;
text-align: center;
display: inline-block;
background: #1778f1;
}
img {
width: 43px;
height: 44px;
margin-left: 20px;
}
}
.remove {
background: #1778f1;
span {
height: 100%;
line-height: 57px;
border-radius: 12px;
text-align: center;
display: inline-block;
}
img {
width: 43px;
height: 44px;
}
}
.sell {
width: 348px;
background: #6336d7;
}
.cancel {
width: 348px;
background: #ff6271;
}
.redeem {
width: 348px;
background: #1778f1;
}
}
}
.info {
color: #B3B5DA;
margin-top: 40px;
h2 {
font-family: 'Poppins';
font-weight: bold;
font-size: 30px;
color: #fff;
border-bottom: 2px solid #3A3B57;
}
li {
display: flex;
justify-content: space-between;
margin-top: 10px;
div {
width: 300px;
font-size: 22px;
text-align: left;
margin-top: 10px;
a {
color: #B3B5DA;
cursor: pointer;
}
}
.contract-address {
position: relative;
cursor: pointer;
>div {
width: 520px;
height: 40px;
position: absolute;
top: -50px;
left: -50%;
background: #17141b;
color: #fff;
display: none;
}
&:hover {
>div {
display: block;
}
}
}
}
}
}
.btm-left {
padding-bottom: 90px;
h2 {
font-size: 30px;
font-family: 'Poppins';
font-weight: bold;
margin-bottom: 10px;
}
.btm-detail {
display: flex;
flex-wrap: wrap;
clear: both;
width: 489px;
li {
width: 154px;
height: 84px;
background: #2d2738;
border-radius: 20px;
margin-right: 9px;
margin-bottom: 10px;
div {
text-align: center;
font-size: 22px;
color: #B3B5DA;
font-family: "Poppins";
h5 {
font-weight: bold;
}
p {
font-weight: 400;
color: #fff;
}
}
}
}
.gold-content {
width: 455px;
height: 84px;
background: #2D2738;
border-radius: 20px;
display: flex;
justify-content: space-between;
.left {
padding: 10px 19px;
font-family: 'Poppins';
font-size: 22px;
h4 {
height: 18px;
font-weight: 400;
color: #B3B5DA;
}
p {
height: 20px;
font-weight: bold;
color: #FFFFFF;
margin-top: 18px;
}
}
.right {
position: relative;
cursor: pointer;
margin-top: 9px;
margin-right: 10px;
.right-img {
width: 34px;
height: 33px;
img {
width: 100%;
height: 100%;
}
}
.right-tips {
display: none;
position: absolute;
top: 45px;
left: -20px;
width: 313px;
height: 82px;
padding: 20px;
box-sizing: border-box;
background: #1A1821;
box-shadow: 0px 15px 28px 3px rgba(22,22,22,0.13);
border-radius: 10px;
border: 1px solid #B966FF;
}
&:hover {
.right-tips {
display: block;
}
}
}
}
}
&:nth-child(2) {
padding-top: 20px;
}
}
}
}
</style>