增加测试第三阶段宝箱开启页面

This commit is contained in:
cebgcontract 2022-06-24 12:53:46 +08:00
parent 41ca281b72
commit 254bc28db7
5 changed files with 743 additions and 0 deletions

View File

@ -75,3 +75,24 @@ export const queryActivateNFTState = (data: any) =>
method: 'get',
params: data
})
export const getPhase3Box = (data: any) =>
request({
url: '/webapp/index.php?c=Market&a=getPhase3box',
method: 'get',
params: data
})
export const openPhase3Box = (data: any) =>
request({
url: '/webapp/index.php?c=Market&a=openPhase3Box',
method: 'get',
params: data
})
export const queryPhase3Box = (data: any) =>
request({
url: '/webapp/index.php?c=Market&a=queryPhase3Box',
method: 'get',
params: data
})

View File

@ -31,6 +31,12 @@
<div class="active-bottom" v-if="currentTab==='mystery'"></div>
</div>
</a>
<a class="menu-item" href="/eventreward" >
<div class="item " :class="{'active': currentTab==='reward'}">
EventReward
<div class="active-bottom" v-if="currentTab==='reward'"></div>
</div>
</a>
<a class="menu-item" href="/mynft" v-if="logined" >
<div class="item " :class="{'active': currentTab==='mynft'}">
MyNFT

View File

@ -0,0 +1,73 @@
<template>
<div
class="one-box"
@mouseover="boxOver"
@mouseout="boxNormal"
@click="onOpenBox"
>
<div class="nft-id">#{{tokenId}}</div>
<img class="box-img" :src="currentImg" alt="mystery boxes">
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import { UserModule } from '@/store/modules/user'
import { AppModule } from '@/store/modules/app'
export const REWARD_BOX_CLICKED = 'reward-box-clicked'
@Component({
name: 'OneRewardBox',
components: {
}
})
export default class OneRewardBox extends Vue {
@Prop() tokenId: string | number
@Prop() normalImg: string
@Prop() highImg: string
boxState = 'n'
boxOver() {
if (this.boxState !== 'o') {
this.boxState = 'h'
}
}
boxNormal() {
if (this.boxState !== 'o') {
this.boxState = 'n'
}
}
onOpenBox() {
this.$emit(REWARD_BOX_CLICKED, this.tokenId)
}
get isLogin() {
return !!UserModule.token && !!AppModule.step
}
get currentImg() {
return this.boxState === 'n'
? this.normalImg : this.highImg
}
}
</script>
<style lang="scss" scoped>
.one-box{
width: 14em;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
.nft-id {
color: #46E0F4;
display: unset;
width: 100%;
margin-bottom: 5px;
text-align: center;
}
.box-img{
width: 14em;
}
}
</style>

View File

