802 lines
24 KiB
Vue
802 lines
24 KiB
Vue
<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: <StarTimer :getAddress="detailData.event.data.end_at" /></div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<div class="price">
|
|
<span class="bold">{{ price }} </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(detailData.value,contractBlankUrl.value,import.meta.env.VUE_APP_NET_ID,import.meta.env.VUE_APP_GPAL_API,`${import.meta.env.VUE_APP_EXPLORER_URL}${data.nft.contract_address}`,'----')
|
|
}
|
|
|
|
onMounted(() => {
|
|
getDetail()
|
|
})
|
|
</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> |