@ -58,6 +58,14 @@ const routes: Array<RouteConfig> = [
title: 'Mystery Boxes | CEBG: CRYPTO ELITES BATTLEGROUNDS'
}
},
{
path: '/eventreward',
name: 'EventReward',
component: resolve => require(['@/views/desktop/EventReward.vue'], resolve),
meta: {
title: 'Event Reward | CEBG: CRYPTO ELITES BATTLEGROUNDS'
}
},
{
path: '/presale',
name: 'Presale',

View File

@ -0,0 +1,635 @@
<template>
<div>
<top-menu class="desk-top" :current-tab="currentTab"></top-menu>
<section class="root">
<div class="container">
<div class="box-info">
<div class="info-title">{{presaleTitle}}</div>
<div class="info-desc" v-html="hint">
</div>
</div>
<div class="detail-info-bar" v-if="false">
<div class="detailBox">
<div class="circle">
<img src="@/assets/market/key_120.png" alt="key">
</div>
<div class="content">
<span class="info">Mystery Key</span>
<span class="title">{{countShow}}</span>
</div>
</div>
</div>
<div class="card-list" v-if="nftList.length > 0">
<one-reward-box
v-for="nft in nftList"
:token-id="nft.id"
:normal-img = "nft.normalImg"
:high-img = "nft.highImg"
:key="nft.id"
@reward-box-clicked = "onClickBox"
></one-reward-box>
</div>
<result-no
v-if="nftList.length === 0"
title="You have no Event Reward."
desc=""
></result-no>
<pagination
v-if="totalPage>1"
:total="totalPage"
:current="currentPage"
@to-page="toPage"
class="page-comp"
></pagination>
</div>
<div class="order-status" v-show="showOrderStatus">
<el-tooltip class="item" effect="light" content="Transaction in progress" placement="right">
<time-loader></time-loader>
</el-tooltip>
</div>
</section>
<base-footer :auto-size="true">></base-footer>
</div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import TopMenu from '@/components/market/TopMenu.vue'
import BaseFooter from '@/components/layout/BaseFooter.vue'
import OneBox from '@/components/market/mall/OneBox.vue'
import { UserModule } from '@/store/modules/user'
import { AppModule } from '@/store/modules/app'
import ChainManager from '@/chain/ChainManager'
import { secs2str } from '@/utils/time.util'
import { ElLoadingComponent } from 'element-ui/types/loading'
import TimeLoader from '@/components/main/TimeLoader.vue'
import Pagination from '@/components/market/Pagination.vue'
import ResultNo from '@/components/market/ResultNo.vue'
import { CONTRACT_ADDRESS } from '@/configs/config_chain'
import OneLuckyBox from '@/components/market/mystery/OneLuckyBox.vue'
import { getPhase3Box, openPhase3Box, queryPhase3Box } from '@/api/Market'
import RewardModal from '@/components/core/RewardModal.vue'
import { INftData, parseNftData } from '@/types/Nft'
import { createModal, ZModal } from '@/utils/modal.util'
import OneRewardBox from '@/components/market/mystery/OneRewardBox.vue'
const PAGE_SIZE = 8
const MYSTERY_BOX_CACHE = 'reward_box_cache'
@Component({
components: {
OneRewardBox,
RewardModal,
OneLuckyBox,
ResultNo,
Pagination,
TimeLoader,
OneBox,
BaseFooter,
TopMenu
}
})
export default class EventReward extends Vue {
currentTab = 'reward';
hint = 'The box can only draw one of the following rewards.<br/>' +
'- 1 Hero, 3% chance<br/>' +
'- 1 Weapon, 5% chance<br/>' +
'- 1 Chip, 7% chance<br/>' +
'- 25 GCEC, 20% chance<br/>' +
'- 20 GCEC, 30% chance<br/>' +
'- 15 GCEC, 35% chance<br/>' +
'Validity period 2023/6/30';
presaleTitle = 'Phase 3 Rewards During the Test'
presaleStatus = 0
timeStr = 'UNLIMITED'
countdown = 0
orderTimer: any = null
loadingInstance: ElLoadingComponent
showOrderStatus = false
historyOrderId: string | null = ''
chainManager = new ChainManager()
totalCount = 0
private totalPage = 1
private currentPage = 1
private nftList: {id: string, normalImg: string, highImg: string}[] = []
private isProcess = false
private rewardModal: ZModal
created() {
if (!process.env.VUE_APP_PART_CLOSE) {
this.fetchData()
}
this.chainManager.init()
}
mounted() {
this.checkOrderHistory()
// this.showTestModal()
// if (process.env.NODE_ENV === 'development') {
// window.showModal = this.showTestModal
// }
}
unmounted() {
this.rewardModal?.destroy()
}
private resetData() {
this.totalPage = 1
this.currentPage = 1
this.nftList.length = 0
this.$forceUpdate()
}
@Watch('isLogin')
private async accountChange() {
if (this.isLogin) {
this.checkOrderHistory()
await this.getNftList()
} else {
this.resetData()
}
}
@Watch('countdown')
private countDownChange() {
this.timeStr = secs2str(this.countdown)
}
get countShow() {
if (!this.isLogin) {
return 'UNAVAILABLE'
}
return 'x 0'
}
get accountId() {
return AppModule.accountId
}
get isLogin() {
return !!UserModule.token && !!AppModule.step && AppModule.accountId
}
get boxAddress() {
return CONTRACT_ADDRESS[AppModule.chainId].mystery
}
get boxProxyAddress() {
return CONTRACT_ADDRESS[AppModule.chainId].mysteryProxy
}
async fetchData() {
console.log('Mystery fetchData')
}
showLoading() {
this.loadingInstance = this.$loading({ background: 'rgba(0, 0, 0, 0.8)' })
}
hideLoading() {
this.loadingInstance?.close()
}
async getNftList() {
this.showLoading()
this.nftList.length = 0
try {
const records: any = await getPhase3Box({
account: this.accountId
})
console.log(records)
if (records.rows.length > 0) {
records.rows.forEach((o: any) => {
this.nftList.push({
id: o.box_id,
normalImg: o.image_box_1,
highImg: o.image_box_2
})
})
// for (let i = 0; i < 10; i++) {
// this.nftList.push({
// id: '22' + i,
// normalImg: this.nftList[0].normalImg,
// highImg: this.nftList[0].highImg
// })
// }
}
} catch (err) {
console.log(err)
}
this.hideLoading()
}
checkOrderHistory() {
const historyOrderId = localStorage.getItem(MYSTERY_BOX_CACHE)
if (historyOrderId && this.accountId) {
try {
const data = JSON.parse(historyOrderId)
this.beginTraceOrderStatus(data)
} catch (err) {
localStorage.removeItem(MYSTERY_BOX_CACHE)
}
}
}
beginTraceOrderStatus(cacheData: any) {
this.showOrderStatus = true
this.isProcess = true
this.loadingInstance?.close()
this.orderTimer = setInterval(() => {
this.getOrderStatus(cacheData)
}, 1000)
}
resetTmpOrderId() {
if (this.orderTimer !== null) {
clearInterval(this.orderTimer)
this.orderTimer = null
}
this.isProcess = false
localStorage.removeItem(MYSTERY_BOX_CACHE)
this.loadingInstance?.close()
}
async onClickBox(tokenId: string) {
if (!this.isLogin) {
this.$message({
message: 'You should login first',
type: 'warning',
duration: 5 * 1000
})
return
}
if (this.isProcess) {
this.$message({
message: 'Box open in process',
type: 'warning',
duration: 5 * 1000
})
return
}
this.isProcess = true
this.showLoading()
try {
const res : any = await openPhase3Box({
account: this.accountId,
box_id: tokenId
})
const stateData = { token_id: tokenId }
localStorage.setItem(MYSTERY_BOX_CACHE, JSON.stringify(stateData))
this.hideLoading()
this.beginTraceOrderStatus(stateData)
} catch (err) {
console.log('pre open box err', err)
this.$message.error('open reward box with pre open error')
this.hideLoading()
this.isProcess = false
return false
}
}
async getOrderStatus(data: any) {
console.log('getOrderStatus: ', data)
try {
const res: any = await queryPhase3Box(data)
if (res.state === 1) {
// success
const nfts: any = res.nfts || []
if (res.cec) {
nfts.unshift(this.generateCECData('GCEC', res.cec, ''))
}
this.onOpenSuccess(nfts)
}
} catch (err) {
console.log('query order status error', err)
}
}
async onOpenSuccess(nfts: any) {
console.log('open success')
this.resetTmpOrderId()
this.showOrderStatus = false
const cardList: INftData[] = []
for (const data of nfts) {
const nftData = parseNftData(data)
cardList.push(nftData)
}
this.showRewardModal({
title: 'Open Mystery Box Success',
cec: '',
cardList
})
this.getNftList()
// this.$alert('Congratulations', 'Open Success', { type: 'success', confirmButtonText: 'OK' })
}
showRewardModal(data: any) {
console.log('show reward modal with data: ', data)
this.rewardModal = createModal(RewardModal, data)
this.rewardModal.show()
}
toPage(pageNo: number) {
console.log('to page: ', pageNo)
this.currentPage = pageNo
this.getNftList()
}
generateCECData(name: string, amount: number, image: string) {
return {
token_id: name,
owner_address: '0x42448c6a38c08637218d8327b748f213fc2c0231',
owner_name: '',
item_id: '30600',
type: '2',
state: '0',
hide_attr: 1,
is_genesis: false,
image: image,
currency_list: [],
transaction_recrod: [],
info:
{
name: `${name} X ${amount}`,
attr: [],
job: 1,
level: 1,
quality: 1,
hp: 200,
speed: 6,
atk: 32,
def: 7,
advanced_count: 0,
lucky: 0,
success_rate: 0
},
mint_time: '1650529475'
}
}
// showTestModal() {
// const nftList = [
// {
// token_id: '501007316776010040',
// owner_address: '0x42448c6a38c08637218d8327b748f213fc2c0231',
// owner_name: '',
// item_id: '30100',
// type: '1',
// state: '0',
// hide_attr: 1,
// is_genesis: false,
// image: 'https://www.cebg.games/res/avatars/30100.png',
// currency_list: [],
// transaction_recrod: [],
// info:
// {
// name: 'Hill',
// attr: [],
// job: 1,
// level: 1,
// quality: 1,
// hp: 195,
// speed: 6,
// atk: 35,
// def: 6,
// advanced_count: 0,
// lucky: 0,
// success_rate: 0
// },
// mint_time: '1650529592'
// },
// {
// token_id: '501007319181010046',
// owner_address: '0x42448c6a38c08637218d8327b748f213fc2c0231',
// owner_name: '',
// item_id: '30300',
// type: '1',
// state: '0',
// hide_attr: 1,
// is_genesis: true,
// image: 'https://www.cebg.games/res/avatars/30300_1.png',
// currency_list: [],
// transaction_recrod: [],
// info:
// {
// name: 'Aoi',
// attr: [],
// job: 3,
// level: 1,
// quality: 1,
// hp: 120,
// speed: 5,
// atk: 20,
// def: 10,
// advanced_count: 0,
// lucky: 0,
// success_rate: 0
// },
// mint_time: '1650531993'
// }]
// nftList.unshift(this.generateCECData('GCEC', 20, 'https://www.cebg.games/img/cec.e9eb8837.png'))
// const cardList: INftData[] = []
// nftList.forEach(o => cardList.push(parseNftData(o)))
// const data = {
// title: 'Test data',
// cardList
// }
// this.showRewardModal(data)
// }
}
</script>
<style lang="scss" scoped>
@import '../../scss/breakpoints.scss';
.root {
display: flex;
flex-direction: column;
align-items: center;
.container {
display: flex;
flex-direction: column;
width: 1440px;
max-width: 100%;
box-sizing: border-box;
align-items: center;
.box-info {
width: 100%;
color: white;
display: flex;
flex-direction: column;
align-items: center;
.info-title {
font-size: 50px;
padding: 60px 20px 20px 20px;
color: #FFA81E;
}
}
}
}
.card-list {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: row;
flex-wrap: wrap;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
display: flex;
column-gap: 1.875em;
row-gap: 1.3125em;
margin: 50px 10vw;
font-size: 16px;
}
.detail-info-bar {
width: toEm(969px);
max-width: 100%;
height: toEm(93px);
margin-top: toEm(32px);
display: flex;
justify-content: center;
gap: 50px;
.detailBox {
width: toEm(302px);
border-radius: toEm(8px);
padding: 0 toEm(36px);
box-sizing: border-box;
display: flex;
align-items: center;
background: rgba(4, 4, 34, 0.56);
transform: matrix(0.98, 0, -0.19, 1, 0, 0);
.circle {
width: toEm(57px);
height: toEm(57px);
margin-right: toEm(24px);
transform: skewX(11deg);
background-color: #FFA81E;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
img{
width: 80%;
height: 80%;
}
}
.content {
display: flex;
flex-direction: column;
transform: skewX(11deg);
.title {
font-style: normal;
text-transform: uppercase;
font-size: toEm(14px);
line-height: 1.57;
color: #c9c5db;
}
.info {
font-style: normal;
font-weight: bold;
font-size: toEm(24px);
line-height: 1.25;
text-transform: uppercase;
color: #ffffff;
margin-bottom: toEm(8px);
display: flex;
flex-direction: row;
align-items: center;
.total {
color: #8a8ab2;
}
}
.timeUp {
color: #ff5c5c;
}
.unavailableTime {
font-size: 1.125em;
text-transform: none;
}
}
}
}
.order-status {
transform: scale(0.3);
width: 220px;
height: 220px;
border-radius: 110px;
background: white;
display: flex;
justify-content: center;
align-items: center;
transform-origin: top;
position: fixed;
left: 100px;
top: 100px;
}
@include media('<wide') {
.root {
font-size: 11px;
.container {
width: 1024px;
max-width: 100%;
.card-list{
font-size: 15px;
}
}
}
}
@include media('<desktop') {
.root {
font-size: 20px;
.container {
width: 768px;
flex-direction: column;
.card-list {
-ms-grid-columns: (1fr)[2];
grid-template-columns: repeat(2, 1fr);
}
}
}
}
@include media('<tablet') {
.root {
font-size: 11px;
.container {
width: 375px;
padding-top: 80px;
.card-list{
display: flex;
flex-direction: column;
align-items: center;
}
}
}
}
@include media('<phone') {
.root {
font-size: 9px;
}
}
</style>
<style lang="scss">
.circle {
rect {
fill: #FFA81E;
}
path {
fill: white;
}
}
</style>