fix
4
.env.dev
Normal file
@ -0,0 +1,4 @@
|
||||
VUE_APP_BASE_API='https://market.cebg.games'
|
||||
VUE_APP_BASE_API2='https://invitation.counterfire.games'
|
||||
//VUE_APP_BASE_API2='http://192.168.100.83:3000/'
|
||||
VUE_APP_GPAL_API='https://gacha.counterfire.games'
|
2
.env.development
Normal file
@ -0,0 +1,2 @@
|
||||
VUE_APP_BASE_API='https://market.cebg.games'
|
||||
VUE_APP_GPAL_API='http://192.168.100.83:4000/sns'
|
3
.env.production
Normal file
@ -0,0 +1,3 @@
|
||||
VUE_APP_BASE_API='https://market.cebg.games'
|
||||
VUE_APP_BASE_API2='https://invitation.counterfire.games'
|
||||
VUE_APP_GPAL_API='https://gacha.counterfire.games'
|
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
|
6
README.txt
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
build command:
|
||||
|
||||
export NODE_OPTIONS=--max_old_space_size=8192
|
||||
npm run build:prod
|
||||
|
58
index.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/logo.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Planet</title>
|
||||
<meta property="og:title" content="Gacha" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Gacha.counterFire.games | Gacha is blinking! Quest and Rewards.Join Counter Fire and Rise of Gacha. Get your gacha and rewards. A new evolution about Web3Gaming."
|
||||
/>
|
||||
<meta
|
||||
name="description"
|
||||
content="Gacha.counterFire.games | Gacha is blinking! Quest and Rewards.Join Counter Fire and Rise of Gacha. Get your gacha and rewards. A new evolution about Web3Gaming."
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="CounterFire;CF;Gamefi;Web3;web3gaming; Cf game;Cf mobile; CounterFire googleplay; CounterFire Appstore;
|
||||
battle royale;token;airdrop;p2e; play to earn, free to play, blockchain game;Arbitrum game;Arbitrum. Cryptocurrency; Crypto;anime game;anime web3 game;Two-dimensional game;shooting game;Anime shooting mobile game"
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://gacha.counterfire.games/" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://gacha.counterfire.games/images/counter.png"
|
||||
/>
|
||||
<!-- <meta property="og:site_name" content="Counter Fire" /> -->
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:title" content="Gacha" />
|
||||
<meta
|
||||
property="twitter:image"
|
||||
content="https://gacha.counterfire.games/images/counter.png"
|
||||
/>
|
||||
</head>
|
||||
<script type="module">
|
||||
import { Buffer } from "buffer";
|
||||
window.Buffer = Buffer;
|
||||
</script>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script
|
||||
async
|
||||
src="https://www.googletagmanager.com/gtag/js?id=G-9WFW3HQTR8"
|
||||
></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag("js", new Date());
|
||||
|
||||
gtag("config", "G-9WFW3HQTR8");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
24957
package-lock.json
generated
Normal file
62
package.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "my-vue-app",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite --host --mode dev",
|
||||
"build:dev": "vite build --mode dev",
|
||||
"build:test": "vite build --mode test",
|
||||
"build:prod": "vite build --mode production"
|
||||
},
|
||||
"dependencies": {
|
||||
"@animxyz/core": "^0.6.6",
|
||||
"@animxyz/vue3": "^0.6.7",
|
||||
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
||||
"@metamask/safe-event-emitter": "^2.0.0",
|
||||
"@vue/runtime-dom": "^3.2.47",
|
||||
"@vueuse/core": "^9.12.0",
|
||||
"@walletconnect/web3-provider": "^1.8.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"ant-design-vue": "^3.2.15",
|
||||
"axios": "^1.3.3",
|
||||
"buffer": "^6.0.3",
|
||||
"gsap": "^3.11.5",
|
||||
"js-cookie": "^3.0.1",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.0.30",
|
||||
"postcss-px-to-viewport": "^1.1.1",
|
||||
"prerender-spa-plugin-next": "^4.2.3",
|
||||
"process": "^0.11.10",
|
||||
"rollup-plugin-polyfill-node": "^0.12.0",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"swiper": "8",
|
||||
"util": "^0.12.5",
|
||||
"uuid": "^9.0.0",
|
||||
"video.js": "^8.0.4",
|
||||
"videojs-flash": "^2.2.1",
|
||||
"vite-plugin-pages": "^0.31.0",
|
||||
"vite-plugin-ssr": "^0.4.132",
|
||||
"vite-ssg": "^0.22.2",
|
||||
"vue": "^3.2.45",
|
||||
"vue-3d-loader": "^2.1.5",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue3-autocounter": "^1.0.6",
|
||||
"vue3-clipboard": "^1.0.0",
|
||||
"web3": "^1.8.2",
|
||||
"youtube-player": "^5.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "^2.8.4",
|
||||
"sass": "^1.58.1",
|
||||
"tailwindcss": "^3.3.1",
|
||||
"terser": "^5.16.3",
|
||||
"vite": "^4.1.0",
|
||||
"vite-plugin-prerender": "^1.0.8",
|
||||
"vite-plugin-require-transform": "^1.0.9"
|
||||
}
|
||||
}
|
24
postcss.config.cjs
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'postcss-px-to-viewport': {
|
||||
unitToConvert: 'px', // 需要转换的单位,默认为"px"
|
||||
viewportWidth: 1920, // 设计稿的视口宽度
|
||||
unitPrecision: 5, // 单位转换后保留的精度
|
||||
propList: ['*'], // 能转化为vw的属性列表
|
||||
viewportUnit: 'vw', // 希望使用的视口单位
|
||||
fontViewportUnit: 'vw', // 字体使用的视口单位
|
||||
selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
|
||||
minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
|
||||
mediaQuery: false, // 媒体查询里的单位是否需要转换单位
|
||||
replace: true, // 是否直接更换属性值,而不添加备用属性
|
||||
exclude: undefined, // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
|
||||
include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换
|
||||
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
|
||||
landscapeUnit: 'vw', // 横屏时使用的单位
|
||||
landscapeWidth: 1920 // 横屏时使用的视口宽度
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
public/images/counter.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
public/logo.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
70
src/App.vue
Normal file
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<Layout></Layout>
|
||||
<Notification :position="'top-right'" :duration="3000" ref="notification" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, watch, reactive ,provide} from "vue";
|
||||
import Layout from "@/components/layout/index.vue";
|
||||
import Notification from './components/global/Notification.vue'
|
||||
import { gsap } from "gsap";
|
||||
|
||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
const notification = ref(null);
|
||||
|
||||
// 在根组件的 setup 函数中,将 addNotification 函数提供给子组件
|
||||
provide('addNotification', (title, message) => {
|
||||
notification.value.addNotification(title, message);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
body,
|
||||
html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
font-family: "ui-sans-serif", "system-ui", "-apple-system",
|
||||
"BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial",
|
||||
"Noto Sans", "sans-serif", "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol", "Noto Color Emoji";
|
||||
audio,
|
||||
canvas,
|
||||
embed,
|
||||
iframe,
|
||||
img,
|
||||
object,
|
||||
svg,
|
||||
video {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
img,
|
||||
video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "MyFont";
|
||||
src: url("/fonts/myfont.ttf") format("truetype");
|
||||
}
|
||||
#app{
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
104
src/api/User.js
Normal file
@ -0,0 +1,104 @@
|
||||
import request from '@/utils/request'
|
||||
import request2 from '@/utils/requestduplicate'
|
||||
|
||||
|
||||
const GPAL_URL = import.meta.env.VUE_APP_GPAL_API;
|
||||
|
||||
export const defaultUser = {
|
||||
id: '',
|
||||
username: '',
|
||||
showname: '',
|
||||
comment: '',
|
||||
locked: false,
|
||||
password: '',
|
||||
avatar: '',
|
||||
account: ''
|
||||
}
|
||||
/**
|
||||
* @param data {account: string, token: string}
|
||||
*/
|
||||
export const getUserInfo = (data) =>
|
||||
request({
|
||||
url: '/webapp/index.php?c=BcUser&a=info',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
|
||||
export const login = (data) =>
|
||||
request({
|
||||
url: '/webapp/index.php?c=Market&a=auth',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
|
||||
export const logout = () =>
|
||||
request({
|
||||
url: '/api/user/logout',
|
||||
method: 'post'
|
||||
})
|
||||
|
||||
export const beginclaim = (data) => {
|
||||
return request2({
|
||||
url: '/aa2/beginClaim',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const Claim=(data)=>{
|
||||
return request2({
|
||||
url: '/aa2/claim',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export const UserStatus=(data)=>{
|
||||
return request2({
|
||||
url: '/aa2/user_status',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export const getLeaderboard=(data)=>{
|
||||
return request2({
|
||||
url: '/aa2/leaderboard',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export const UserInfo=(data)=>{
|
||||
return request2({
|
||||
url: '/aa2/user_info',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export const totalClaimed=(data)=>{
|
||||
return request2({
|
||||
url: '/aa2/totalClaimed',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export const getJoin=(data)=>{
|
||||
return request2({
|
||||
url: '/aa2/join',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//
|
||||
// export const changePass = (params: any) =>
|
||||
// request({
|
||||
// url: '/api/user/passwd',
|
||||
// method: 'post',
|
||||
// data: params
|
||||
// })
|
||||
|
||||
export const getNonce = (params) =>
|
||||
|
||||
request({
|
||||
url: '/webapp/index.php?c=Market&a=getNonce',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
349
src/assets/css/normalize.css
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
BIN
src/assets/img/planet/AppStore_icon.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
src/assets/img/planet/CFunivers_bg.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
src/assets/img/planet/GooglePlay_icon.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
src/assets/img/planet/com_Discord_icon.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
src/assets/img/planet/com_Twitter_icon.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
src/assets/img/planet/com_Youtube_icon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/img/planet/footer-logo.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
src/assets/img/planet/header-logo.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
src/assets/img/planet/investors.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
src/assets/img/planet/logo.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
src/assets/img/planet/planet_banner.png
Normal file
After Width: | Height: | Size: 2.3 MiB |
BIN
src/assets/img/planet/planet_btnBg.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/img/planet/planet_card01.png
Normal file
After Width: | Height: | Size: 275 KiB |
BIN
src/assets/img/planet/planet_card02.png
Normal file
After Width: | Height: | Size: 279 KiB |
BIN
src/assets/img/planet/planet_card03.png
Normal file
After Width: | Height: | Size: 272 KiB |
BIN
src/assets/img/planet/planet_title.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
src/assets/img/planet/wallet_icon.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
1
src/assets/svg/android.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1677464048404" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5219" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M911.020879 320.237361c-36.202548 0-66.192962 28.664228-66.192962 63.470791V630.54159c0 34.806563 28.966692 63.494057 66.192962 63.494057 36.179281 0 66.169695-28.687495 66.169695-63.517323V383.731418c-1.023722-34.806563-29.990414-63.470791-66.169695-63.47079z m-798.317365 0C76.547499 320.237361 46.533818 348.901589 46.533818 383.684885V630.54159c0 34.806563 28.943425 63.494057 66.169696 63.494057 37.22627 0 66.192962-28.687495 66.192961-63.517323V383.731418c0-34.806563-28.966692-63.470791-66.192961-63.47079z m106.513665 2.047445v451.601191c0 26.616783 22.754558 49.138677 51.697983 49.138677h58.957106v137.225338c0 34.829829 28.943425 63.494057 66.169695 63.494057 36.202548 0 66.192962-28.664228 66.192962-63.494057v-137.225338h103.395965v137.225338c0 34.829829 28.966692 63.494057 66.192962 63.494057C667.979867 1023.744069 697.993547 995.079841 697.993547 960.250012v-137.225338h58.933839c28.966692 0 51.721249-21.498171 51.72125-49.138677V322.26154H219.217179zM651.46071 88.783026L706.276393 15.051744c2.047445-5.118612 2.047445-11.260947-3.117701-13.308391-4.141423-3.071167-10.33029-1.023722-13.44799 3.071167l-55.839405 76.802449A363.142266 363.142266 0 0 0 511.862196 60.118798c-43.438404 0-84.78283 7.166057-122.009101 21.498171l-55.839405-76.779183c-3.1177-5.118612-9.306568-6.165601-13.44799-3.094433a9.655564 9.655564 0 0 0-2.093978 13.308391l54.815683 73.754548c-85.806553 37.87773-146.811103 109.561567-154.070226 193.530073h588.407734c-9.306568-83.991772-69.310662-155.652342-156.164203-193.553339zM387.782384 205.533916c-18.613135 0-32.061125-13.308392-32.061125-30.711673 0-17.426548 14.471713-30.711673 32.061125-30.711673 18.613135 0 32.037859 13.285125 32.037859 30.711673 0 17.403281-14.471713 30.711673-32.037859 30.711673z m252.301047 0c-18.613135 0-32.061125-13.308392-32.061125-30.711673 0-17.426548 14.494979-30.711673 32.061125-30.711673 18.613135 0 32.061125 13.285125 32.061125 30.711673 0 17.403281-14.471713 30.711673-32.061125 30.711673z" fill="#6E7580" p-id="5220"></path></svg>
|
After Width: | Height: | Size: 2.3 KiB |
1
src/assets/svg/apple.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1677464028670" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4201" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M836.608 675.84q41.984 59.392 96.256 76.8-23.552 72.704-74.752 151.552-78.848 118.784-155.648 118.784-28.672 0-84.992-19.456-52.224-19.456-91.136-19.456t-86.016 20.48q-49.152 19.456-80.896 19.456-92.16 0-181.248-156.672-89.088-154.624-89.088-304.128 0-138.24 67.584-226.304 69.632-88.064 172.032-88.064 22.528 0 50.176 5.632t57.344 20.992q31.744 17.408 52.224 24.064t31.744 6.656q13.312 0 40.96-6.144t55.296-22.528q29.696-16.384 51.2-24.576t44.032-8.192q71.68 0 129.024 38.912 30.72 20.48 62.464 60.416-47.104 40.96-68.608 71.68-39.936 57.344-39.936 124.928 0 74.752 41.984 135.168zM630.784 197.632q-35.84 33.792-65.536 44.032-10.24 3.072-26.112 5.632t-36.352 4.608q1.024-90.112 47.104-155.648t151.552-90.112q2.048 10.24 3.072 14.336l0 11.264q0 36.864-17.408 82.944-18.432 45.056-56.32 82.944z" fill="#272636" p-id="4202"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
11
src/assets/svg/btn.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="100" height="40">
|
||||
<rect x="0" y="0" width="100" height="40" fill="#0080ff" />
|
||||
<rect x="25" y="10" width="50" height="20" fill="#ff4d4d" opacity="0">
|
||||
<animate attributeName="opacity" from="0" to="1" begin="mouseover" dur="0.2s" fill="freeze" />
|
||||
<animate attributeName="width" from="0" to="50" begin="mouseover" dur="0.2s" fill="freeze" />
|
||||
<animate attributeName="height" from="0" to="20" begin="mouseover" dur="0.2s" fill="freeze" />
|
||||
<animate attributeName="x" from="50" to="25" begin="mouseover" dur="0.2s" fill="freeze" />
|
||||
<animate attributeName="y" from="15" to="10" begin="mouseover" dur="0.2s" fill="freeze" />
|
||||
</rect>
|
||||
<text x="50" y="24" text-anchor="middle" fill="#fff" font-size="16">按钮</text>
|
||||
</svg>
|
After Width: | Height: | Size: 772 B |
19
src/assets/svg/checkmark-active.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 29 28" style="enable-background:new 0 0 29 28;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#60FF00;}
|
||||
.st1{fill:#030000;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M8.49,23.9L8.49,23.9c-0.59-0.59-0.59-1.54,0-2.12L26.17,4.1c0.59-0.59,1.54-0.59,2.12,0l0,0
|
||||
c0.59,0.59,0.59,1.54,0,2.12L10.61,23.9C10.03,24.49,9.08,24.49,8.49,23.9z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st0" d="M0.71,14L0.71,14c0.59-0.59,1.54-0.59,2.12,0l7.78,7.78c0.59,0.59,0.59,1.54,0,2.12l0,0
|
||||
c-0.59,0.59-1.54,0.59-2.12,0l-7.78-7.78C0.13,15.54,0.13,14.59,0.71,14z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 836 B |
19
src/assets/svg/checkmark.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 29 28" style="enable-background:new 0 0 29 28;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#60FF00;}
|
||||
.st1{fill:#030000;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M8.49,23.9L8.49,23.9c-0.59-0.59-0.59-1.54,0-2.12L26.17,4.1c0.59-0.59,1.54-0.59,2.12,0l0,0
|
||||
c0.59,0.59,0.59,1.54,0,2.12L10.61,23.9C10.03,24.49,9.08,24.49,8.49,23.9z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M0.71,14L0.71,14c0.59-0.59,1.54-0.59,2.12,0l7.78,7.78c0.59,0.59,0.59,1.54,0,2.12l0,0
|
||||
c-0.59,0.59-1.54,0.59-2.12,0l-7.78-7.78C0.13,15.54,0.13,14.59,0.71,14z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 836 B |
1
src/assets/svg/chip-icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48"><image width="46" height="45" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAtCAYAAADRLVmZAAAH1klEQVRogeXZeaweZRUG8F8FhBYI Q1WUCAKJKIgsslnAqhUomwRaEBSVAsHBDo0FyiYqCiotVNlKRxhZLYvKUhCXAmURRfaCytoihJKg INCBUmmKpf5xZvJNP+Zu7f3Pk3y5911m3ud955znPGdmCKzzjfEG2YbhVHwVr+A8XN7T5LLIB7zA qisIrDf7JC7ELlV7A1yGHXE8/jMYi7xnMG7SsCNxpw7opo3H7dhpMBYaLOBr4QL8HO/vZd4IzMY3 V3bBwQC+HW7F0S1jy6pf04bhZ8KdkhVddGWBH6798T+BWY327/Bo15yjcId4CgO2FQX+AVyES7FO 19iT+CJuwJDqNxNj8c+uuZ/CbUmaTRgogBUBvqM4zbRl7Hl8Cc9h3Ub/hlXfAXip65q1MC1JsyuS NHtff0EMFPh4EVzbtozNxR54vGo3gQ+r/t6L3cQmuu1Q3JmkWRsjvcv6C/yDuBY51m4Zn4PReLpq H4FJwq/n4lsYV409Jjb4tHfblsJ1Jg0G8JGCNQ7sYfyOCvTz1f2m4BK8iL2xD14VmfPH1Zx54uTv 9W7WGYqfJGk2I0mzHqm1L+Dfxh+wVQ/jz2ECloiMeQNOEgH6WRGMz1T/P4NTcJM42YXIqk202ddw d5Jmu7YNDqFVq6yP6RhTtZdilZbrF+FfWE0E2XD8WrjKoq65CX6BffFa9VsmJMHQHsATh3JqWeRn NjvbtMq+OAubNfr+holYrBN0y/Bf4a8nNeY+0gIaSuFW+1YbHF71T8LDWL0xd0G1ztnYAlOSNNse J5VF/izLn/gQfLf6vbdl12cKxddm++EKHU4vcFxjA6vjR8I1aoZ5FYfg1jZ1mKTZedX85uHOxcSy yGfVwNfDNBzUA7DabhLs8HrL2La4DptU7b8IWbtEuEjTV+cJvv8ry8vaJM2G45fYvQcMS/GDOjg3 7Qdo4mRvxHotY3OE28yp2jvjLtzTBfoe7FWDblqSZhuJAO8JNBFrJ9bAH8IZ/QAOn69u3gZ+ngjo P1XtjbBxY3yWyJ7/aAG9sQjsz/Wx/ss4uptVxgiX+XCf8COR7IdnW8bWxQzB4bXdLJ7q4pb5H8dv 8LE+1rwLR5VFPrebx2cK4XNLn7CDt2/H1i1jC0SWbdo07aB3EmzTF+ipZZGPKot8LstH7B4im52A PXE6vqP3JLWx2OyBOr5dW7c06FaRhC9fIfJGT/YCji6L/OYkzbbBYZheg9oK14ua8F58QlDffiKV 92abVOC7NflqXe3unLGnYI/eQM/GLhXocVV7Iq6qgS/R4dwRuF9UNL/FDoIGe7OPiGJhdKOv+0kN afw/VhzUcO22FKeURb47Xk7S7EqhdWrZ+2Z986fwBUFVdGrIAm9gf+E2S3sBv67YaE2rZdd47d+p 4Pth2u05jCqLfHKSZjvgzyIf1DYd+3ezyqr4qZChtT0qyqwHxOOdho/2soHFYqNv4Y9V39viSW6g 96c3ExPKIn8xSbNjRZytVY29hmPKIp/B8o9zFVGhTxRZ7dWqfxvBy6ng4Z0Ej/dkawg3OB3vVH1L Rcxc2st1x5VFPhYLkzS7XOiUGvQ9GFkW+YwkzTako1XWFm+bRuNkXCn89mLLZ7FrhO8vEOxzmt6V 3TLL+3abPY6sLPK7kzQbhfMF1dZ2dlnkkyBJswtErjmrBr6zjn/DOUIkweRqM7U9KSjpAVFkXChY aEVsRgX6zSTNjhFFSK0SXxGucVWSZptU69TB/3rtKk+KQKztWEGLm4liYoxOhb65cJ3jq78jRKoe iC3GMaLOXCNJs+vFYdWg78CICvTBQpLUoBfhezXwBSIAJ+oovxFC4R0hhNW2+H019l5MrdrDcLCo hN7oB+g54kmdJ8TWg4Iea5tSFvmumJ+k2bmC64c3rh1dFvm0VWCN7XaoL7pfuMwWQq8MFUlo/eoG VwvmGSl8d9Nq/An8SuiRkaK4brPLhH55UZRxRQPUfBxeFvkFSZptXt2ruaFLcFhZ5E/Tc+m2tuDx Qxt991XtWgGeKwKYoLvJ+D7WFFw7rnHtQuFy0yugF+uUhXAbjiyLfH6SZodUa9eV1hui8rmwCbAn HbKwWni8CBLCdR4WLyxn4tMiWxLp/VRRWA8XwXuQoM3LhTafLk77IcvXspPLIh+NV5I0uxRXNUA/ iN26QdPziTdtaxHRzXd8lwnfJ0q903QOYb6IlRu77nN6Nbemx3k6r563FG7YpMEcJ5dFvrANVH+A ExX6FBHAtT1YLfywOMmLdHT8O4KPLxFP4BShPmubJdzu36KuPENHPZY4oSzyi3sD1F/gtX1F0FYd fG8Jjj8fHxK+eUAv178tNM9UEUcFvtwYv0/w+iN9ARnou8NrMEpHgwzV+b6zSOjySUJtdttT4sXQ VHymAtkEPR279wf0igAnktVe4t1LbeNEwhopNMaeIgiJU75axMh9IiPP1sm2C/D1ssgnlEX+Zn9B DNRVuu1A4R6167wjTvxcwTRjhKqbLeKkEAKutruFGvz7QBde2S8S14nHf1vjfucIdbi+kAKzdZ5A E/RZImAHDJrB+Vw4V3yB+CFOrPrGYnvxBW5NkV3rUu4l4S5Xr8yig/Wdc4l4f/iQ8PENRFYd1zXv FiHOHlvZBQf7O+e1wnVu7epfJvLAPgYBNIMPnKgZ9xYvSV8Qpd84oVV6q1n/P+x/Y/QhtBsN+W0A AAAASUVORK5CYII=" transform="translate(1 1.5)" overflow="visible"/></svg>
|
After Width: | Height: | Size: 2.9 KiB |
18
src/assets/svg/discord-red.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 250 200" style="enable-background:new 0 0 250 200;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#EC2E5A;}
|
||||
</style>
|
||||
<path class="st0" d="M204.9,27.3c-0.1-0.1-0.2-0.2-0.3-0.3c-14.9-6.8-30.6-11.7-46.8-14.5c-0.3-0.1-0.6,0.1-0.8,0.4
|
||||
c-2.1,3.9-4.1,7.9-5.8,12c-17.4-2.6-35.1-2.6-52.5,0c-1.7-4.1-3.7-8.1-5.9-12c-0.2-0.3-0.5-0.4-0.8-0.4C76,15.3,60.2,20.2,45.3,27
|
||||
c-0.1,0.1-0.2,0.1-0.3,0.3C15.3,71.7,7.1,115.1,11.1,158c0,0.2,0.1,0.4,0.3,0.5c17.3,12.8,36.7,22.6,57.4,29c0.3,0.1,0.6,0,0.8-0.3
|
||||
c4.4-6,8.4-12.4,11.7-19.1c0.2-0.4,0-0.8-0.3-1c0,0-0.1,0-0.1,0c-6.2-2.4-12.2-5.2-17.9-8.5c-0.4-0.2-0.5-0.7-0.3-1
|
||||
c0-0.1,0.1-0.2,0.2-0.2c1.2-0.9,2.4-1.8,3.6-2.8c0.2-0.2,0.5-0.2,0.7-0.1c37.6,17.2,78.3,17.2,115.4,0c0.2-0.1,0.5-0.1,0.8,0.1
|
||||
c1.2,1,2.4,1.9,3.6,2.8c0.3,0.2,0.4,0.7,0.1,1c-0.1,0.1-0.1,0.1-0.2,0.2c-5.7,3.3-11.7,6.2-17.9,8.5c-0.4,0.1-0.6,0.6-0.4,0.9
|
||||
c0,0,0,0.1,0,0.1c3.4,6.6,7.4,13,11.7,19.1c0.2,0.3,0.5,0.4,0.8,0.3c20.7-6.3,40.1-16.1,57.4-29c0.2-0.1,0.3-0.3,0.3-0.5
|
||||
C243.6,108.4,230.8,65.4,204.9,27.3L204.9,27.3z M86.9,131.9c-11.3,0-20.6-10.4-20.6-23.1s9.1-23.1,20.6-23.1
|
||||
c11.6,0,20.8,10.5,20.6,23.1C107.6,121.5,98.4,131.9,86.9,131.9z M163.2,131.9c-11.3,0-20.6-10.4-20.6-23.1s9.1-23.1,20.6-23.1
|
||||
c11.6,0,20.8,10.5,20.6,23.1C183.9,121.5,174.8,131.9,163.2,131.9z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
1
src/assets/svg/discord.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1677464651966" class="icon" viewBox="0 0 1280 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1126" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="200"><path d="M1049.062 139.672a3 3 0 0 0-1.528-1.4A970.13 970.13 0 0 0 808.162 64.06a3.632 3.632 0 0 0-3.846 1.82 674.922 674.922 0 0 0-29.8 61.2 895.696 895.696 0 0 0-268.852 0 619.082 619.082 0 0 0-30.27-61.2 3.78 3.78 0 0 0-3.848-1.82 967.378 967.378 0 0 0-239.376 74.214 3.424 3.424 0 0 0-1.576 1.352C78.136 367.302 36.372 589.38 56.86 808.708a4.032 4.032 0 0 0 1.53 2.75 975.332 975.332 0 0 0 293.65 148.378 3.8 3.8 0 0 0 4.126-1.352A696.4 696.4 0 0 0 416.24 860.8a3.72 3.72 0 0 0-2.038-5.176 642.346 642.346 0 0 1-91.736-43.706 3.77 3.77 0 0 1-0.37-6.252 502.094 502.094 0 0 0 18.218-14.274 3.638 3.638 0 0 1 3.8-0.512c192.458 87.834 400.82 87.834 591 0a3.624 3.624 0 0 1 3.848 0.466 469.066 469.066 0 0 0 18.264 14.32 3.768 3.768 0 0 1-0.324 6.252 602.814 602.814 0 0 1-91.78 43.66 3.75 3.75 0 0 0-2 5.222 782.11 782.11 0 0 0 60.028 97.63 3.728 3.728 0 0 0 4.126 1.4A972.096 972.096 0 0 0 1221.4 811.458a3.764 3.764 0 0 0 1.53-2.704c24.528-253.566-41.064-473.824-173.868-669.082zM444.982 675.16c-57.944 0-105.688-53.174-105.688-118.478s46.818-118.482 105.688-118.482c59.33 0 106.612 53.64 105.686 118.478 0 65.308-46.82 118.482-105.686 118.482z m390.76 0c-57.942 0-105.686-53.174-105.686-118.478s46.818-118.482 105.686-118.482c59.334 0 106.614 53.64 105.688 118.478 0 65.308-46.354 118.482-105.688 118.482z" p-id="1127"></path></svg>
|
After Width: | Height: | Size: 1.6 KiB |
11
src/assets/svg/google-play-red.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#EC2E5A;}
|
||||
</style>
|
||||
<path class="st0" d="M127.1,91.5L40.9,5.1l109.7,63C150.5,68,127.1,91.5,127.1,91.5z M18.4,0c-5.1,2.7-8.5,7.5-8.5,13.8v172.4
|
||||
c0,6.3,3.4,11.1,8.5,13.8l100.2-100L18.4,0z M184.5,88.1l-23-13.3L135.8,100l25.7,25.2l23.5-13.3C192,106.3,192,93.7,184.5,88.1
|
||||
L184.5,88.1z M40.9,194.9l109.7-63l-23.5-23.5L40.9,194.9z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 720 B |
1
src/assets/svg/google-play.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1677464090924" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6760" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M650.6 468.6L209.2 26l561.6 322.4-120.2 120.2zM94 0C68 13.6 50.6 38.4 50.6 70.6v882.6c0 32.2 17.4 57 43.4 70.6l513.2-512L94 0z m850.4 451.2l-117.8-68.2-131.4 129 131.4 129 120.2-68.2c36-28.6 36-93-2.4-121.6zM209.2 998l561.6-322.4-120.2-120.2L209.2 998z" p-id="6761"></path></svg>
|
After Width: | Height: | Size: 612 B |
1
src/assets/svg/hero-icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg version="1.1" id="prefix__图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 48 48" xml:space="preserve"><style>.prefix__st2{fill:#0f6569} .prefix__st2:hover{fill:#f12c12}</style><path class="prefix__st2" d="M40.94 19.13l-1-1c0-7-4-16-14.41-16.47-7.4-.34-13.59.47-18.59 10.47s2 17 2 17c0-7 3-9 3-9 1.19 1.03.92.95 4 3 3 2 4 5 4 5v-3c0-.67-1-3-1-3s1 1 2 3c2.08 4.15 1.28 9.52 1.05 10 4.98-.07 8.95-10 8.95-10 1 5-1.78 7-1.78 7l-.22 3 4.89-1.33c4.89-2.33 6.11-13.67 6.11-13.67 1 1 3 0 3 0s-1 0-2-1z"/><path class="prefix__st2" d="M21.99 35.12h-.05c.01.07.03.05.05 0z"/><path class="prefix__st2" d="M27.94 33.13l-1 1s-.16 1.53 0 2c.53 1.59 3 6 3 6l-4 4h-5v-2s1.74-2.14 2-3c.07-.24.09-.77 0-1-.24-.66-1.31-1.86-2-2-.78-.16-3 1-3 1l-4-1-4-6v-1.04l3-2.96-1-5-1-1v6l-3 3 1 2 4 6 5 1s2.22-1.16 3-1c.35.07.89.66 1 1 .08.24.07.76 0 1-.26.86-2 3-2 3v3h6l5-5s-2.47-4.41-3-6c-.23-.71 0-3 0-3z"/></svg>
|
After Width: | Height: | Size: 912 B |
37
src/assets/svg/login-active.svg
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 228 72" style="enable-background:new 0 0 228 72;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#D74458;}
|
||||
.st3{fill:#90FEEA;}
|
||||
.st4{fill:#122326;}
|
||||
.st5{fill:#E83154;}
|
||||
.st6{fill:#151E26;}
|
||||
</style>
|
||||
<path class="st0" d="M228,72H20C8.95,72,0,63.05,0,52V0h228V72z"/>
|
||||
<g>
|
||||
<polygon points="73,0 138.17,0 133.17,5 78,5 "/>
|
||||
<polygon points="145,5 139,5 144,0 150,0 "/>
|
||||
<polygon points="157.17,5 151.17,5 156.17,0 162.17,0 "/>
|
||||
<polygon points="169.17,5 163.17,5 168.17,0 174.17,0 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="73,72 138.17,72 133.17,67 78,67 "/>
|
||||
<polygon points="145,67 139,67 144,72 150,72 "/>
|
||||
<polygon points="157.17,67 151.17,67 156.17,72 162.17,72 "/>
|
||||
<polygon points="169.17,67 163.17,67 168.17,72 174.17,72 "/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon points="25,25.28 25,31.5 21,35.28 15,35.28 "/>
|
||||
<polygon points="25,46.72 25,40.5 21,36.72 15,36.72 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="211,0 211,5 223,5 223,67 211,67 211,72 228,72 228,0 "/>
|
||||
<path d="M17,66.48C10.1,64.7,5,58.45,5,51V5h12V0H0v52c0,10.02,7.38,18.3,17,19.75V66.48z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
59
src/assets/svg/login.svg
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 228 72" style="enable-background:new 0 0 228 72;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#D74458;}
|
||||
.st2{fill:#90FEEA;}
|
||||
.st3{fill:#122326;}
|
||||
.st4{fill:#E83154;}
|
||||
.st5{fill:#151E26;}
|
||||
.st6{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path d="M228,72H20C8.95,72,0,63.05,0,52V0h228V72z"/>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="st0" points="73,0 138.17,0 133.17,5 78,5 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st0" points="145,5 139,5 144,0 150,0 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st0" points="157.17,5 151.17,5 156.17,0 162.17,0 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st0" points="169.17,5 163.17,5 168.17,0 174.17,0 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="st0" points="73,72 138.17,72 133.17,67 78,67 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st0" points="145,67 139,67 144,72 150,72 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st0" points="157.17,67 151.17,67 156.17,72 162.17,72 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st0" points="169.17,67 163.17,67 168.17,72 174.17,72 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="st0" points="25,25.28 25,31.5 21,35.28 15,35.28 "/>
|
||||
<polygon class="st0" points="25,46.72 25,40.5 21,36.72 15,36.72 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="st0" points="211,0 211,5 223,5 223,67 211,67 211,72 228,72 228,0 "/>
|
||||
<path class="st0" d="M17,66.48C10.1,64.7,5,58.45,5,51V5h12V0H0v52c0,10.02,7.38,18.3,17,19.75V66.48z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
32
src/assets/svg/tab/chip-icon-active.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M46.09,17.49L24.1,1.57c-0.08-0.06-0.19-0.06-0.27,0L2.31,17.21c-0.36,0.26-0.36,0.81,0,1.07L23.2,33.41
|
||||
c0.49,0.35,1.15,0.35,1.64,0l21.25-15.45C46.25,17.84,46.25,17.6,46.09,17.49z M24.96,7.12c0-0.24,0.28-0.37,0.47-0.22l7.68,6.15
|
||||
c0.21,0.17,0.09,0.51-0.18,0.51H29.4c-0.07,0-0.13-0.02-0.18-0.06l-4.15-3.33c-0.07-0.05-0.11-0.14-0.11-0.22V7.12z M14.88,13.08
|
||||
l7.68-6.15c0.19-0.15,0.47-0.02,0.47,0.22v2.82c0,0.09-0.04,0.17-0.11,0.22l-4.15,3.33c-0.05,0.04-0.11,0.06-0.18,0.06h-3.53
|
||||
C14.79,13.59,14.67,13.24,14.88,13.08z M23.02,26.86c0,0.25-0.29,0.38-0.48,0.21L9.58,15.5C9.38,15.32,9.51,15,9.77,15h6.37
|
||||
c0.07,0,0.13,0.02,0.18,0.06l6.59,5.3c0.07,0.05,0.11,0.14,0.11,0.22V26.86z M24.22,17.79c-0.11,0.11-0.29,0.11-0.41,0l-3.55-3.55
|
||||
c-0.13-0.13-0.11-0.34,0.04-0.44l3.55-2.46c0.1-0.07,0.23-0.07,0.33,0l3.51,2.44c0.15,0.1,0.17,0.31,0.04,0.44L24.22,17.79z
|
||||
M38.4,15.47L25.44,27.05c-0.18,0.16-0.48,0.03-0.48-0.21v-6.28c0-0.09,0.04-0.17,0.11-0.22l6.59-5.3
|
||||
c0.05-0.04,0.11-0.06,0.18-0.06h6.37C38.48,14.97,38.6,15.3,38.4,15.47z"/>
|
||||
<path class="st0" d="M45.27,21.49L24.9,35.38c-0.55,0.38-1.28,0.38-1.83,0L2.71,21.49c-0.31-0.21-0.72,0.01-0.72,0.38v2.9
|
||||
c0,0.15,0.07,0.29,0.19,0.37l20.73,15.08c0.64,0.46,1.51,0.45,2.13-0.03l20.77-16.05c0.11-0.09,0.18-0.22,0.18-0.36v-1.9
|
||||
C45.99,21.5,45.58,21.28,45.27,21.49z"/>
|
||||
<path class="st0" d="M45.02,27.7L24.91,42.33c-0.55,0.4-1.29,0.4-1.83,0L2.96,27.7c-0.4-0.29-0.97-0.01-0.97,0.49v1.49
|
||||
c0,0.2,0.09,0.38,0.25,0.49L23.02,45.3c0.58,0.42,1.36,0.42,1.94,0l20.78-15.11c0.16-0.11,0.25-0.3,0.25-0.49V28.2
|
||||
C45.99,27.7,45.43,27.41,45.02,27.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
32
src/assets/svg/tab/chip-icon-hover.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M46.09,17.49L24.1,1.57c-0.08-0.06-0.19-0.06-0.27,0L2.31,17.21c-0.36,0.26-0.36,0.81,0,1.07L23.2,33.41
|
||||
c0.49,0.35,1.15,0.35,1.64,0l21.25-15.45C46.25,17.84,46.25,17.6,46.09,17.49z M24.96,7.12c0-0.24,0.28-0.37,0.47-0.22l7.68,6.15
|
||||
c0.21,0.17,0.09,0.51-0.18,0.51H29.4c-0.07,0-0.13-0.02-0.18-0.06l-4.15-3.33c-0.07-0.05-0.11-0.14-0.11-0.22V7.12z M14.88,13.08
|
||||
l7.68-6.15c0.19-0.15,0.47-0.02,0.47,0.22v2.82c0,0.09-0.04,0.17-0.11,0.22l-4.15,3.33c-0.05,0.04-0.11,0.06-0.18,0.06h-3.53
|
||||
C14.79,13.59,14.67,13.24,14.88,13.08z M23.02,26.86c0,0.25-0.29,0.38-0.48,0.21L9.58,15.5C9.38,15.32,9.51,15,9.77,15h6.37
|
||||
c0.07,0,0.13,0.02,0.18,0.06l6.59,5.3c0.07,0.05,0.11,0.14,0.11,0.22V26.86z M24.22,17.79c-0.11,0.11-0.29,0.11-0.41,0l-3.55-3.55
|
||||
c-0.13-0.13-0.11-0.34,0.04-0.44l3.55-2.46c0.1-0.07,0.23-0.07,0.33,0l3.51,2.44c0.15,0.1,0.17,0.31,0.04,0.44L24.22,17.79z
|
||||
M38.4,15.47L25.44,27.05c-0.18,0.16-0.48,0.03-0.48-0.21v-6.28c0-0.09,0.04-0.17,0.11-0.22l6.59-5.3
|
||||
c0.05-0.04,0.11-0.06,0.18-0.06h6.37C38.48,14.97,38.6,15.3,38.4,15.47z"/>
|
||||
<path class="st0" d="M45.27,21.49L24.9,35.38c-0.55,0.38-1.28,0.38-1.83,0L2.71,21.49c-0.31-0.21-0.72,0.01-0.72,0.38v2.9
|
||||
c0,0.15,0.07,0.29,0.19,0.37l20.73,15.08c0.64,0.46,1.51,0.45,2.13-0.03l20.77-16.05c0.11-0.09,0.18-0.22,0.18-0.36v-1.9
|
||||
C45.99,21.5,45.58,21.28,45.27,21.49z"/>
|
||||
<path class="st0" d="M45.02,27.7L24.91,42.33c-0.55,0.4-1.29,0.4-1.83,0L2.96,27.7c-0.4-0.29-0.97-0.01-0.97,0.49v1.49
|
||||
c0,0.2,0.09,0.38,0.25,0.49L23.02,45.3c0.58,0.42,1.36,0.42,1.94,0l20.78-15.11c0.16-0.11,0.25-0.3,0.25-0.49V28.2
|
||||
C45.99,27.7,45.43,27.41,45.02,27.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
32
src/assets/svg/tab/chip-icon.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st2" d="M46.03,17.62L24.04,1.7c-0.08-0.06-0.19-0.06-0.27,0L2.26,17.34c-0.36,0.26-0.36,0.81,0,1.07l20.89,15.12
|
||||
c0.49,0.35,1.15,0.35,1.64,0l21.25-15.45C46.19,17.97,46.19,17.73,46.03,17.62z M24.91,7.25c0-0.24,0.28-0.37,0.47-0.22l7.68,6.15
|
||||
c0.21,0.17,0.09,0.51-0.18,0.51h-3.53c-0.07,0-0.13-0.02-0.18-0.06l-4.15-3.33c-0.07-0.05-0.11-0.14-0.11-0.22V7.25z M14.82,13.2
|
||||
l7.68-6.15c0.19-0.15,0.47-0.02,0.47,0.22v2.82c0,0.09-0.04,0.17-0.11,0.22l-4.15,3.33c-0.05,0.04-0.11,0.06-0.18,0.06H15
|
||||
C14.73,13.71,14.61,13.37,14.82,13.2z M22.96,26.99c0,0.25-0.29,0.38-0.48,0.21L9.52,15.63c-0.2-0.18-0.07-0.5,0.19-0.5h6.37
|
||||
c0.07,0,0.13,0.02,0.18,0.06l6.59,5.3c0.07,0.05,0.11,0.14,0.11,0.22V26.99z M24.17,17.92c-0.11,0.11-0.29,0.11-0.41,0l-3.55-3.55
|
||||
c-0.13-0.13-0.11-0.34,0.04-0.44l3.55-2.46c0.1-0.07,0.23-0.07,0.33,0l3.51,2.44c0.15,0.1,0.17,0.31,0.04,0.44L24.17,17.92z
|
||||
M38.35,15.6L25.38,27.17c-0.18,0.16-0.48,0.03-0.48-0.21v-6.28c0-0.09,0.04-0.17,0.11-0.22l6.59-5.3
|
||||
c0.05-0.04,0.11-0.06,0.18-0.06h6.37C38.42,15.1,38.54,15.42,38.35,15.6z"/>
|
||||
<path class="st2" d="M45.22,21.62L24.85,35.5c-0.55,0.38-1.28,0.38-1.83,0L2.65,21.62C2.35,21.41,1.94,21.63,1.94,22v2.9
|
||||
c0,0.15,0.07,0.29,0.19,0.37l20.73,15.08c0.64,0.46,1.51,0.45,2.13-0.03l20.77-16.05c0.11-0.09,0.18-0.22,0.18-0.36V22
|
||||
C45.94,21.63,45.52,21.41,45.22,21.62z"/>
|
||||
<path class="st2" d="M44.97,27.83L24.85,42.46c-0.55,0.4-1.29,0.4-1.83,0L2.9,27.83c-0.4-0.29-0.97-0.01-0.97,0.49v1.49
|
||||
c0,0.2,0.09,0.38,0.25,0.49l20.78,15.11c0.58,0.42,1.36,0.42,1.94,0l20.78-15.11c0.16-0.11,0.25-0.3,0.25-0.49v-1.49
|
||||
C45.94,27.83,45.37,27.54,44.97,27.83z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
24
src/assets/svg/tab/hero-icon-active.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M41,19c-0.25-0.25-1-1-1-1c0-7-4-16-14.41-16.47C18.19,1.19,12,2,7,12s2,17,2,17c0-7,3-9,3-9
|
||||
c1.19,1.03,0.92,0.95,4,3c3,2,4,5,4,5s0-1.67,0-3c0-0.67-1-3-1-3s1,1,2,3c2.08,4.15,1.28,9.52,1.05,10C27.03,34.93,31,25,31,25
|
||||
c1,5-1.78,7-1.78,7L29,35l4.89-1.33C38.78,31.34,40,20,40,20c1,1,3,0,3,0S42,20,41,19z"/>
|
||||
<path class="st0" d="M22.05,35c-0.02,0-0.03,0-0.05,0C22.01,35.06,22.03,35.04,22.05,35z"/>
|
||||
<path class="st0" d="M28,33l-1,1c0,0-0.16,1.53,0,2c0.53,1.59,3,6,3,6l-4,4h-5v-2c0,0,1.74-2.14,2-3c0.07-0.24,0.09-0.77,0-1
|
||||
c-0.24-0.66-1.31-1.86-2-2c-0.78-0.16-3,1-3,1l-4-1l-4-6v-1.04L13,28l-1-5l-1-1v6l-3,3l1,2l4,6l5,1c0,0,2.22-1.16,3-1
|
||||
c0.35,0.07,0.89,0.66,1,1c0.08,0.24,0.07,0.76,0,1c-0.26,0.86-2,3-2,3v3h6l5-5c0,0-2.47-4.41-3-6C27.76,35.29,28,33,28,33z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
24
src/assets/svg/tab/hero-icon-hover.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M41,19c-0.25-0.25-1-1-1-1c0-7-4-16-14.41-16.47C18.19,1.19,12,2,7,12s2,17,2,17c0-7,3-9,3-9
|
||||
c1.19,1.03,0.92,0.95,4,3c3,2,4,5,4,5s0-1.67,0-3c0-0.67-1-3-1-3s1,1,2,3c2.08,4.15,1.28,9.52,1.05,10C27.03,34.93,31,25,31,25
|
||||
c1,5-1.78,7-1.78,7L29,35l4.89-1.33C38.78,31.34,40,20,40,20c1,1,3,0,3,0S42,20,41,19z"/>
|
||||
<path class="st0" d="M22.05,35c-0.02,0-0.03,0-0.05,0C22.01,35.06,22.03,35.04,22.05,35z"/>
|
||||
<path class="st0" d="M28,33l-1,1c0,0-0.16,1.53,0,2c0.53,1.59,3,6,3,6l-4,4h-5v-2c0,0,1.74-2.14,2-3c0.07-0.24,0.09-0.77,0-1
|
||||
c-0.24-0.66-1.31-1.86-2-2c-0.78-0.16-3,1-3,1l-4-1l-4-6v-1.04L13,28l-1-5l-1-1v6l-3,3l1,2l4,6l5,1c0,0,2.22-1.16,3-1
|
||||
c0.35,0.07,0.89,0.66,1,1c0.08,0.24,0.07,0.76,0,1c-0.26,0.86-2,3-2,3v3h6l5-5c0,0-2.47-4.41-3-6C27.76,35.29,28,33,28,33z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
26
src/assets/svg/tab/hero-icon.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st2" d="M40.94,19.13c-0.25-0.25-1-1-1-1c0-7-4-16-14.41-16.47c-7.4-0.34-13.59,0.47-18.59,10.47s2,17,2,17
|
||||
c0-7,3-9,3-9c1.19,1.03,0.92,0.95,4,3c3,2,4,5,4,5s0-1.67,0-3c0-0.67-1-3-1-3s1,1,2,3c2.08,4.15,1.28,9.52,1.05,10
|
||||
c4.98-0.07,8.95-10,8.95-10c1,5-1.78,7-1.78,7l-0.22,3l4.89-1.33c4.89-2.33,6.11-13.67,6.11-13.67c1,1,3,0,3,0
|
||||
S41.94,20.13,40.94,19.13z"/>
|
||||
<path class="st2" d="M21.99,35.12c-0.02,0-0.03,0-0.05,0C21.95,35.19,21.97,35.17,21.99,35.12z"/>
|
||||
<path class="st2" d="M27.94,33.13l-1,1c0,0-0.16,1.53,0,2c0.53,1.59,3,6,3,6l-4,4h-5v-2c0,0,1.74-2.14,2-3
|
||||
c0.07-0.24,0.09-0.77,0-1c-0.24-0.66-1.31-1.86-2-2c-0.78-0.16-3,1-3,1l-4-1l-4-6v-1.04l3-2.96l-1-5l-1-1v6l-3,3l1,2l4,6l5,1
|
||||
c0,0,2.22-1.16,3-1c0.35,0.07,0.89,0.66,1,1c0.08,0.24,0.07,0.76,0,1c-0.26,0.86-2,3-2,3v3h6l5-5c0,0-2.47-4.41-3-6
|
||||
C27.71,35.42,27.94,33.13,27.94,33.13z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
25
src/assets/svg/tab/weapon-icon-active.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M6.2,12.44h3.98V13H11c3.1-4.32,7.78-6.6,13.5-6.6s10.78,2.82,13.88,7.14h1.37l1.05-1.05h2.14
|
||||
C39.19,6.21,32.34,2,24.5,2C15.81,2,8.34,6.17,4.95,13.59H6.2V12.44z"/>
|
||||
<path class="st0" d="M7.2,26.12v-3.15l-1.1-1.1H3.18C3.07,22.74,3,22.61,3,23.5c0,2.54,0.47,4.98,1.28,7.24L7.2,26.12z"/>
|
||||
<path class="st0" d="M41.52,21.93c0.05,0.52,0.08,1.04,0.08,1.57c0,9.45-7.66,17.1-17.1,17.1c-3.85,0-7.39-1.29-10.24-3.43
|
||||
l-2,3.99C15.73,43.58,19.95,45,24.5,45C36.37,45,46,35.37,46,23.5c0-0.53-0.04-1.05-0.08-1.57H41.52z"/>
|
||||
<path class="st0" d="M44.48,14l-1-1h-2l-1,1H9v-1H7v1H4.48v5h-1v2h3l2,2v3L1.11,37.67V42h9.37l8-15c2.52,2,6,1.93,6,1.93
|
||||
c7,0,7.37-7.93,7.37-7.93h13.63l1-1.3v-2.11h1V14H44.48z M28.48,26c-1.04,1.65-5.48,2-7.81,0c-0.84-0.72-2.41-3.16,1.7-4.08
|
||||
c0,0,0.03,1.15,0.41,2.2c0.3,0.84,0.81,1.61,1.7,1.69c0,0-0.81-2.05-0.48-2.81c0.16-0.37,1-1,2-1S31,22,28.48,26z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
25
src/assets/svg/tab/weapon-icon-hover.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M6.2,12.44h3.98V13H11c3.1-4.32,7.78-6.6,13.5-6.6s10.78,2.82,13.88,7.14h1.37l1.05-1.05h2.14
|
||||
C39.19,6.21,32.34,2,24.5,2C15.81,2,8.34,6.17,4.95,13.59H6.2V12.44z"/>
|
||||
<path class="st0" d="M7.2,26.12v-3.15l-1.1-1.1H3.18C3.07,22.74,3,22.61,3,23.5c0,2.54,0.47,4.98,1.28,7.24L7.2,26.12z"/>
|
||||
<path class="st0" d="M41.52,21.93c0.05,0.52,0.08,1.04,0.08,1.57c0,9.45-7.66,17.1-17.1,17.1c-3.85,0-7.39-1.29-10.24-3.43
|
||||
l-2,3.99C15.73,43.58,19.95,45,24.5,45C36.37,45,46,35.37,46,23.5c0-0.53-0.04-1.05-0.08-1.57H41.52z"/>
|
||||
<path class="st0" d="M44.48,14l-1-1h-2l-1,1H9v-1H7v1H4.48v5h-1v2h3l2,2v3L1.11,37.67V42h9.37l8-15c2.52,2,6,1.93,6,1.93
|
||||
c7,0,7.37-7.93,7.37-7.93h13.63l1-1.3v-2.11h1V14H44.48z M28.48,26c-1.04,1.65-5.48,2-7.81,0c-0.84-0.72-2.41-3.16,1.7-4.08
|
||||
c0,0,0.03,1.15,0.41,2.2c0.3,0.84,0.81,1.61,1.7,1.69c0,0-0.81-2.05-0.48-2.81c0.16-0.37,1-1,2-1S31,22,28.48,26z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
25
src/assets/svg/tab/weapon-icon.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFBA00;}
|
||||
.st1{fill:#EC2E5B;}
|
||||
.st2{fill:#9E9E9E;}
|
||||
.st3{fill:#0F6569;}
|
||||
.st4{fill:#CEC3C3;}
|
||||
.st5{fill:#8AF4E1;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st2" d="M6.14,12.57h3.98v0.56h0.82c3.1-4.32,7.78-6.6,13.5-6.6s10.78,2.82,13.88,7.14h1.37l1.05-1.05h2.14
|
||||
C39.13,6.34,32.29,2.13,24.44,2.13c-8.69,0-16.16,4.17-19.55,11.59h1.24V12.57z"/>
|
||||
<path class="st2" d="M7.14,26.25V23.1L6.04,22H3.12c-0.1,0.86-0.18,0.73-0.18,1.62c0,2.54,0.47,4.98,1.28,7.24L7.14,26.25z"/>
|
||||
<path class="st2" d="M41.47,22.05c0.05,0.52,0.08,1.04,0.08,1.57c0,9.45-7.66,17.1-17.1,17.1c-3.85,0-7.39-1.29-10.24-3.43
|
||||
l-2,3.99c3.48,2.41,7.69,3.84,12.24,3.84c11.87,0,21.5-9.63,21.5-21.5c0-0.53-0.04-1.05-0.08-1.57H41.47z"/>
|
||||
<path class="st2" d="M44.43,14.13l-1-1h-2l-1,1H8.94v-1h-2v1H4.43v5h-1v2h3l2,2v3L1.06,37.79v4.33h9.37l8-15c2.52,2,6,1.93,6,1.93
|
||||
c7,0,7.37-7.93,7.37-7.93h13.63l1-1.3v-2.11h1v-3.59H44.43z M28.43,26.13c-1.04,1.65-5.48,2-7.81,0c-0.84-0.72-2.41-3.16,1.7-4.08
|
||||
c0,0,0.03,1.15,0.41,2.2c0.3,0.84,0.81,1.61,1.7,1.69c0,0-0.81-2.05-0.48-2.81c0.16-0.37,1-1,2-1S30.94,22.13,28.43,26.13z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
10
src/assets/svg/telegram-red.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#EC2E5A;}
|
||||
</style>
|
||||
<path class="st0" d="M81.5,155.4l2.3-35.2l64-57.7c2.8-2.6-0.6-3.8-4.3-1.6l-79,49.9L30.3,100c-7.3-2.1-7.4-7.2,1.7-10.8l133.1-51.3
|
||||
c6.1-2.8,11.9,1.5,9.6,10.8L152,155.4c-1.6,7.6-6.2,9.4-12.5,5.9L105,135.8l-16.6,16.1C86.5,153.8,84.9,155.4,81.5,155.4z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 662 B |
1
src/assets/svg/telegram.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1677464753225" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2113" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M417.28 795.733333l11.946667-180.48 327.68-295.253333c14.506667-13.226667-2.986667-19.626667-22.186667-8.106667L330.24 567.466667 155.306667 512c-37.546667-10.666667-37.973333-36.693333 8.533333-55.466667l681.386667-262.826666c31.146667-14.08 61.013333 7.68 49.066666 55.466666l-116.053333 546.56c-8.106667 38.826667-31.573333 48.213333-64 30.293334L537.6 695.466667l-84.906667 82.346666c-9.813333 9.813333-17.92 17.92-35.413333 17.92z" fill="" p-id="2114"></path></svg>
|
After Width: | Height: | Size: 803 B |
13
src/assets/svg/twitter-red.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#EC2E5A;}
|
||||
</style>
|
||||
<path class="st0" d="M200,38c-7.5,3.3-15.5,5.5-23.6,6.5c8.6-5.1,15-13.2,18-22.7c-8.1,4.8-16.9,8.2-26.1,10
|
||||
c-15.6-16.5-41.5-17.2-58-1.6c-8.2,7.8-12.9,18.5-12.8,29.8c0,3.1,0.4,6.3,1.1,9.3c-33-1.7-63.8-17.3-84.6-43
|
||||
c-3.7,6.2-5.6,13.4-5.6,20.6C8,60.5,14.6,73.3,25.8,81C19,80.8,6.3,79,6.3,75.9v0.5c0.5,19.6,14.6,36.2,33.8,40
|
||||
c-3.3,0.9-6.6,1.4-10,1.4c-2.5,0-5-0.2-7.5-0.7c5.4,16.7,20.8,28.2,38.4,28.5c-14.5,11.5-32.5,17.8-51,17.8c-3.3,0-6.7-0.2-10-0.6
|
||||
c18.8,12,40.6,18.4,62.9,18.4c64,0.7,116.4-50.7,117.1-114.7c0-0.7,0-1.3,0-2v-5.3C187.9,53.4,194.6,46.2,200,38z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 974 B |
1
src/assets/svg/twitter.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1677463959719" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3002" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1024 194.56a420.352 420.352 0 0 1-120.832 33.28 210.432 210.432 0 0 0 92.16-116.224 422.4 422.4 0 0 1-133.632 51.2A209.92 209.92 0 0 0 499.2 307.2a211.968 211.968 0 0 0 5.632 47.616 596.48 596.48 0 0 1-433.152-220.16 208.896 208.896 0 0 0-28.672 105.472A204.8 204.8 0 0 0 132.096 414.72C97.28 413.696 32.256 404.48 32.256 388.608v2.56a214.528 214.528 0 0 0 173.056 204.8 193.024 193.024 0 0 1-51.2 7.168 199.68 199.68 0 0 1-38.4-3.584 210.944 210.944 0 0 0 196.608 145.92A420.864 420.864 0 0 1 51.2 836.608a438.784 438.784 0 0 1-51.2-3.072 594.944 594.944 0 0 0 322.048 94.208A593.408 593.408 0 0 0 921.6 330.24v-27.136a427.008 427.008 0 0 0 102.4-108.544z m0 0" fill="#000" p-id="3003"></path></svg>
|
After Width: | Height: | Size: 1.0 KiB |
1
src/assets/svg/weapon-icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48"><image width="46" height="45" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAtCAYAAADRLVmZAAAFrklEQVRogeXZe4xcVR0H8M8Oy1IK 2qFsRdP6iNgaIiGIGKlPqv0D4yPBWB8hgP7BmI4SlRqNUeOjaiIJxmgzMaMBQdFoFBLQ+mqxCBSQ gKDx0aTUB21VoO1g6Xa7Xbr+8Tu3vZ2dO3PvsMlq/CYnd+7J75zznd859/c6/I9iZGZmZqBQvdEc JHISnoU6lmIxFmIKB7Abj2NfelZCp92a1TdadZIuvAIXYDVejjP6yD6FP+B2bMZv8I9hFx6W+CV4 O95cYY4TcE5qV+JPuBVtPFyVQFXiq/BJvL7qQj1wVmrvwo34LA6VHVwrKTeG9bjF3JDO43n4OO7E a8sOGqjxeqN5Oq7HmwaI/gv/TG03JtL8dTwXS9JzQcH484ViPozrnhbxeqO5NE12XoHINH4uPraf iXNbhGfg1bgIb8BLesgswrU4DV8eini90VyWCK0oELleaOb2fgvksB8/TW0J3okP4cwestcIpXy1 aLKeZ7zeaJ6aiK1IE+TxF2FN3lOBdDcewwZciNlGOvAVnF00wSwHVG80F+ILwoHciBGsFF/9L3EZ 9g5JuAiXYl36vQBb8QnhwE7GTKfd2jWI+JlYK7S5Ho+K83Y+bsAjafKRAhJHCvpHCsYcTmNOyslN YkYclfcL5/VBfFMc75lCl19vNNfgB+l1C3ZiPA0sIi0t0ot8TTihXphJLU98kfDKJ6b+fbgn/cFH jyOeTN9avEicv+f3ITif2N9tVZ6JJp4zD2SqYKLbqkwIR/LfjN24rpt4DafMA5kquAufOko8mcH1 WD5vlMphDKN5jT8bF88TmSo4EbUa1BvNV+J9gvi78at5JDYIu3Awsyp1fBSjnXZrXb3R3CiCppUV J30KD4lQdRy/xSZh118gFDOWZA+KSPKACCt6hR+TIkav4VT8HRs67dZMRjx7XlVvNMeFSbxWOIB+ zqab9MfwbeGwRsTubcvJfF3s7H34HLYLSzZdsM5CYSwyz/pwp93amyc8lhO+DH8WmppyzBUPwoMi qsuwX2xrHjcl4j9ObRA+gnckHmO4r95oruu0W5MZ8e6U6QzhcqukdvuS/LQI0q7CMqGEDFPpOVFy zleJJDzDkdSOnqsDXQN+h5cpji164TxxtIiocpXjScPb0nObcuhe/2+ddmuKYxrdg38Ll79b5H9f Ks8ZUUv5vojjHxOaP0Uo57DIeC7Hbfh1yTnHu96PljMy4juxA+fiavFRvK4C6a24H28RiW8vHBLl iCvxRIk5XyisUx5/zX6MQqfd2lNvNHeIaPAb+KLI+8rgEawRO3U1Xiz+OGFpsjD3cWEey+I1oiqW 4aAwtceIJ9yPX4gtXVthgZsSaWLndlYY2w9v7Hrfhruzlzzxa8QZv8Xx5rEfDoosf65xDt7a1be1 025NZi9HvVWn3TokbOwFyuOPIlqba3xA5JoZpvCdvEA+OjxblAuq4CfCGs0lVuOKrr7bOu3W3fmO LMg6QdQET6+wwBOC+FxiqTAOeRzGZ7oFM42vEq61CjarZiUG4TR8VwRjeWzotFv3dgvX6o3mArxX +WAqwyahjbnAuPC23UXPh0T4MAs1Ucu7qOJCu0QpbS7wUmw02/xlxmJPr0E14e0WV1xss5wXGxJL hJfd6vhAiggX1mDWEckw2mPQIBzBt0RlaRW+hx8KD1kGy0XofLHeFdv9oiR3a79JRlWzJERMMy1K Y8vFjn0aD4jgbLsocTwp8sPFIrw9V2RUZymu22wXXnvTIBLD3AHdLLSVVQNqjl2LXCLSraweOJLW GCux1o9E+rijDIlRfF5c9T2pv2UZS6S2iBJwERYovnXohQfxNZEqlsaw95wXCru/2nB1mCPCKm0U hCf7Cc/lPeeW1JaJj3tlaivE7nVjShyB3+MOkSzfM+TaePoXtFkYe7OILBeJMsLJIiafFvnlhIhp 9pp9w/H/hf8AsHdjd0huR7YAAAAASUVORK5CYII=" transform="translate(1 1.5)" overflow="visible"/></svg>
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/assets/text/GEMUNULIBRE-EXTRABOLD.TTF
Normal file
BIN
src/assets/text/MEUROSTILE.TTF
Normal file
BIN
src/assets/text/Poppins-SemiBold.ttf
Normal file
BIN
src/assets/text/SAIRA-BLACK.TTF
Normal file
BIN
src/assets/text/arial.ttf
Normal file
BIN
src/assets/text/arialbd.ttf
Normal file
BIN
src/assets/text/ariblk.ttf
Normal file
BIN
src/assets/text/big-john-woff2-2.ttf
Normal file
33
src/assets/text/text.css
Normal file
@ -0,0 +1,33 @@
|
||||
@font-face {
|
||||
font-family: "Big John";
|
||||
src: url('./big-john-woff2-2.ttf');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Arial";
|
||||
src: url('./arial.ttf');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url('./Poppins-SemiBold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MEurostile';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url('./MEUROSTILE.TTF') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'GemunuExtraBold';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url('./GEMUNULIBRE-EXTRABOLD.TTF') format('truetype');
|
||||
}
|
||||
|
1
src/assets/vue.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
After Width: | Height: | Size: 496 B |
21
src/bus/event.js
Normal file
@ -0,0 +1,21 @@
|
||||
export const PRESALE_BEGIN = 'presale_begin'
|
||||
|
||||
export const PRESALE_ORDER_GET = 'presale_order_get'
|
||||
|
||||
export const PRESALE_SUCCESS = 'presale_success'
|
||||
|
||||
export const PRESALE_ERROR = 'presale_error'
|
||||
|
||||
export const NEED_LOGIN = 'need_login'
|
||||
|
||||
export const NEED_NONCE = 'need_nonce'
|
||||
|
||||
export const ACCOUNT_CHANGE = 'account_change'
|
||||
|
||||
export const SHOW_CHAIN_MODAL = 'show_chain_modal'
|
||||
|
||||
export const NEED_CHANGE_CHAIN = 'need_change_chain'
|
||||
|
||||
export const WALLET_SELECTED = 'wallet_selected'
|
||||
|
||||
export const CHAIN_SELECTED = 'chain_selected'
|
48
src/chain/Chain.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import Web3 from 'web3'
|
||||
import { useAppStore } from '@/store/app'
|
||||
import { ERC20ABI } from '@/configs/contracts'
|
||||
import pinia from '@/store';
|
||||
|
||||
const AppModule = useAppStore(pinia);
|
||||
|
||||
export class Chain {
|
||||
private web3: Web3
|
||||
|
||||
constructor(provider: any) {
|
||||
this.web3 = new Web3(provider)
|
||||
}
|
||||
|
||||
public async initInstance({ abi, address, account }: {abi: any, address: string, account: string}) {
|
||||
return new this.web3.eth.Contract(
|
||||
abi,
|
||||
address,
|
||||
{ from: account }
|
||||
)
|
||||
}
|
||||
|
||||
public async initContractInstance(address: string, abi: any = ERC20ABI) {
|
||||
return this.initInstance({
|
||||
abi,
|
||||
address,
|
||||
account: AppModule.accountId
|
||||
})
|
||||
}
|
||||
|
||||
public async sendCmd({ method, params, from }: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
this.web3.currentProvider.send({
|
||||
method,
|
||||
params,
|
||||
from
|
||||
}, async function(err: any, result: any) {
|
||||
if (err) {
|
||||
reject && reject(err)
|
||||
return
|
||||
}
|
||||
resolve && resolve(result)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
276
src/chain/ChainManager.ts
Normal file
@ -0,0 +1,276 @@
|
||||
import { Blockchain } from "@/chain/blockchain";
|
||||
import { getNonce } from "@/api/User";
|
||||
import pinia from "@/store";
|
||||
import { useAppStore } from "@/store/app";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import { message } from "ant-design-vue";
|
||||
import { Chain } from "@/chain/Chain";
|
||||
import { AVAILABLE_CHAINS } from "@/configs/configchain";
|
||||
import { AllChains } from "@/configs/allchain";
|
||||
import {
|
||||
ACTIVATE_PROXY_ABI,
|
||||
MYSTERY_BOX_ABI,
|
||||
MYSTERY_PROXY_ABI
|
||||
} from "@/configs/contracts";
|
||||
|
||||
const AppModule = useAppStore(pinia);
|
||||
const UserModule = useUserStore();
|
||||
|
||||
export default class ChainManager {
|
||||
bc: Blockchain;
|
||||
instanceMap: Map<string, any>;
|
||||
public chainMap: Map<number, any> = new Map();
|
||||
private _availableChains: Map<number, any> = new Map();
|
||||
|
||||
constructor() {
|
||||
this.bc = new Blockchain();
|
||||
this.instanceMap = new Map();
|
||||
for (const data of AllChains) {
|
||||
this.chainMap.set(data.id, data);
|
||||
}
|
||||
}
|
||||
|
||||
get availableChains() {
|
||||
if (this._availableChains.size === 0) {
|
||||
for (const id of AVAILABLE_CHAINS) {
|
||||
const d = this.chainMap.get(id);
|
||||
if (d) {
|
||||
this._availableChains.set(id, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this._availableChains;
|
||||
}
|
||||
|
||||
public async init() {
|
||||
if (this.bc.isWalletConnect) {
|
||||
try {
|
||||
await this.bc.connect();
|
||||
} catch (err) {
|
||||
console.log("connect chain error: ", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get isLogined() {
|
||||
return !!UserModule.token && !!AppModule.step;
|
||||
}
|
||||
|
||||
public async logout() {
|
||||
await this.bc.disconnect();
|
||||
}
|
||||
|
||||
public get currentChain() {
|
||||
return this.bc.currentChain;
|
||||
}
|
||||
|
||||
public async login() {
|
||||
if (!AppModule.step) {
|
||||
try {
|
||||
await this.bc.connect(true);
|
||||
await this.checkNance();
|
||||
} catch (err) {
|
||||
message.error(err.message, 5);
|
||||
await this.bc.disconnect();
|
||||
await Promise.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async checkNance() {
|
||||
try {
|
||||
const preRequest: any = await getNonce();
|
||||
let nonce = preRequest.nonce + "";
|
||||
const tips = preRequest.data?.tips;
|
||||
AppModule.updateNonce(nonce);
|
||||
|
||||
await UserModule.Login({
|
||||
bcInstance: this.bc,
|
||||
account: AppModule.accountId,
|
||||
chainId: AppModule.chainId,
|
||||
nonce,
|
||||
tips,
|
||||
});
|
||||
AppModule.updateStep(1);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
await Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
public async getInstance(address: string, chainId: number, abi?: any) {
|
||||
const key = `${chainId}_${address}`;
|
||||
if (!this.instanceMap.has(key)) {
|
||||
const chain = new Chain(this.chainMap.get(chainId)!.rpc);
|
||||
const coinInstance = await chain.initContractInstance(address, abi);
|
||||
this.instanceMap.set(key, coinInstance);
|
||||
}
|
||||
return this.instanceMap.get(key);
|
||||
}
|
||||
|
||||
public async getBalance(address: string, chainId: number) {
|
||||
const coinInstance = await this.getInstance(address, chainId);
|
||||
const balance = await coinInstance.methods
|
||||
.balanceOf(AppModule.accountId)
|
||||
.call();
|
||||
console.log("balance: ", balance);
|
||||
return balance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get amount of mystery boxes
|
||||
* this method can get amount of general erc721 also
|
||||
* @param {string} address
|
||||
* @param {number} chainId
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
public async getNftBalance(address: string, chainId: number) {
|
||||
const coinInstance = await this.getInstance(
|
||||
address,
|
||||
chainId,
|
||||
MYSTERY_BOX_ABI
|
||||
);
|
||||
const balance = await coinInstance.methods
|
||||
.balanceOf(AppModule.accountId)
|
||||
.call();
|
||||
console.log("nft balance: ", balance);
|
||||
return balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NFT list of current user
|
||||
* @param {string} address NFT address
|
||||
* @param {number} chainId chain id
|
||||
* @param {number} start
|
||||
* @param {number} page
|
||||
*/
|
||||
public async getNftList(
|
||||
address: string,
|
||||
chainId: number,
|
||||
start = 0,
|
||||
page = 8
|
||||
) {
|
||||
const nftInstance = await this.getInstance(
|
||||
address,
|
||||
chainId,
|
||||
MYSTERY_BOX_ABI
|
||||
);
|
||||
return nftInstance.methods
|
||||
.userTokens(AppModule.accountId, start, page)
|
||||
.call();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NFT of current user with index
|
||||
* @param {string} address
|
||||
* @param {number} chainId
|
||||
* @param {number} index
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
public async getNftIdOfIndex(
|
||||
address: string,
|
||||
chainId: number,
|
||||
index: number
|
||||
) {
|
||||
const nftInstance = await this.getInstance(
|
||||
address,
|
||||
chainId,
|
||||
MYSTERY_BOX_ABI
|
||||
);
|
||||
const nftId = await nftInstance.methods
|
||||
.tokenOfOwnerByIndex(AppModule.accountId, index)
|
||||
.call();
|
||||
console.log(
|
||||
`address: ${address}, chainId: ${chainId}, index: ${index}, token: ${nftId}`
|
||||
);
|
||||
return nftId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open one mystery box
|
||||
* @param {string} address address of mystery box contract on current chain
|
||||
* @param {string} boxId nftid of mystery box
|
||||
* @param {number[]} tokenIds
|
||||
* @param {string} nonce
|
||||
* @param {string} signature
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
public async openMysteryBox(
|
||||
address: string,
|
||||
boxId: string,
|
||||
tokenIds: number[],
|
||||
nonce: string,
|
||||
signature: string
|
||||
) {
|
||||
const proxyInstance = await this.bc.getContractInstance(
|
||||
address,
|
||||
MYSTERY_PROXY_ABI
|
||||
);
|
||||
// get transactionHash and upload to server for verify
|
||||
return proxyInstance.methods
|
||||
.openBox(boxId, tokenIds, nonce, signature)
|
||||
.send({ gas: 1000000 });
|
||||
}
|
||||
|
||||
/**
|
||||
* activate one nft with 18 digital id
|
||||
* @param {string} address
|
||||
* @param {string} nftOld
|
||||
* @param {string} nftNew
|
||||
* @param {number} nftType
|
||||
* @param {string} nonce
|
||||
* @param {string} signature
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
public async activateOneNft(
|
||||
address: string,
|
||||
nftOld: string,
|
||||
nftNew: string,
|
||||
nftType: number,
|
||||
nonce: string,
|
||||
signature: string
|
||||
) {
|
||||
const nftProxyInstance = await this.bc.getContractInstance(
|
||||
address,
|
||||
ACTIVATE_PROXY_ABI
|
||||
);
|
||||
const gas = await nftProxyInstance.methods
|
||||
.activateOne(nftOld, nftNew, nftType, nonce, signature)
|
||||
.estimateGas({ gas: 1000000 });
|
||||
console.log("nftProxyInstance activateOne need gas: ", gas);
|
||||
return nftProxyInstance.methods
|
||||
.activateOne(nftOld, nftNew, nftType, nonce, signature)
|
||||
.send({ gas: (gas * 1.1) | 0 });
|
||||
}
|
||||
|
||||
public async transferToAccount({
|
||||
to,
|
||||
amount,
|
||||
chainId,
|
||||
address,
|
||||
}: {
|
||||
to: string;
|
||||
amount: number;
|
||||
chainId: number;
|
||||
address: string;
|
||||
}) {
|
||||
const self = this;
|
||||
if (chainId !== this.bc.currentChain) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.bc.switchEthereumChain(chainId, function () {
|
||||
self.bc
|
||||
.transferToAccount(to, amount, address)
|
||||
.then((res) => {
|
||||
resolve && resolve(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject && reject(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return this.bc.transferToAccount(to, amount, address);
|
||||
}
|
||||
}
|
||||
}
|
577
src/chain/blockchain.ts
Normal file
@ -0,0 +1,577 @@
|
||||
import WalletConnectProvider from "@walletconnect/web3-provider";
|
||||
import { useAppStore } from "@/store/app";
|
||||
import Web3 from "web3";
|
||||
import { AVAILABLE_CHAINS, CONTRACT_ADDRESS } from "@/configs/configchain";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import { isMobile } from "@/utils/resize";
|
||||
import { hasMetamask, toHexChainId } from "@/utils/chain.util";
|
||||
import { AllChains } from "@/configs/allchain";
|
||||
import { ERC20ABI,CLAIM_ABI} from "@/configs/contracts";
|
||||
import { TransactionReceipt } from "web3-core";
|
||||
import { useEventBus } from "@vueuse/core";
|
||||
import { Global } from "@/configs/global";
|
||||
import * as bus_event from "@/bus/event";
|
||||
import pinia from "@/store";
|
||||
|
||||
const EIP721_DOMAIN_DATA = [
|
||||
{ name: "name", type: "string" },
|
||||
{ name: "version", type: "string" },
|
||||
{ name: "chainId", type: "uint256" },
|
||||
{ name: "verifyingContract", type: "address" },
|
||||
];
|
||||
|
||||
const CACHE_KEY = "cebg_chain_cache_key";
|
||||
|
||||
const busShowChainModal = useEventBus(bus_event.SHOW_CHAIN_MODAL);
|
||||
const busNeedChangeChain = useEventBus(bus_event.NEED_CHANGE_CHAIN);
|
||||
const busNeedLogin = useEventBus(bus_event.NEED_LOGIN);
|
||||
const busNeedNonce = useEventBus(bus_event.NEED_NONCE);
|
||||
|
||||
const AppModule = useAppStore(pinia);
|
||||
const UserModule = useUserStore(pinia);
|
||||
|
||||
export class Blockchain {
|
||||
provider: any;
|
||||
web3: Web3;
|
||||
currentChain = 0;
|
||||
// 0: null, 1: metamask, 2: walletconnect
|
||||
walletType = 0;
|
||||
dataCached = false;
|
||||
instanceCacheMap: Map<string, any>;
|
||||
public chainMap: Map<number, any> = new Map();
|
||||
public rpc: any = {};
|
||||
|
||||
constructor() {
|
||||
const allChainMap: Map<number, any> = new Map();
|
||||
for (const d of AllChains) {
|
||||
const id = d.id;
|
||||
this.rpc[id] = d.rpc;
|
||||
allChainMap.set(id, d);
|
||||
}
|
||||
for (const id of AVAILABLE_CHAINS) {
|
||||
this.chainMap.set(id, allChainMap.get(id)!);
|
||||
}
|
||||
this.loadCachedProvider();
|
||||
this.instanceCacheMap = new Map();
|
||||
// AppModule.updateChainID(chainId)
|
||||
busNeedLogin.on(this.connect.bind(this));
|
||||
}
|
||||
|
||||
get isWalletConnect() {
|
||||
return !!this.walletType && !!this.currentChain;
|
||||
}
|
||||
|
||||
get mallAddress() {
|
||||
return CONTRACT_ADDRESS[this.currentChain]?.mall;
|
||||
}
|
||||
|
||||
public get hexChainId() {
|
||||
return toHexChainId(this.currentChain);
|
||||
}
|
||||
|
||||
public async chainSelected(id: number) {
|
||||
if (!this.chainMap.has(id)) {
|
||||
return;
|
||||
}
|
||||
this.currentChain = id;
|
||||
if (this.provider) {
|
||||
await this.switchEthereumChain();
|
||||
} else {
|
||||
await this.connectWallet(true);
|
||||
}
|
||||
}
|
||||
|
||||
public async connectWallet(isManual: boolean) {
|
||||
console.log(
|
||||
"begin connect to wallet: ",
|
||||
this.walletType,
|
||||
this.currentChain
|
||||
);
|
||||
if (this.walletType === 1) {
|
||||
this.provider = await this.connectMetaMask();
|
||||
} else if (this.walletType === 2) {
|
||||
this.provider = await this.connectWalletConnect();
|
||||
}
|
||||
if (!this.provider) {
|
||||
return;
|
||||
}
|
||||
this.web3 = new Web3(this.provider);
|
||||
|
||||
const chainId = await this.web3.eth.getChainId();
|
||||
await this.checkChain(chainId);
|
||||
|
||||
this.subscribeToEvents();
|
||||
const accounts = await this.web3.eth.getAccounts();
|
||||
if (accounts && accounts.length > 0) {
|
||||
AppModule.updateAccount(accounts[0]);
|
||||
}
|
||||
if (!this.currentChain) this.currentChain = chainId;
|
||||
this.saveProvider();
|
||||
AppModule.updateChainID(chainId);
|
||||
AppModule.updateWalletStatus(true);
|
||||
|
||||
console.log("current login chain: ", chainId);
|
||||
console.log("accountsLogin: ", accounts, AppModule.accountId);
|
||||
if (isManual) {
|
||||
busNeedNonce.emit(busNeedNonce);
|
||||
} else {
|
||||
AppModule.updateStep(1);
|
||||
}
|
||||
return { account: accounts[0], chainId };
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether special chainId is supported by config
|
||||
* show chain picker when chainId is not supported and current wallet is meatmask
|
||||
* show message box when chainId is not supported and current wallet is wallet connect
|
||||
* @param {number} chainId
|
||||
* @return {Promise<void>}
|
||||
* @private
|
||||
*/
|
||||
private async checkChain(chainId: number) {
|
||||
if (chainId !== AVAILABLE_CHAINS[0]) {
|
||||
// if (this.walletType === 1) {
|
||||
try {
|
||||
await this.selectChain();
|
||||
} catch (err) {
|
||||
await this.disconnect();
|
||||
}
|
||||
// } else if (this.walletType === 2) {
|
||||
// await this.disconnect()
|
||||
// this.walletType = 2
|
||||
// await MessageBox.alert(
|
||||
// 'You need to connect to supported network',
|
||||
// 'Wrong Network',
|
||||
// {
|
||||
// confirmButtonText: 'Confirm'
|
||||
// })
|
||||
// await this.connectWallet(true)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
public async connect(isManual = false) {
|
||||
// if (isMobile()) {
|
||||
// if (hasMetamask()) {
|
||||
// this.walletType = 1;
|
||||
// } else {
|
||||
// this.walletType = 2;
|
||||
// }
|
||||
// } else {
|
||||
// if (hasMetamask()) {
|
||||
// if (isManual && !this.walletType) {
|
||||
// this.walletType = await this.selectWallet();
|
||||
// }
|
||||
// } else {
|
||||
// this.walletType = 2;
|
||||
// }
|
||||
// }
|
||||
this.walletType = 1;
|
||||
if (isManual || this.isWalletConnect) {
|
||||
await this.connectWallet(isManual);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* show wallet picker
|
||||
* @return {Promise<number>}
|
||||
* @private
|
||||
*/
|
||||
private selectWallet(): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
busShowChainModal.emit({
|
||||
confirm: (id: number) => {
|
||||
console.log("select wallet: ", id);
|
||||
resolve && resolve(id);
|
||||
},
|
||||
cancel: (reason: any) => {
|
||||
console.log("cancel select wallet: ", reason);
|
||||
reject && reject(reason);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* show chain picker
|
||||
* @return {Promise<number>}
|
||||
* @private
|
||||
*/
|
||||
private selectChain(): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.switchEthereumChain(AVAILABLE_CHAINS[0], (res: any)=>{
|
||||
if (res.err) {
|
||||
reject && reject(res.err)
|
||||
return
|
||||
}
|
||||
resolve && resolve(res.chain)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async connectMetaMask() {
|
||||
let provider = null;
|
||||
if (typeof window.ethereum !== "undefined") {
|
||||
provider = window.ethereum;
|
||||
try {
|
||||
await provider.request({ method: "eth_requestAccounts" });
|
||||
} catch (error: any) {
|
||||
if (error.code === -32002) {
|
||||
// const hexChainId = toHexChainId(this.currentChain)
|
||||
// await provider.request({
|
||||
// method: 'wallet_switchEthereumChain',
|
||||
// params: [{ chainId: hexChainId }]
|
||||
// })
|
||||
throw new Error("MeatMask not login, Open MeatMask and login first");
|
||||
} else {
|
||||
throw new Error("User Rejected");
|
||||
}
|
||||
}
|
||||
} else if (window.web3) {
|
||||
provider = window.web3.currentProvider;
|
||||
} else if (window.celo) {
|
||||
provider = window.celo;
|
||||
} else {
|
||||
throw new Error("Cannot find Metamask");
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
|
||||
public async connectWalletConnect() {
|
||||
const provider = new WalletConnectProvider({
|
||||
infuraId: import.meta.env.VUE_APP_WALLET_INFURAID,
|
||||
rpc: this.rpc,
|
||||
});
|
||||
try {
|
||||
await provider.enable();
|
||||
} catch (err) {
|
||||
console.log("connect to wallet connect error: ", err);
|
||||
await Promise.reject(err);
|
||||
}
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
public async getContractInstance(address: string, abi: any = ERC20ABI) {
|
||||
if (!this.web3) {
|
||||
this.connectWallet(true)
|
||||
// throw new Error(
|
||||
// "Web3 instance is not initialized. Please call `initWeb3` method after user login."
|
||||
// );
|
||||
}
|
||||
if (!this.instanceCacheMap.has(address)) {
|
||||
const instance = new this.web3.eth.Contract(abi, address, {
|
||||
from: AppModule.accountId,
|
||||
});
|
||||
this.instanceCacheMap.set(address, instance);
|
||||
}
|
||||
return this.instanceCacheMap.get(address);
|
||||
}
|
||||
|
||||
public clearCachedProvider() {
|
||||
console.log("clear cached provider");
|
||||
localStorage.removeItem(CACHE_KEY);
|
||||
}
|
||||
|
||||
public loadCachedProvider() {
|
||||
const dataStr = localStorage.getItem(CACHE_KEY);
|
||||
if (dataStr) {
|
||||
try {
|
||||
const data = JSON.parse(dataStr);
|
||||
this.walletType = data.walletType;
|
||||
if (this.chainMap.has(data.chainId)) {
|
||||
this.currentChain = data.chainId;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err parse cached json");
|
||||
this.clearCachedProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public saveProvider() {
|
||||
const data = {
|
||||
walletType: this.walletType,
|
||||
chainId: this.currentChain,
|
||||
};
|
||||
localStorage.setItem(CACHE_KEY, JSON.stringify(data));
|
||||
}
|
||||
|
||||
public async disconnect() {
|
||||
try {
|
||||
await UserModule.Logout();
|
||||
await this.provider?.disconnect();
|
||||
} catch (err) {}
|
||||
this.currentChain = 0;
|
||||
this.walletType = 0;
|
||||
this.instanceCacheMap.clear();
|
||||
this.clearCachedProvider();
|
||||
AppModule.updateStep(0);
|
||||
AppModule.updateChainID(0);
|
||||
AppModule.updateNonce("");
|
||||
AppModule.updateAccount("");
|
||||
AppModule.updateWalletStatus(false);
|
||||
}
|
||||
|
||||
public subscribeToEvents = () => {
|
||||
// Subscribe to accounts change
|
||||
this.provider.on("accountsChanged", async (accounts: string[]) => {
|
||||
console.log("accountsChanged: ", accounts);
|
||||
if (accounts && accounts.length > 0) {
|
||||
if (AppModule.accountId !== accounts[0]) {
|
||||
await UserModule.Logout();
|
||||
|
||||
this.currentChain = 0;
|
||||
this.walletType = 0;
|
||||
this.instanceCacheMap.clear();
|
||||
this.clearCachedProvider();
|
||||
AppModule.updateStep(0);
|
||||
AppModule.updateChainID(0);
|
||||
AppModule.updateNonce("");
|
||||
AppModule.updateAccount("");
|
||||
AppModule.updateWalletStatus(false);
|
||||
localStorage.removeItem("totalSupply");
|
||||
localStorage.removeItem("supplyLimit");
|
||||
localStorage.removeItem("mintableCount");
|
||||
location.reload();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Subscribe to chainId change
|
||||
this.provider.on("chainChanged", async (chainId: string) => {
|
||||
const chainIdNum = parseInt(chainId);
|
||||
console.log("chainChanged", chainId, chainIdNum);
|
||||
await this.checkChain(chainIdNum);
|
||||
this.currentChain = chainIdNum;
|
||||
this.saveProvider();
|
||||
AppModule.updateChainID(this.currentChain);
|
||||
});
|
||||
|
||||
// Subscribe to session disconnection
|
||||
this.provider.on("disconnect", (err: any) => {
|
||||
console.log("disconnect", err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* change chain of metamask
|
||||
* @param {number} chainId
|
||||
* @param {() => void} cb
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async switchEthereumChain(chainId?: number, cb?: (res: any) => void) {
|
||||
chainId = chainId || AVAILABLE_CHAINS[0];
|
||||
const hexChainId = toHexChainId(chainId);
|
||||
const onChainChange = (chainId: string) => {
|
||||
console.log("switchEthereumChain: ", chainId);
|
||||
this.provider.removeListener("chainChanged", onChainChange);
|
||||
cb && cb({chain: chainId});
|
||||
};
|
||||
this.provider.on("chainChanged", onChainChange);
|
||||
try {
|
||||
const data = this.chainMap.get(chainId)!;
|
||||
await this.provider.request({
|
||||
method: "wallet_addEthereumChain",
|
||||
params: [
|
||||
{
|
||||
chainId: hexChainId,
|
||||
chainName: data.name,
|
||||
nativeCurrency: {
|
||||
name: data.symbol,
|
||||
symbol: data.symbol,
|
||||
decimals: data.decimals || 18,
|
||||
},
|
||||
blockExplorerUrls: [data.explorerurl],
|
||||
rpcUrls: [data.rpc],
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log("add chain success");
|
||||
} catch (addError) {
|
||||
console.error("add chain error: ", addError);
|
||||
this.provider.removeListener("chainChanged", onChainChange);
|
||||
cb && cb({err: addError})
|
||||
}
|
||||
}
|
||||
|
||||
public async getTransactionReceipt(txHash: string) {
|
||||
return this.web3.eth.getTransactionReceipt(txHash);
|
||||
}
|
||||
|
||||
public async getTxConfirms(txhash: string) {
|
||||
const receipt: TransactionReceipt = await this.getTransactionReceipt(
|
||||
txhash
|
||||
);
|
||||
const latest = await this.web3.eth.getBlockNumber();
|
||||
return latest - receipt.blockNumber + 1;
|
||||
}
|
||||
|
||||
public async signPresale({
|
||||
type,
|
||||
paymentTokenAddress,
|
||||
price,
|
||||
buyerAddress,
|
||||
netId,
|
||||
}: {
|
||||
type: number | string;
|
||||
paymentTokenAddress: string;
|
||||
price: any;
|
||||
buyerAddress: string;
|
||||
netId?: any;
|
||||
}) {
|
||||
const nonce = (Math.random() * 100000) | 0;
|
||||
|
||||
const signMsg = {
|
||||
item: type,
|
||||
token: paymentTokenAddress,
|
||||
price: price,
|
||||
salt: nonce,
|
||||
};
|
||||
netId = netId || (await this.web3.eth.getChainId());
|
||||
const signObj = {
|
||||
types: {
|
||||
EIP712Domain: EIP721_DOMAIN_DATA,
|
||||
set: [
|
||||
{ name: "item", type: "uint256" },
|
||||
{ name: "token", type: "address" },
|
||||
{ name: "price", type: "uint256" },
|
||||
{ name: "salt", type: "uint256" },
|
||||
],
|
||||
},
|
||||
primaryType: "set",
|
||||
domain: {
|
||||
name: "BEBoxMall",
|
||||
version: "1",
|
||||
chainId: netId,
|
||||
verifyingContract: this.mallAddress,
|
||||
},
|
||||
message: signMsg,
|
||||
};
|
||||
const signature = await this.signData(signObj, buyerAddress);
|
||||
return { nonce, signature };
|
||||
}
|
||||
|
||||
public async increaseAllowance(address: string, price: string) {
|
||||
const coinInstance: any = await this.getContractInstance(address);
|
||||
const res = await coinInstance.methods
|
||||
.increaseAllowance(this.mallAddress, price)
|
||||
.send({ gas: 1000000 });
|
||||
console.log("increaseAllowance: ", res);
|
||||
}
|
||||
public async claimReward(address: string,startTime:string,saltNonce:string,signature:string) {
|
||||
const coinInstance: any = await this.getContractInstance(
|
||||
Global.LIMIT_ABI_Address,
|
||||
CLAIM_ABI
|
||||
);
|
||||
let gas = await coinInstance.methods.claim(address,startTime,saltNonce,signature).estimateGas()
|
||||
gas = gas * 1.1 | 0
|
||||
console.log('gas:: ' , gas)
|
||||
let gasPrice = await this.web3.eth.getGasPrice()
|
||||
const res = await coinInstance.methods.claim(address,startTime,saltNonce,signature).send({gas, gasPrice});
|
||||
console.log("claimReward: ", res);
|
||||
return res
|
||||
}
|
||||
public async getBalances( account: string ) {
|
||||
account = account || AppModule.accountId
|
||||
const coinInstance: any = await this.getContractInstance(
|
||||
Global.LIMIT_ABI_Address,
|
||||
CLAIM_ABI
|
||||
);
|
||||
return await coinInstance.methods.claimHistory(account).call()
|
||||
}
|
||||
// public async totalSupply(address: string) {
|
||||
// const coinInstance: any = await this.getContractInstance(
|
||||
// Global.LIMIT_ABI_Address,
|
||||
// LIMIT_ABI
|
||||
// );
|
||||
// const res = await coinInstance.methods.totalSupply().call();
|
||||
// console.log("totalSupply: ", res);
|
||||
// return res
|
||||
// }
|
||||
// // 获取当前用户可mint的数量
|
||||
// public async getMintableCount(address?: string) {
|
||||
// // address = address || //TODO: current address
|
||||
// const coinInstance: any = await this.getContractInstance(
|
||||
// Global.MEDAL_REWARDS_Address,
|
||||
// MEDAL_REWARDS_ABI
|
||||
// );
|
||||
// const res = await coinInstance.methods
|
||||
// .getMintableCount(AppModule.accountId)
|
||||
// .call();
|
||||
// console.log("getMintableCount: ", res);
|
||||
// return res
|
||||
// }
|
||||
// // 获取当前用户的mint总数
|
||||
// public async supplyLimit(address: string) {
|
||||
// const coinInstance: any = await this.getContractInstance(
|
||||
// Global.LIMIT_ABI_Address,
|
||||
// LIMIT_ABI
|
||||
// );
|
||||
// const res = await coinInstance.methods.supplyLimit().call();
|
||||
// console.log("supplyLimit: ", res);
|
||||
// return res
|
||||
// }
|
||||
/**
|
||||
* @param {string} address
|
||||
* @param {string | null} account
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
// public async getBalance(address: string, account: string | null) {
|
||||
// account = account || AppModule.accountId;
|
||||
// const coinInstance: any = await this.getContractInstance(address);
|
||||
// return await coinInstance.methods.balanceOf(account).call();
|
||||
// }
|
||||
public async getBalance(address: string, account: string | null) {
|
||||
account = account || AppModule.accountId
|
||||
const coinInstance: any = await this.getContractInstance(address)
|
||||
return await coinInstance.methods.claimHistory(account).call()
|
||||
}
|
||||
public async transferToAccount(
|
||||
account: string,
|
||||
amount: number,
|
||||
address: string
|
||||
) {
|
||||
const amountBN = this.web3.utils.toBN(this.web3.utils.toWei(amount + ""));
|
||||
const coinInstance: any = await this.getContractInstance(address);
|
||||
return coinInstance.methods
|
||||
.transfer(account, amountBN)
|
||||
.send({ gas: 1000000 });
|
||||
}
|
||||
|
||||
public async signData(signObj: any, signer: string) {
|
||||
const msgParams = JSON.stringify(signObj);
|
||||
const from = signer;
|
||||
console.log("clicked, sending personal sign req", "from", from, msgParams);
|
||||
const params = [from, msgParams];
|
||||
const result: any = await this.sendCmd({
|
||||
method: "eth_signTypedData_v4",
|
||||
params,
|
||||
from,
|
||||
});
|
||||
console.log(result);
|
||||
return result.result;
|
||||
}
|
||||
|
||||
public async sendCmd({ method, params, from }: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
this.web3.currentProvider.sendAsync(
|
||||
{
|
||||
method,
|
||||
params,
|
||||
from,
|
||||
},
|
||||
async function (err: any, result: any) {
|
||||
if (err) {
|
||||
reject && reject(err);
|
||||
return;
|
||||
}
|
||||
resolve && resolve(result);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
119
src/components/global/Notification.vue
Normal file
@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<transition-group name="slide" tag="div">
|
||||
<div
|
||||
v-for="(notification, index) in notifications"
|
||||
:key="notification.id"
|
||||
class="notification"
|
||||
:class="position"
|
||||
>
|
||||
<span>{{ notification.message }}</span>
|
||||
</div>
|
||||
</transition-group>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, watchEffect } from "vue";
|
||||
|
||||
let id = 0;
|
||||
|
||||
const props = defineProps({
|
||||
position: {
|
||||
type: String,
|
||||
default: "top-right",
|
||||
validator: (value) =>
|
||||
["top-right", "top-left", "bottom-right", "bottom-left"].includes(value),
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 3000,
|
||||
},
|
||||
});
|
||||
|
||||
const notifications = reactive([]);
|
||||
|
||||
const addNotification = (message) => {
|
||||
const notification = {
|
||||
id: id++,
|
||||
message,
|
||||
};
|
||||
|
||||
notifications.push(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
closeNotification(notifications.indexOf(notification));
|
||||
}, props.duration);
|
||||
};
|
||||
|
||||
const closeNotification = (index) => {
|
||||
if (index !== -1) {
|
||||
notifications.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
addNotification,
|
||||
closeNotification,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.slide-enter-active,
|
||||
.slide-leave-active {
|
||||
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
|
||||
}
|
||||
|
||||
.slide-enter-from,
|
||||
.slide-leave-to {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.slide-enter-to,
|
||||
.slide-leave-from {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.notification {
|
||||
position: fixed;
|
||||
padding: 0.8em;
|
||||
background: url('../../assets/img/task/msg-bg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #721c24;
|
||||
/* border: solid 1px #f5c6cb; */
|
||||
border-radius: 0.25rem;
|
||||
min-width: 304px;
|
||||
min-height: 80px; /* set minimum height */
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-family: Arial;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
|
||||
}
|
||||
|
||||
.notification.top-right {
|
||||
right: 50px;
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
.notification.top-left {
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.notification.bottom-right {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.notification.bottom-left {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
213
src/components/home/ChainModel.vue
Normal file
@ -0,0 +1,213 @@
|
||||
<template>
|
||||
<div class="chain-modal" v-if="modalShow" :class="{ mobile: 'mobile' }">
|
||||
<div class="modal-bg" @click="cancelSelect"></div>
|
||||
<div class="modal-content" :class="{ mobile: 'mobile' }">
|
||||
<div class="modal-title">You need to connect to supported network</div>
|
||||
<div
|
||||
class="chain-modal-card"
|
||||
v-for="data in currentDatas"
|
||||
:key="data.name"
|
||||
@click="cardClicked(data.id)"
|
||||
>
|
||||
<div class="icon">
|
||||
<img :src="data.logo" :alt="data.name" />
|
||||
</div>
|
||||
<div class="name">{{ data.name }}</div>
|
||||
<div class="desc">{{ data.desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted } from "vue";
|
||||
import { ALL_PROVIDERS } from "@/configs/configchain";
|
||||
import { useChainStore } from "@/store/chain";
|
||||
import { useEventBus } from "@vueuse/core";
|
||||
import * as bus_event from "@/bus/event";
|
||||
|
||||
const busShowChainModal = useEventBus(bus_event.SHOW_CHAIN_MODAL);
|
||||
const busNeedChangeChain = useEventBus(bus_event.NEED_CHANGE_CHAIN);
|
||||
|
||||
const chain = useChainStore();
|
||||
const modalShow = ref(false);
|
||||
const dataType = ref(1);
|
||||
const chainDatas = computed(() => {
|
||||
// console.log([...chain.chainManager.availableChains.values()]);
|
||||
return [...chain.chainManager.availableChains.values()];
|
||||
});
|
||||
// const currentDatas = computed(()=> {
|
||||
// if (dataType.value===0) {
|
||||
// //console.log({ALL_PROVIDERS});
|
||||
// return ALL_PROVIDERS;
|
||||
// } else if (dataType.value===1) {
|
||||
// //console.log({chainDatas});
|
||||
// return chainDatas.value;
|
||||
// } else {
|
||||
// //console.log("error=====");
|
||||
// return [];
|
||||
// }
|
||||
// });
|
||||
const currentDatas = computed(() => {
|
||||
return (
|
||||
{
|
||||
0: ALL_PROVIDERS,
|
||||
1: chainDatas.value,
|
||||
}[dataType.value] || []
|
||||
);
|
||||
});
|
||||
|
||||
let confirmFun = (id) => {};
|
||||
let cancelFun = (reason) => {};
|
||||
|
||||
onMounted(() => {
|
||||
busShowChainModal.on(showSelectWallet);
|
||||
busNeedChangeChain.on(showChangeChain);
|
||||
});
|
||||
onUnmounted(() => {
|
||||
busShowChainModal.off(showSelectWallet);
|
||||
busNeedChangeChain.off(showChangeChain);
|
||||
});
|
||||
|
||||
function showSelectWallet({ confirm, cancel }) {
|
||||
confirmFun = confirm;
|
||||
cancelFun = cancel;
|
||||
showModal(0);
|
||||
}
|
||||
|
||||
function showChangeChain({ confirm, cancel }) {
|
||||
confirmFun = confirm;
|
||||
cancelFun = cancel;
|
||||
// showModal(0);
|
||||
cancelSelect();
|
||||
}
|
||||
|
||||
function cardClicked(id) {
|
||||
console.log("card clicked:", id);
|
||||
confirmFun && confirmFun(id);
|
||||
hideModal();
|
||||
}
|
||||
|
||||
function cancelSelect() {
|
||||
cancelFun();
|
||||
hideModal();
|
||||
}
|
||||
|
||||
function showModal(type) {
|
||||
|
||||
dataType.value = type;
|
||||
modalShow.value = true;
|
||||
}
|
||||
|
||||
function hideModal() {
|
||||
|
||||
modalShow.value = false;
|
||||
// confirmFun = (id) => {
|
||||
// console.log(id);
|
||||
// };
|
||||
// cancelFun = (reason) => {
|
||||
// console.log(reason);
|
||||
// };
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.chain-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
z-index: 10;
|
||||
.modal-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
background-color: #000000a3;
|
||||
}
|
||||
.modal-content {
|
||||
width: 500px;
|
||||
max-height: 400px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.mobile {
|
||||
width: 100vw;
|
||||
}
|
||||
.modal-title {
|
||||
background-color: rgb(255, 255, 255);
|
||||
color: black;
|
||||
border-radius: 12px 12px 0 0;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid rgba(195, 195, 195, 0.14);
|
||||
}
|
||||
.chain-modal-card {
|
||||
background-color: rgb(255, 255, 255);
|
||||
transition: background-color 0.2s ease-in-out 0s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
padding: 24px 16px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
&:first-child {
|
||||
border-radius: 12px 12px 0 0;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid rgba(195, 195, 195, 0.14);
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 0 12px 12px;
|
||||
}
|
||||
.icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
display: flex;
|
||||
border-radius: 50%;
|
||||
overflow: visible;
|
||||
box-shadow: none;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.icon-svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: currentColor;
|
||||
color: unset;
|
||||
stroke: none;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-top: 0.5em;
|
||||
color: rgb(12, 12, 13);
|
||||
}
|
||||
.desc {
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
margin: 0.333em 0px;
|
||||
color: rgb(169, 169, 188);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
603
src/components/layout/NavBar.vue
Normal file
@ -0,0 +1,603 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="header header-top">
|
||||
<div class="header-left">
|
||||
<div class="header-logo">
|
||||
<a href="/"
|
||||
><img src="../../assets/img/planet/header-logo.png" alt=""
|
||||
/></a>
|
||||
</div>
|
||||
<div class="nav">
|
||||
<a
|
||||
class="nav-item duration-200"
|
||||
v-for="(nav, i) in navList"
|
||||
:class="getNavItemClass(i, nav)"
|
||||
:key="i"
|
||||
@click="handNavCurent(nav)"
|
||||
>
|
||||
<span> {{ nav.name }}</span>
|
||||
<div class="dropdown">
|
||||
<ul>
|
||||
<li v-for="(item, index) in nav.submenu" :key="index">
|
||||
<div
|
||||
class="link-content"
|
||||
v-if="i !== 2"
|
||||
@click="openThirdPartyLink(item.link)"
|
||||
>
|
||||
<div>
|
||||
<a
|
||||
class="link-name"
|
||||
:href="item.link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>{{ item.label }}</a
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
:href="item.link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img
|
||||
class="link-img"
|
||||
src="../../assets/img/home/link-icon.png"
|
||||
alt=""
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="link-label">{{ item.label }}</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header-right">
|
||||
<div class="community-btn">Community</div>
|
||||
<div class="metaMask-login">
|
||||
<div class="metaMask-logo">
|
||||
<img src="../../assets/img/planet/wallet_icon.png" alt="" />
|
||||
</div>
|
||||
<div class="matamask">
|
||||
<div>Connect</div>
|
||||
<div>wallet</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div
|
||||
v-if="!chain.logined"
|
||||
class="login-btn login-btn-active"
|
||||
@click="login"
|
||||
>
|
||||
LOGIN
|
||||
</div>
|
||||
<div v-else class="avatar" @click="showMenu = !showMenu">
|
||||
<img
|
||||
class="avatar-img"
|
||||
src="../../assets/img/home/avatar.png"
|
||||
alt="用户头像"
|
||||
/>
|
||||
|
||||
<div class="menu" v-show="showMenu">
|
||||
<div class="menu-item-top">
|
||||
<div class="title">{{ formatAddress }}</div>
|
||||
<div @click="handleCopy">
|
||||
<img src="../../assets/img/home/copy.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-item" @click="logout">Logout</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<ChainModel></ChainModel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed, watchEffect } from "vue";
|
||||
import { useChainStore } from "@/store/chain";
|
||||
import { useAppStore } from "@/store/app";
|
||||
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import ChainModel from "@/components/home/ChainModel.vue";
|
||||
import { useCopyToClipboard } from "./../../hooks/useCopyToClipboard";
|
||||
|
||||
const AppModule = useAppStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const chain = useChainStore();
|
||||
const app = useAppStore();
|
||||
|
||||
function click(event) {
|
||||
router.push(event.key);
|
||||
}
|
||||
//const { copied, copyToClipboard } = useCopyToClipboard(AppModule.accountId);
|
||||
const { copied, error, reset, copyToClipboard } = useCopyToClipboard();
|
||||
|
||||
const message = copied.value
|
||||
? "Text copied!"
|
||||
: "Click the button to copy text.";
|
||||
const formatAddress = computed(() => {
|
||||
const accountId = AppModule.accountId;
|
||||
if (!accountId) return "-";
|
||||
if (accountId.length >= 10) {
|
||||
return `${accountId.substring(0, 6)}......${accountId.slice(-4)}`;
|
||||
}
|
||||
return accountId;
|
||||
});
|
||||
const getNavItemClass = (index, nav) => {
|
||||
if (index === activeIndex.value) {
|
||||
return "active-nav-item";
|
||||
} else if (index === 5) {
|
||||
return "badge-nav-item";
|
||||
} else if (index === 6) {
|
||||
return "task-nav-item"; // Add the desired class for index 6
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
async function login(event) {
|
||||
if (!chain.logined) {
|
||||
//没有登录情况下执行登录
|
||||
|
||||
await chain.chainManager.login();
|
||||
// console.log("logined:", chain.chainManager.isLogined);
|
||||
chain.logined = chain.chainManager.isLogined;
|
||||
}
|
||||
}
|
||||
const logout = async () => {
|
||||
await chain.chainManager.logout();
|
||||
window.location.reload();
|
||||
// console.log("logined:", chain.chainManager.isLogined);
|
||||
chain.logined = chain.chainManager.isLogined;
|
||||
window.location.reload();
|
||||
};
|
||||
const avatarUrl = ref("https://example.com/avatar.jpg");
|
||||
const showMenu = ref(false);
|
||||
const showNavMenu = ref(false);
|
||||
const activeIndex = ref(0);
|
||||
const navList = reactive([
|
||||
{ id: 0, name: "MAP", path: "/" },
|
||||
{ id: 1, name: "TEH GAME", path: "/about" },
|
||||
{
|
||||
id: 2,
|
||||
name: "STAKE",
|
||||
path: "/marketpalce",
|
||||
submenu: [{ label: "Coming soon", link: "/products/1" }],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "MORE",
|
||||
path: "/contact",
|
||||
submenu: [
|
||||
{ label: "Twitter", link: "https://twitter.com/CEBG_GAME" },
|
||||
{
|
||||
label: "Youtube",
|
||||
link: "https://youtube.com/c/CryptoElitesBattlegrounds",
|
||||
},
|
||||
{
|
||||
label: "Facebook",
|
||||
link: "https://www.facebook.com/profile.php?id=100090965821157&mibextid=LQQJ4d",
|
||||
},
|
||||
{ label: "Medium", link: "https://medium.com/@CEBG-BATTLEGROUNDS" },
|
||||
{ label: "Telegram", link: "https://t.me/CEBG_Rally" },
|
||||
{ label: "Discord", link: "https://discord.com/invite/fNSn2NHUvf" },
|
||||
],
|
||||
},
|
||||
// { id: 4, name: "BETA TEST II", path: "/" },
|
||||
// { id: 5, name: "BADGE", path: "https://badge.kingsome.cn" },
|
||||
// { id: 6, name: "TASK", path: "/task" },
|
||||
]);
|
||||
|
||||
//{ id: 5, name: "BADGE", path: "https://badge.kingsome.cn" },
|
||||
function handNavCurent(nav) {
|
||||
activeIndex.value = nav.id;
|
||||
if (nav.id === 0 || nav.id === 1 || (nav.id === 4) | (nav.id === 6)) {
|
||||
router.push(nav.path);
|
||||
} else if (nav.id === 5) {
|
||||
window.location.href = nav.path;
|
||||
//window.open(nav.path, "_blank");
|
||||
}
|
||||
}
|
||||
function openThirdPartyLink(url) {
|
||||
window.open(url, "_blank");
|
||||
}
|
||||
const handleCopy = () => {
|
||||
const accountId = AppModule.accountId;
|
||||
reset();
|
||||
copyToClipboard(accountId).then(() => {
|
||||
// if (copied.value) {
|
||||
// message.success("Copy successful!");
|
||||
// }
|
||||
});
|
||||
};
|
||||
watchEffect(() => {
|
||||
const index = navList.findIndex(
|
||||
(navItem) => route.path.slice(0, 5) === navItem.path.slice(0, 5)
|
||||
);
|
||||
activeIndex.value = index !== -1 ? index : 0;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
position: fixed;
|
||||
z-index: 19;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #0e0e0e;
|
||||
width: 100%;
|
||||
height: 84px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 11px;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
||||
.header-left{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.header-logo {
|
||||
margin-left: 64px;
|
||||
width: 194px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
padding-left: 83px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
// width: 830px;
|
||||
a {
|
||||
padding-top: 29px;
|
||||
padding-bottom: 29px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
font-weight: 800;
|
||||
padding-left: 64px;
|
||||
padding-right: 64px;
|
||||
transition-property: color;
|
||||
transition-duration: 0.15s;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-family: "Big John";
|
||||
font-size: 18px;
|
||||
color: #cccccc;
|
||||
.dropdown {
|
||||
position: absolute;
|
||||
top: 84px;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
background: rgba(0, 0, 0, 0.84);
|
||||
border-radius: 0px 0px 12px 12px;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
transform: translate(-50%, 0%);
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
.dropdown ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.dropdown li {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.link-content {
|
||||
display: flex;
|
||||
// width: 150px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.link-label {
|
||||
font-size: 16px;
|
||||
font-family: Arial;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
.dropdown li a {
|
||||
font-size: 16px;
|
||||
font-family: Arial;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
.dropdown li span {
|
||||
font-size: 15px;
|
||||
font-family: Arial;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.duration-200 {
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
.nav-item:hover {
|
||||
transition-property: color;
|
||||
transition-duration: 0.15s;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-family: "Big John";
|
||||
background-color: #2dadb2;
|
||||
color: rgba(12, 12, 12, 1);
|
||||
}
|
||||
.nav-item:hover .dropdown {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
// .nav-item::after {
|
||||
// content: "";
|
||||
// height: 7px;
|
||||
// overflow: hidden;
|
||||
// display: block;
|
||||
// left: 0;
|
||||
// bottom: 0;
|
||||
// position: absolute;
|
||||
// width: 100%;
|
||||
// // background: #1fc8ff;
|
||||
// background: url("@/assets/img/home/nav-boder.png") no-repeat;
|
||||
// background-size: 100% 100%;
|
||||
// transform: scaleX(0);
|
||||
|
||||
// transition: all 0.3s;
|
||||
// }
|
||||
// .nav-item:hover::after {
|
||||
// transform: scaleX(1);
|
||||
// }
|
||||
|
||||
.active-nav-item {
|
||||
font-size: 16px;
|
||||
font-family: "Big John";
|
||||
position: relative;
|
||||
font-weight: 800;
|
||||
background-color: #2dadb2;
|
||||
transition-property: color;
|
||||
transition-duration: 0.3s;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
color: rgba(12, 12, 12, 1);
|
||||
}
|
||||
|
||||
// .active-nav-item::after {
|
||||
// content: "";
|
||||
// height: 8px;
|
||||
// overflow: hidden;
|
||||
// display: block;
|
||||
// left: -7%;
|
||||
// bottom: 0;
|
||||
// position: absolute;
|
||||
// width: 120%;
|
||||
// // background: #1fc8ff;
|
||||
// background: url("@/assets/img/home/nav-boder.png") no-repeat;
|
||||
// background-size: 100% 100%;
|
||||
// transform: scaleX(0);
|
||||
// transition: all 0.3s;
|
||||
// }
|
||||
// .active-nav-item::after {
|
||||
// transform: scaleX(1);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
.header-right {
|
||||
// width: 228px;
|
||||
// position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
// right: 11px;
|
||||
.community-btn {
|
||||
width: 218px;
|
||||
height: 68px;
|
||||
background: #2a2b3e;
|
||||
margin-right: 10px;
|
||||
text-align: center;
|
||||
line-height: 68px;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-family: "Poppins";
|
||||
font-weight: 400;
|
||||
color: #eeecff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.metaMask-login {
|
||||
width: 218px;
|
||||
height: 68px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
background: #2a2b3e;
|
||||
font-size: 20px;
|
||||
font-family: "Poppins";
|
||||
font-weight: 400;
|
||||
color: #eeecff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: 111%;
|
||||
right: -35px;
|
||||
width: 180px;
|
||||
z-index: 1;
|
||||
padding: 10px 0;
|
||||
background-color: #000000;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
list-style: none;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
li {
|
||||
margin: 5px 0;
|
||||
}
|
||||
.menu-item-top {
|
||||
padding: 10px 15px;
|
||||
color: #f5f5f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding-bottom: 15px;
|
||||
.title {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
.menu-item-top:before {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 15px;
|
||||
content: "";
|
||||
width: 140px;
|
||||
height: 1px;
|
||||
background: #676767;
|
||||
}
|
||||
.menu-item {
|
||||
padding: 5px 15px;
|
||||
color: #f5f5f5;
|
||||
display: flex;
|
||||
padding-top: 10px;
|
||||
align-items: center;
|
||||
.title {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
a:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
.login-btn {
|
||||
position: relative;
|
||||
width: 228px;
|
||||
height: 65px;
|
||||
font-size: 26px;
|
||||
line-height: 65px;
|
||||
font-size: 22px;
|
||||
font-family: "Big John";
|
||||
color: #122326;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
background: url("@/assets/svg/login-active.svg") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
z-index: 0;
|
||||
transition: background-image 1s;
|
||||
// transition:background-image 1s linear;
|
||||
// transform: scaleX(1);
|
||||
// transition: all 0.15s;
|
||||
// transition-property: background;
|
||||
// transition-duration: 0.15s;
|
||||
// transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.login-btn::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
opacity: 1;
|
||||
// transition: 0.5s;
|
||||
background: url("@/assets/svg/login.svg") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
transform: scaleX(1, 1);
|
||||
clip-path: polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%);
|
||||
transition: all 0.3s ease-in-out;
|
||||
z-index: -1;
|
||||
// transition:background-image 1s linear;
|
||||
// transform: scaleX(0.98);
|
||||
}
|
||||
.login-btn:hover {
|
||||
color: #ffba00;
|
||||
}
|
||||
.login-btn:hover:after {
|
||||
opacity: 1;
|
||||
clip-path: polygon(
|
||||
calc(50% + 0px) calc(50% + 150px),
|
||||
calc(50% + 150px) calc(50% + 0px),
|
||||
calc(50% + 0px) calc(50% - 150px),
|
||||
calc(50% - 150px) calc(50% - 0px)
|
||||
);
|
||||
color: #ffba00;
|
||||
transition: all 0.3s ease-in-out;
|
||||
transform: scaleX(1, 1);
|
||||
}
|
||||
.login-btn:active:after {
|
||||
opacity: 1;
|
||||
color: #ffba00;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
.avatar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.avatar-img {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
margin-top: 5px;
|
||||
margin-right: 30px;
|
||||
border: 2px solid #ffba00;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.link-name {
|
||||
position: relative;
|
||||
.link-img {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
right: -18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1440px) {
|
||||
.header {
|
||||
.header-logo {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.nav {
|
||||
padding-left: 40px;
|
||||
.nav-item {
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
.dropdown {
|
||||
top: 63px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.header-right {
|
||||
width: 200px;
|
||||
right: -20px;
|
||||
.menu {
|
||||
right: -20px;
|
||||
}
|
||||
}
|
||||
.login-btn {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-btn {
|
||||
width: 181px;
|
||||
height: 51px;
|
||||
border: 1px solid #ffffff;
|
||||
clip-path: polygon(
|
||||
10% 0,
|
||||
/* 左上角缺角的位置 */ 100% 0,
|
||||
100% 90%,
|
||||
/* 右下角缺角的位置 */ 0 100%,
|
||||
0 0
|
||||
);
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
50
src/components/layout/index.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="layout">
|
||||
<NavBar></NavBar>
|
||||
<router-view> </router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import NavBar from "./NavBar.vue";
|
||||
|
||||
const currentRoute = useRoute();
|
||||
const showLoading = ref(false);
|
||||
|
||||
const startLoading = () => {
|
||||
showLoading.value = true;
|
||||
};
|
||||
|
||||
const stopLoading = () => {
|
||||
showLoading.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
/*定义进入开始和离开结束的透明度为0*/
|
||||
opacity: 0;
|
||||
}
|
||||
.fade-leave-to {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
.fade-enter-to {
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
.fade-enter-to,
|
||||
.fade-leave-from {
|
||||
/*定义进入结束和离开开始的透明度为1*/
|
||||
opacity: 1;
|
||||
}
|
||||
.fade-leave-active,
|
||||
.fade-enter-active {
|
||||
transition: all 0.32s ease-out;
|
||||
}
|
||||
</style>
|
229
src/components/layout/navber.vue
Normal file
@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<div class="naber">
|
||||
<div class="content">
|
||||
<div class="logo" @click="handTaskHome">
|
||||
<a ><img src="@/assets/img/task/logo.png" alt="" /></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="twitter">
|
||||
<a
|
||||
href="https://twitter.com/_CounterFire"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img src="@/assets/img/task/TW.png" alt=""
|
||||
/></a>
|
||||
</div>
|
||||
<div class="discode">
|
||||
<a
|
||||
href="https://discord.com/invite/fNSn2NHUvf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
><img src="@/assets/img/task/DC.png" alt=""
|
||||
/></a>
|
||||
</div>
|
||||
<div v-if="!chain.logined" class="login-btn" @click="login">
|
||||
Connect Wallet
|
||||
</div>
|
||||
<div v-else class="login-btn-active" @click="showMenu = !showMenu">
|
||||
{{ formatAddress }}
|
||||
<div class="menu" v-show="showMenu">
|
||||
<div class="menu-item" @click="logout">Disconnect</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed, watchEffect } from "vue";
|
||||
import { useChainStore } from "@/store/chain";
|
||||
import { useAppStore } from "@/store/app";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { UserStatus } from "@/api/User";
|
||||
import ChainModel from "@/components/home/ChainModel.vue";
|
||||
import { useCopyToClipboard } from "./../../hooks/useCopyToClipboard";
|
||||
import { hasMetamask } from "@/utils/chain.util";
|
||||
|
||||
const AppModule = useAppStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const showMenu = ref(false);
|
||||
const chain = useChainStore();
|
||||
const app = useAppStore();
|
||||
const { copied, error, reset, copyToClipboard } = useCopyToClipboard();
|
||||
const emit = defineEmits(["login-success"]);
|
||||
const formatAddress = computed(() => {
|
||||
const accountId = AppModule.accountId;
|
||||
if (!accountId) return "-";
|
||||
if (accountId.length >= 10) {
|
||||
return `${accountId.substring(0, 6)}......${accountId.slice(-4)}`;
|
||||
}
|
||||
return accountId;
|
||||
});
|
||||
async function login(event) {
|
||||
var next = window.location.href;
|
||||
if (!hasMetamask()) {
|
||||
var url = `https://metamask.app.link/dapp/${next}`;
|
||||
location.href = url;
|
||||
} else {
|
||||
if (!chain.logined) {
|
||||
//没有登录情况下执行登录
|
||||
|
||||
await chain.chainManager.login();
|
||||
// console.log("logined:", chain.chainManager.isLogined);
|
||||
chain.logined = chain.chainManager.isLogined;
|
||||
const resq = await UserStatus({
|
||||
account: AppModule.accountId,
|
||||
invite_code: route.query.code,
|
||||
});
|
||||
emit("login-success");
|
||||
}
|
||||
}
|
||||
}
|
||||
const logout = async () => {
|
||||
await chain.chainManager.logout();
|
||||
window.location.reload();
|
||||
// console.log("logined:", chain.chainManager.isLogined);
|
||||
chain.logined = chain.chainManager.isLogined;
|
||||
window.location.reload();
|
||||
};
|
||||
const handTaskHome = () => {
|
||||
//router.push("/quest");
|
||||
const code = route.query.code;
|
||||
if (code) {
|
||||
router.push({ path: "/quest", query: { code: code } });
|
||||
} else {
|
||||
router.push("/quest");
|
||||
}
|
||||
};
|
||||
const handleCopy = () => {
|
||||
const accountId = AppModule.accountId;
|
||||
reset();
|
||||
copyToClipboard(accountId).then(() => {
|
||||
// if (copied.value) {
|
||||
// message.success("Copy successful!");
|
||||
// }
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.naber {
|
||||
// position: fixed;
|
||||
// z-index: 20;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// background-color: rgb(15, 15, 15);
|
||||
width: 100%;
|
||||
height: 75px;
|
||||
padding-top: 10px;
|
||||
display: flex;
|
||||
//padding-right: 360px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.content {
|
||||
width: 1200px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.login-btn {
|
||||
width: 180px;
|
||||
height: 50px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
//border: 1px solid #ffffff;
|
||||
background: url("@/assets/img/task/login-btn.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.login-btn:hover {
|
||||
background: url("@/assets/img/task/login-btn-active.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #000000;
|
||||
}
|
||||
.login-btn-active {
|
||||
width: 180px;
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
// border: 1px solid #ffffff;
|
||||
background: url("@/assets/img/task/login-btn.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: relative;
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0; //update this line to right: 0;
|
||||
width: 180px;
|
||||
z-index: 1;
|
||||
// padding: 10px 0;
|
||||
// background-color: #bdb8b8;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
list-style: none;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
li {
|
||||
margin: 5px 0;
|
||||
}
|
||||
.menu-item-top {
|
||||
padding: 10px 15px;
|
||||
color: #f5f5f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding-bottom: 15px;
|
||||
.title {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
.menu-item-top:before {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 15px;
|
||||
content: "";
|
||||
width: 140px;
|
||||
height: 1px;
|
||||
background: #676767;
|
||||
}
|
||||
.menu-item {
|
||||
// padding: 5px 15px;
|
||||
color: #f5f5f5;
|
||||
display: flex;
|
||||
//border: 1px solid #ccc;
|
||||
background-color: #161515;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
// padding-top: 10px;
|
||||
align-items: center;
|
||||
.title {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-btn-active:hover {
|
||||
background: url("@/assets/img/task/login-btn-active.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #000000;
|
||||
}
|
||||
.header-right {
|
||||
// width: 228px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.discode {
|
||||
padding-left: 28px;
|
||||
padding-right: 39px;
|
||||
}
|
||||
.twitter {
|
||||
// padding-left: 28px;
|
||||
//padding-right: 39px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
189
src/components/map/CounterFire.vue
Normal file
@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div class="counterfire-container">
|
||||
<div class="header"></div>
|
||||
<div class="container-conter">
|
||||
<div class="content">
|
||||
<div>
|
||||
<div class="counterfire-img"><img src="../../assets/img/planet/logo.png" alt="" /></div>
|
||||
<div class="humanity-text">
|
||||
<div>
|
||||
As humanity delves into the mysteries of the cosmos, it marks a
|
||||
new era where Pluto serves as a vital jumpgate. This colossal leap
|
||||
allows humanity to venture into uncharted star systems, opening
|
||||
doors to unexplored realms of discovery and daring.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
In the expanse of the universe, humanity encounters novel races
|
||||
and untapped energy sources. Amid the quest for the precious
|
||||
universal resource known as Crystals, brace yourself to etch your
|
||||
legend across this cosmos teeming with adventure and challenge.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="download-btn">
|
||||
<a href="https://apps.apple.com/app/counter%20fire/id6444462915" target="_blank" class="download-item">
|
||||
<img src="../../assets/img/planet/AppStore_icon.png" alt=""
|
||||
/></a>
|
||||
<a class="https://play.google.com/store/apps/details?id=com.cege.games.release" target="_blank" href="http://"
|
||||
><img src="../../assets/img/planet/GooglePlay_icon.png" alt=""
|
||||
/></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg">
|
||||
<img src="../../assets/img/planet/CFunivers_bg.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="footer-content">
|
||||
<div class="footer-left">
|
||||
<div class="footer-logo">
|
||||
<a href="/"
|
||||
><img src="../../assets/img/planet/footer-logo.png" alt=""
|
||||
/></a>
|
||||
</div>
|
||||
<div class="copyright">Copyright © 2023</div>
|
||||
</div>
|
||||
<div class="footer-right">
|
||||
<a href="https://discord.com/invite/fNSn2NHUvf" class="discord-icon"
|
||||
><img src="../../assets/img/planet/com_Discord_icon.png" alt=""
|
||||
/></a>
|
||||
<a class="twitter-icon" href="https://twitter.com/_CounterFire"
|
||||
><img src="../../assets/img/planet/com_Twitter_icon.png" alt=""
|
||||
/></a>
|
||||
<a class="youtube-icon" href="https://www.youtube.com/c/CryptoElitesBattlegrounds"
|
||||
><img src="../../assets/img/planet/com_Youtube_icon.png" alt=""
|
||||
/></a>
|
||||
</div>
|
||||
<!-- <div class="logo"></div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.counterfire-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.header {
|
||||
height: 84px;
|
||||
}
|
||||
.container-conter {
|
||||
position: relative;
|
||||
height: calc(100% - 168px);
|
||||
width: 100%;
|
||||
.content {
|
||||
width: 1764px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
padding-top: 58px;
|
||||
justify-content: flex-end;
|
||||
.counterfire-img{
|
||||
// width: 992px;
|
||||
// height: 152px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.humanity-text {
|
||||
text-align: left;
|
||||
width: 992px;
|
||||
font-size: 24px;
|
||||
font-family: "Poppins";
|
||||
font-weight: 400;
|
||||
color: #110d1c;
|
||||
}
|
||||
.bg {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0px;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
bottom: 0;
|
||||
color: transparent;
|
||||
img {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0px;
|
||||
right: 0;
|
||||
// object-fit: cover;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
height: 84px;
|
||||
background-color: #0e0f22;
|
||||
|
||||
.footer-content {
|
||||
width: 1764px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.copyright {
|
||||
font-size: 20px;
|
||||
font-family: "Poppins";
|
||||
font-weight: 400;
|
||||
color: #686a8f;
|
||||
}
|
||||
.footer-logo {
|
||||
width: 194px;
|
||||
height: 62px;
|
||||
img {
|
||||
width: 194px;
|
||||
height: 62px;
|
||||
}
|
||||
}
|
||||
.footer-right {
|
||||
display: flex;
|
||||
.discord-icon {
|
||||
width: 64px;
|
||||
height: 48px;
|
||||
img {
|
||||
width: 64px;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
.twitter-icon {
|
||||
width: 60px;
|
||||
height: 48px;
|
||||
margin-right: 34px;
|
||||
margin-left: 42px;
|
||||
img {
|
||||
width: 60px;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
.youtube-icon {
|
||||
width: 60px;
|
||||
height: 42px;
|
||||
img {
|
||||
width: 60px;
|
||||
height: 42px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.download-btn {
|
||||
display: flex;
|
||||
margin-top: 38px;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
.download-item{
|
||||
width: 413px;
|
||||
height: 112px;
|
||||
}
|
||||
}
|
||||
</style>
|
139
src/components/map/PlanetBanner.vue
Normal file
@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<div class="planet-container">
|
||||
<div class="herder"></div>
|
||||
<div class="banner">
|
||||
<div class="banner-content">
|
||||
<div class="banner-left">
|
||||
<div class="banner-left-top">
|
||||
<div class="title">
|
||||
<img src="../../assets/img/planet/planet_title.png" alt="" />
|
||||
</div>
|
||||
<div class="banner-slogan">
|
||||
Secure Your Stellar Investment with Exclusive Planets! Embark on
|
||||
an interstellar journey and claim planets that are truly
|
||||
exceptional. Stake for success and unlock rewards that are out of
|
||||
this world.
|
||||
</div>
|
||||
<div class="each">Each one is a unique masterpiece.</div>
|
||||
<div class="buy-btn">Buy our token</div>
|
||||
</div>
|
||||
|
||||
<div class="investors">
|
||||
<img src="../../assets/img/planet/investors.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="banner-right">
|
||||
<div class="planet_card">
|
||||
<div class="planet_card01">
|
||||
<img src="../../assets/img/planet/planet_card01.png" alt="" />
|
||||
</div>
|
||||
<div class="planet_card02">
|
||||
<img src="../../assets/img/planet/planet_card02.png" alt="" />
|
||||
</div>
|
||||
<div class="planet_card03">
|
||||
<img src="../../assets/img/planet/planet_card03.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg">
|
||||
<img src="../../assets/img/planet/planet_banner.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.planet-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.header {
|
||||
height: 84px;
|
||||
}
|
||||
// padding-bottom: 232px;
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
top: 84px;
|
||||
height: 100%;
|
||||
.banner-content {
|
||||
width: 1764px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
padding-top: 83px;
|
||||
.banner-left {
|
||||
width: 776px;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.banner-slogan {
|
||||
font-size: 24px;
|
||||
font-family: "Poppins";
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
margin-top: 24px;
|
||||
color: #f3f0ff;
|
||||
}
|
||||
.each {
|
||||
font-size: 28px;
|
||||
font-family: "Poppins";
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
margin-top: 24px;
|
||||
color: #f3f0ff;
|
||||
}
|
||||
.buy-btn {
|
||||
width: 369px;
|
||||
height: 87px;
|
||||
font-size: 36px;
|
||||
font-family: "Poppins";
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
margin-top: 45px;
|
||||
line-height: 87px;
|
||||
color: #ffffff;
|
||||
background: url("../../assets/img/planet/planet_btnBg.png");
|
||||
}
|
||||
.investors {
|
||||
margin-top: 103px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bg {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
bottom: 0;
|
||||
color: transparent;
|
||||
img {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
object-fit: cover;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
.banner-right{
|
||||
.planet_card{
|
||||
display: flex;
|
||||
margin-top: 190px;
|
||||
}
|
||||
}
|
||||
</style>
|
1562
src/components/task/TaskOne.vue
Normal file
889
src/components/task/TaskTwo.vue
Normal file
@ -0,0 +1,889 @@
|
||||
<template>
|
||||
<div class="task-two">
|
||||
<div class="task-two-header">
|
||||
<NavBar></NavBar>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="center">
|
||||
<div class="header">
|
||||
<div class="return">
|
||||
<div class="return-icon" @click="handTaskHome">
|
||||
<img src="@/assets/img/task/return.png" alt="" />
|
||||
</div>
|
||||
<div class="invite-quest">
|
||||
<a
|
||||
href="https://medium.com/@CounterFire/rise-of-gacha-4d5fac449d95"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
VIEW YOUR QUEST</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="complete">
|
||||
<!-- Complete the Sailor’s Quest to unlock the invite quest -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-conter">
|
||||
<div class="content-left">
|
||||
<div class="leaderboard">Leaderboard</div>
|
||||
<div class="address-header">
|
||||
<div class="address-header-item">#</div>
|
||||
<div class="address-header-item-address">Address</div>
|
||||
<div class="address-header-item-points">Points</div>
|
||||
<!-- <div>Points</div> -->
|
||||
</div>
|
||||
<div class="scroll-content">
|
||||
<a-list
|
||||
item-layout="vertical"
|
||||
class="value-list"
|
||||
:data-source="formattedData"
|
||||
:bordered="false"
|
||||
:split="false"
|
||||
>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
<div class="assress-item">
|
||||
<div class="assress-item-id">{{ item.id }}</div>
|
||||
<div>{{ item.account }}</div>
|
||||
<div class="code">
|
||||
<!-- <NumberCounter :duration="10000" :targetNumber="item.code"></NumberCounter> -->
|
||||
{{ item.point }}
|
||||
|
||||
<!-- <Vue3autocounter
|
||||
ref="counter"
|
||||
:startAmount="0"
|
||||
:endAmount="Number(item.point)"
|
||||
:duration="0.4"
|
||||
prefix=""
|
||||
suffix=""
|
||||
separator=","
|
||||
decimalSeparator="."
|
||||
:decimals="0"
|
||||
:autoinit="true"
|
||||
>
|
||||
</Vue3autocounter> -->
|
||||
</div>
|
||||
<!-- <div>{{ item.targetCode }}</div> -->
|
||||
</div>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-right" v-if="isStatus">
|
||||
<!-- <div class="link-title">Invite Link</div> -->
|
||||
<div class="boder-left"></div>
|
||||
<div class="link-btn">
|
||||
<div>
|
||||
<div>Invite Link</div>
|
||||
<div>{{ inviteLink }}</div>
|
||||
</div>
|
||||
<div class="copy" @click="handleCopy">
|
||||
<img src="@/assets/img/task/copy-icon.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="you">
|
||||
<div class="you-title">
|
||||
You Invited
|
||||
<span class="you-title-number">{{
|
||||
userInfo.direct_clan ? userInfo.direct_clan : "0"
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="you-input">
|
||||
<div v-if="userInfo.regular && userInfo.regular.length > 0">
|
||||
<div class="you-input-item">
|
||||
Points
|
||||
<span class="item-number">
|
||||
{{ userInfo.point - totalRegularPoints }}
|
||||
</span>
|
||||
<a-tooltip placement="bottom" overlayClassName="my-tooltip">
|
||||
<template #title>
|
||||
<div class="tooltip-text">
|
||||
<span v-html="typesInRegular"></span><br />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<span class="item-number-right">
|
||||
+ {{ totalRegularPoints }}</span
|
||||
>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="you-input-item" v-else>
|
||||
Points
|
||||
<span class="item-number">{{
|
||||
userInfo.point ? userInfo.point : "0"
|
||||
}}</span>
|
||||
</div>
|
||||
<!-- <a-tooltip placement="bottomLeft">
|
||||
<template #title>
|
||||
<span>10 points for each successful invite.</span>
|
||||
</template> -->
|
||||
<div class="you-input-item">
|
||||
Rank
|
||||
<span class="item-number">{{
|
||||
userInfo.rank ? userInfo.rank : "0"
|
||||
}}</span>
|
||||
</div>
|
||||
<!-- <div class="you-input-item">
|
||||
Top
|
||||
<span class="item-number"
|
||||
>{{ userInfo.top > 30 ? "+30" : userInfo.top }}%</span
|
||||
>
|
||||
</div> -->
|
||||
<!-- </a-tooltip> -->
|
||||
<a-tooltip placement="bottom" overlayClassName="my-tooltip">
|
||||
<template #title>
|
||||
<div class="tooltip-text">
|
||||
<div>
|
||||
Top 10% points holder share 40% of the prize pool
|
||||
</div>
|
||||
<div>
|
||||
Top 10%-30% points holder share 40% of the prize pool
|
||||
</div>
|
||||
<div>
|
||||
Top 30%-50% points holder share 20% of the prize pool
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="you-input-item">
|
||||
Top
|
||||
<span class="item-number">
|
||||
{{ userInfo.top != null ? userInfo.top : "0" }}%
|
||||
</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div class="invitation">
|
||||
<div class="invitation-img">
|
||||
<img src="@/assets/img/task/currency.png" alt="" />
|
||||
</div>
|
||||
<div class="invitation-title">
|
||||
10 points for each successful invite,<br />
|
||||
Points will be used to get Token rewards and other.
|
||||
</div>
|
||||
</div>
|
||||
<div class="points-ticket">
|
||||
<div class="points-item">
|
||||
<a-tooltip
|
||||
placement="bottomLeft"
|
||||
overlayClassName="my-tooltip"
|
||||
>
|
||||
<template #title>
|
||||
<span class="tooltip-text"
|
||||
>Every 20 points will earn you 1 Yoyo.</span
|
||||
>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
Your Yoyo
|
||||
<span class="points-item-number">{{
|
||||
userInfo.tickets ? userInfo.tickets : "0"
|
||||
}}</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="candy-dispenser">
|
||||
<div class="candy-img-content">
|
||||
<img src="@/assets/img/task/candy-dispenser.png" alt="" />
|
||||
<a-tooltip placement="bottom" overlayClassName="my-tooltip">
|
||||
<template #title>
|
||||
<div>
|
||||
<div class="tooltip-text">
|
||||
The Yoyo Machine event will be introduced after this
|
||||
event ends.
|
||||
</div>
|
||||
<div class="tooltip-text">
|
||||
You can then collect your Yoyo and participate in a
|
||||
4-week-long lottery. Rewards may include
|
||||
ARB\ETH\CEC\NFTs
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="img-tips"></div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<!-- <div>
|
||||
<img src="@/assets/img/task/candy-dispenser.png" alt="" />
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- <div class="tip">
|
||||
<div class="tip-item">10 points for each successful invite</div>
|
||||
<div class="tip-item">1 ticket for every 20 points</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-right-not-login" v-else>
|
||||
<!-- <div class="complete">
|
||||
Complete the Gacha Quest to unlock the invite quest
|
||||
</div> -->
|
||||
<div v-if="!isStatus && chain.logined" class="the-event" >The event has ended</div>
|
||||
<div v-else>
|
||||
<div class="quest-content">
|
||||
<div class="quest-left">
|
||||
<div class="currency-img">
|
||||
<img src="@/assets/img/task/currency.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="quest-right">
|
||||
<div class="candy-dispenser-img">
|
||||
<img src="@/assets/img/task/candy-dispenser.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="token-btns">
|
||||
<div class="token-btn">Token Rewards</div>
|
||||
<div class="token-btn">Yoyo Event</div>
|
||||
</div>
|
||||
<div class="gacha-quest" @click="login">Connect and check</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg">
|
||||
<img src="@/assets/img/task/one-bg.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import Vue3autocounter from "vue3-autocounter";
|
||||
import NavBar from "../layout/navber.vue";
|
||||
import { useCopyToClipboard } from "../../hooks/useCopyToClipboard";
|
||||
import { getLeaderboard, UserInfo, UserStatus, getJoin } from "@/api/User";
|
||||
import { useChainStore } from "@/store/chain";
|
||||
import { useAppStore } from "@/store/app";
|
||||
import { hasMetamask } from "@/utils/chain.util";
|
||||
import { ref, reactive, watchEffect, onMounted, watch, computed } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
const chain = useChainStore();
|
||||
const AppModule = useAppStore();
|
||||
const loginLoading = ref(false);
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const invited = ref(0);
|
||||
const rank = ref(0);
|
||||
const top = ref(0);
|
||||
const points = ref(0);
|
||||
const ticket = ref(0);
|
||||
const counter = ref(null);
|
||||
const isStatus = ref(false);
|
||||
const data = reactive([]);
|
||||
const userInfo = reactive({});
|
||||
const formattedData = computed(() => {
|
||||
return data
|
||||
.map((item) => ({
|
||||
...item,
|
||||
account: item.account.slice(0, 6) + "..." + item.account.slice(-6),
|
||||
}))
|
||||
.reduce((acc, current) => {
|
||||
const x = acc.find((item) => item.account === current.account);
|
||||
if (!x) {
|
||||
return acc.concat([current]);
|
||||
} else {
|
||||
return acc;
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
const typesInRegular = computed(() =>
|
||||
userInfo.regular.map((item) => item.type).join("<br/>")
|
||||
);
|
||||
async function login(event) {
|
||||
var next = window.location.href;
|
||||
if (!hasMetamask()) {
|
||||
var url = `https://metamask.app.link/dapp/${next}`;
|
||||
location.href = url;
|
||||
} else {
|
||||
if (!chain.logined) {
|
||||
// 没有登录情况下执行登录
|
||||
loginLoading.value = true;
|
||||
try {
|
||||
await chain.chainManager.login();
|
||||
chain.logined = chain.chainManager.isLogined;
|
||||
currentTask.value = 2;
|
||||
loginLoading.value = false;
|
||||
} catch (err) {
|
||||
loginLoading.value = false;
|
||||
}
|
||||
// console.log("logined:", chain.chainManager.isLogined);
|
||||
}
|
||||
}
|
||||
}
|
||||
const assign = (source, target) => {
|
||||
if (target === undefined || target === null) {
|
||||
throw new TypeError("Cannot convert undefined or null to object");
|
||||
}
|
||||
|
||||
for (let key in target) {
|
||||
source[key] = target[key];
|
||||
}
|
||||
};
|
||||
const totalRegularPoints = computed(() =>
|
||||
userInfo.regular.reduce((total, item) => total + item.point, 0)
|
||||
);
|
||||
const handTaskHome = () => {
|
||||
const code = route.query.code;
|
||||
if (code) {
|
||||
router.push({ path: "/quest", query: { code: code } });
|
||||
} else {
|
||||
router.push("/quest");
|
||||
}
|
||||
};
|
||||
const handTaskOne = () => {
|
||||
const code = route.query.code;
|
||||
if (code) {
|
||||
router.push({ path: "/taskTwo", query: { code: code } });
|
||||
} else {
|
||||
router.push("/taskTwo");
|
||||
}
|
||||
console.log(router, "-=-=-");
|
||||
};
|
||||
watchEffect(() => {
|
||||
console.log(data); // 当数据改变时,这会被调用
|
||||
});
|
||||
|
||||
const inviteLink = ref(
|
||||
`${import.meta.env.VUE_APP_GPAL_API}/?code=${userInfo.invite_code}`
|
||||
);
|
||||
const { copied, error, reset, copyToClipboard } = useCopyToClipboard();
|
||||
|
||||
const handleCopy = () => {
|
||||
reset();
|
||||
copyToClipboard(inviteLink.value).then(() => {
|
||||
if (copied.value) {
|
||||
message.success("Copy successful!");
|
||||
}
|
||||
});
|
||||
};
|
||||
watch(
|
||||
() => chain.logined,
|
||||
async (newValue, oldValue) => {
|
||||
// console.log("logined changed from", oldValue, "to", newValue);
|
||||
const res = await getLeaderboard({ offset: 0, limit: 100 });
|
||||
console.log(res);
|
||||
if (res) {
|
||||
data.value = res.data;
|
||||
|
||||
res.data.forEach((e) => {
|
||||
data.push(e);
|
||||
});
|
||||
|
||||
console.log(res.data, "res.data.data");
|
||||
console.log(data.value, "ff");
|
||||
}
|
||||
const userStatus = await UserStatus({ account: AppModule.accountId });
|
||||
|
||||
if (
|
||||
userStatus &&
|
||||
userStatus.claim &&
|
||||
Number(userStatus.claim) !== 0 &&
|
||||
userStatus.status.every((status) => status == 1)
|
||||
) {
|
||||
isStatus.value = true;
|
||||
const resjoin = await getJoin({
|
||||
account: AppModule.accountId,
|
||||
invite_code: route.query.code,
|
||||
});
|
||||
}
|
||||
const resq = await UserInfo({ account: AppModule.accountId });
|
||||
|
||||
if (resq) {
|
||||
// userInfo.value = resq
|
||||
assign(userInfo, resq);
|
||||
inviteLink.value = `${import.meta.env.VUE_APP_GPAL_API}/?code=${
|
||||
userInfo.invite_code
|
||||
}`;
|
||||
}
|
||||
console.log(resq, "dsdsdsdsd");
|
||||
console.log(userInfo.value);
|
||||
}
|
||||
);
|
||||
onMounted(async () => {
|
||||
const res = await getLeaderboard({ offset: 0, limit: 100 });
|
||||
console.log(res);
|
||||
if (res) {
|
||||
data.value = res.data;
|
||||
|
||||
res.data.forEach((e) => {
|
||||
data.push(e);
|
||||
});
|
||||
|
||||
console.log(res.data, "res.data.data");
|
||||
console.log(data.value, "ff");
|
||||
}
|
||||
const resStatus = await UserStatus({ account: AppModule.accountId });
|
||||
if (
|
||||
resStatus &&
|
||||
resStatus.claim &&
|
||||
Number(resStatus.claim) !== 0 &&
|
||||
resStatus.status.every((status) => status == 1)
|
||||
) {
|
||||
isStatus.value = true;
|
||||
}
|
||||
const resq = await UserInfo({ account: AppModule.accountId });
|
||||
|
||||
if (resq) {
|
||||
// userInfo.value = resq
|
||||
assign(userInfo, resq);
|
||||
inviteLink.value = `${import.meta.env.VUE_APP_GPAL_API}/?code=${
|
||||
userInfo.invite_code
|
||||
}`;
|
||||
}
|
||||
console.log(res);
|
||||
//console.log(formattedData);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.task-two-header {
|
||||
// height: 65px;
|
||||
}
|
||||
.the-event{
|
||||
padding-left: 100px;
|
||||
padding-right: 100px;
|
||||
color: #fff;
|
||||
font-size: 28px;
|
||||
}
|
||||
.task-two {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// height: calc(100vh - 65px);
|
||||
// padding-bottom: 100px;
|
||||
.bg {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
bottom: 0;
|
||||
color: transparent;
|
||||
img {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
object-fit: cover;
|
||||
z-index: 0;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
height: calc(100% - 85px);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.header {
|
||||
// padding-top: 47px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.complete {
|
||||
// width: 48%;
|
||||
|
||||
font-size: 18px;
|
||||
font-family: "MEurostile";
|
||||
font-weight: 400;
|
||||
color: #959595;
|
||||
}
|
||||
.return {
|
||||
font-size: 50px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
display: flex;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
.return-icon {
|
||||
margin-right: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-conter {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
//justify-content: space-between;
|
||||
}
|
||||
.content-left {
|
||||
// padding-top: 190px;
|
||||
// margin-top: 58px;
|
||||
width: 540px;
|
||||
padding-right: 33px;
|
||||
height: 600px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
//border-right: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.content-right {
|
||||
// padding-top: 51px;
|
||||
border-left: 1px solid #5d5548;
|
||||
padding-left: 66px;
|
||||
// width: 100%;
|
||||
position: relative;
|
||||
.boder-left {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
// height: 550px;
|
||||
width: 1px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.link-title {
|
||||
font-size: 32px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
// margin-left: 180px;
|
||||
// margin-top: 19px;
|
||||
// margin-right: 28px;
|
||||
}
|
||||
.link-btn {
|
||||
width: 581px;
|
||||
height: 61px;
|
||||
border: 1px solid #8f7440;
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
line-height: 20px;
|
||||
font-family: "MEurostile";
|
||||
font-weight: 400;
|
||||
color: #96763a;
|
||||
display: flex;
|
||||
background: rgba(40, 33, 20, 0.6);
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-left: 31px;
|
||||
padding-right: 31px;
|
||||
margin-bottom: 24px;
|
||||
// padding-top: 5px;
|
||||
}
|
||||
.you-input {
|
||||
width: 100%;
|
||||
// height: 51px;
|
||||
// padding-left: 31px;
|
||||
// padding-right: 31px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
margin-bottom: 26px;
|
||||
// background: rgba(40, 33, 20, 0.6);
|
||||
// border: 1px solid #ffffff;
|
||||
justify-content: space-between;
|
||||
border-radius: 12px;
|
||||
.you-input-item {
|
||||
font-size: 32px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.item-number {
|
||||
font-size: 32px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
color: #5ce501;
|
||||
}
|
||||
.item-number-right {
|
||||
font-size: 22px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
color: #5ce501;
|
||||
}
|
||||
.item-number-right::after {
|
||||
content: ""; /* 伪元素需要内容才能显示,这里我们不需要实际的内容,所以设置为空 */
|
||||
position: absolute; /* 使用绝对定位来放置红点 */
|
||||
top: 0px; /* 红点在右上角,所以 top 和 right 都设置为 0 */
|
||||
right: -6px;
|
||||
width: 6px; /* 可以根据需要调整红点的大小 */
|
||||
height: 6px;
|
||||
background-color: #f50123; /* 红点的颜色 */
|
||||
border-radius: 50%; /* 使红点成为一个圆形 */
|
||||
}
|
||||
.points-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
// height: 51px;
|
||||
// text-align: center;
|
||||
line-height: 21px;
|
||||
// background: rgba(40, 33, 20, 0.6);
|
||||
// border: 1px solid #ffffff;
|
||||
// opacity: 0.6;
|
||||
font-size: 22px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
// padding-left: 31px;
|
||||
border-radius: 12px;
|
||||
.points-item-number {
|
||||
color: #5ce501;
|
||||
}
|
||||
}
|
||||
|
||||
.points-ticket {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 49px;
|
||||
}
|
||||
.tip {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-family: "MEurostile";
|
||||
font-weight: 400;
|
||||
color: #afa07d;
|
||||
.tip-item {
|
||||
width: 281px;
|
||||
// height: 51px;
|
||||
}
|
||||
}
|
||||
.candy-dispenser {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.candy-img-content {
|
||||
position: relative;
|
||||
.img-tips {
|
||||
width: 166px;
|
||||
height: 100px;
|
||||
// background-color: #5ce501;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
// .points-title {
|
||||
// max-width: 250px; /* 设置最大宽度 */
|
||||
// word-wrap: break-word; /* 自动换行 */
|
||||
// }
|
||||
.tooltip-text {
|
||||
font-size: 16px;
|
||||
font-family: "Arial";
|
||||
font-weight: 400;
|
||||
color: #96763a;
|
||||
}
|
||||
.copy {
|
||||
cursor: pointer;
|
||||
}
|
||||
.scroll-content {
|
||||
height: 540px;
|
||||
overflow: auto;
|
||||
scrollbar-width: thin; /* Firefox */
|
||||
scrollbar-color: transparent transparent; /* Firefox */
|
||||
}
|
||||
|
||||
.scroll-content::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
.assress-item {
|
||||
display: flex;
|
||||
font-size: 18px;
|
||||
font-family: "MEurostile";
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
justify-content: space-between;
|
||||
.assress-item-id {
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
.address-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 18px;
|
||||
font-family: "MEurostile";
|
||||
font-weight: 400;
|
||||
color: #898989;
|
||||
.address-header-item {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.address-header-item-address {
|
||||
width: 124px;
|
||||
}
|
||||
.address-header-item-points {
|
||||
width: 89px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.code {
|
||||
width: 89px;
|
||||
text-align: center;
|
||||
color: #5ce501;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
.leaderboard {
|
||||
color: #ffffff;
|
||||
font-size: 32px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
.you-title {
|
||||
font-size: 22px;
|
||||
font-family: "GemunuExtraBold";
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
// text-align: center;
|
||||
margin-bottom: 20px;
|
||||
.you-title-number {
|
||||
color: #5ce501;
|
||||
}
|
||||
}
|
||||
|
||||
.invite-quest {
|
||||
position: relative;
|
||||
line-height: 43px;
|
||||
a {
|
||||
color: #fff;
|
||||
}
|
||||
border-bottom: 2px solid transparent;
|
||||
&:hover {
|
||||
border-bottom: 2px solid #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.invite-quest::after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
width: 25px; /* Adjust according to your needs */
|
||||
height: 24px; /* Adjust according to your needs */
|
||||
background-image: url("@/assets/img/task/arrow.png");
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0;
|
||||
right: -30px; /* Or adjust as per your needs */
|
||||
top: 20%; /* Or adjust as per your needs */
|
||||
//transform: translateY(-50%); /* To vertically center the image */
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.invite-quest:hover::after {
|
||||
// right: -34px;
|
||||
// top: 48%; // 根据需要调整
|
||||
opacity: 1;
|
||||
transform: translate(3px, -3px);
|
||||
}
|
||||
.invitation {
|
||||
display: flex;
|
||||
padding-bottom: 10px;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #5d5548;
|
||||
.invitation-title {
|
||||
margin-left: 24px;
|
||||
font-size: 16px;
|
||||
font-family: "Arial";
|
||||
font-weight: 400;
|
||||
color: #d3d3d3;
|
||||
}
|
||||
}
|
||||
.content-right-not-login {
|
||||
padding-left: 135px;
|
||||
.quest-content {
|
||||
display: flex;
|
||||
width: 85%;
|
||||
margin: 0 auto;
|
||||
margin-top: 42px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
.token-btns {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.gacha-quest {
|
||||
width: 409px;
|
||||
height: 58px;
|
||||
margin: 0 auto;
|
||||
cursor: pointer;
|
||||
margin-top: 47px;
|
||||
margin-bottom: 71px;
|
||||
text-align: center;
|
||||
line-height: 58px;
|
||||
background: url("@/assets/img/task/gacha-quest-bg.png") no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.token-btn {
|
||||
width: 215px;
|
||||
height: 53px;
|
||||
text-align: center;
|
||||
line-height: 53px;
|
||||
background: url("@/assets/img/task/token-btn-bg.png") no-repeat;
|
||||
background-size: contain;
|
||||
font-size: 18px;
|
||||
font-family: Arial;
|
||||
font-weight: 400;
|
||||
color: #96763a;
|
||||
}
|
||||
.currency-img {
|
||||
width: 117px;
|
||||
height: 95px;
|
||||
}
|
||||
.candy-dispenser-img {
|
||||
width: 124px;
|
||||
height: 124px;
|
||||
}
|
||||
.complete {
|
||||
// width: 90%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 17px;
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
margin-top: 60px;
|
||||
font-family: "MEurostile";
|
||||
font-weight: 400;
|
||||
color: #c2c2c2;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1441px) {
|
||||
/* 在此处插入你希望在屏幕宽度大于1440px时应用的样式 */
|
||||
.header {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
/* 更多的样式代码 */
|
||||
}
|
||||
@media (min-width: 1200px) and (max-width: 1439px) {
|
||||
/* 在这里写你的样式规则 */
|
||||
.center {
|
||||
height: 85%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.my-tooltip {
|
||||
&.ant-tooltip {
|
||||
//sass写法
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
</style>
|
286
src/configs/allchain.ts
Normal file
@ -0,0 +1,286 @@
|
||||
export const AllChains = [
|
||||
{
|
||||
name: 'Ethereum Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.ankr.com/eth',
|
||||
id: 1,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://etherscan.io'
|
||||
},
|
||||
{
|
||||
name: 'Ethereum Ropsten Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161',
|
||||
id: 3,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://ropsten.etherscan.io'
|
||||
},
|
||||
{
|
||||
name: 'Ethereum Rinkeby Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://rinkey.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161',
|
||||
id: 4,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://rinkey.etherscan.io'
|
||||
},
|
||||
{
|
||||
name: 'Ethereum Goerli Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161',
|
||||
id: 5,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://goerli.etherscan.io'
|
||||
},
|
||||
{
|
||||
name: 'Ethereum Kovan Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://kovan.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161',
|
||||
id: 6,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://kovan.etherscan.io'
|
||||
},
|
||||
{
|
||||
name: 'Ubiq Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.octano.dev/',
|
||||
id: 8,
|
||||
symbol: 'UBQ',
|
||||
explorerurl: 'https://ubiqscan.io/'
|
||||
},
|
||||
{
|
||||
name: 'Elastos ETH Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://api.elastos.io/eth',
|
||||
id: 20,
|
||||
symbol: 'ELA',
|
||||
explorerurl: 'https://explorer.elaeth.io/'
|
||||
},
|
||||
{
|
||||
name: 'Cronos Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://evm-cronos.crypto.org',
|
||||
id: 25,
|
||||
symbol: 'CRO',
|
||||
explorerurl: 'https://cronos.crypto.org/explorer/'
|
||||
},
|
||||
{
|
||||
name: 'Telos EVM Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://mainnet.telos.net/evm',
|
||||
id: 40,
|
||||
symbol: 'TLOS',
|
||||
explorerurl: 'https://telos.net/'
|
||||
},
|
||||
{
|
||||
name: 'Binance Smart Chain',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.ankr.com/bsc',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTAwIiBoZWlnaHQ9IjI1MDAiIHZpZXdCb3g9IjAgMCAyMDAwIDIwMDAiPjxnIGZpbGw9IiNmM2JhMmYiPjxwYXRoIGQ9Ik02MTEuNTkgODQwLjQybDM4OC40LTM4OC4zOSAzODguNiAzODguNTkgMjI2LTIyNkw5OTkuOTkgMCAzODUuNiA2MTQuNDJsMjI1Ljk5IDIyNk0uMDA2IDk5OS45NjlsMjI2LjAwNy0yMjYuMDA3IDIyNS45OTIgMjI1Ljk5M0wyMjYgMTIyNS45NnpNNjExLjU5IDExNTkuNThsMzg4LjQgMzg4LjM5IDM4OC41OS0zODguNTggMjI2LjEyIDIyNS44OC0uMTEuMTJMOTk5Ljk5IDIwMDBsLTYxNC40MS02MTQuNC0uMzItLjMyIDIyNi4zMy0yMjUuN00xNTQ4LjAxMyAxMDAwLjA5M2wyMjYuMDA3LTIyNi4wMDYgMjI1Ljk5MiAyMjUuOTkyLTIyNi4wMDYgMjI2LjAwN3oiLz48cGF0aCBkPSJNMTIyOS4yMiA5OTkuODhoLjFMOTk5Ljk5IDc3MC41NSA4MzAuNTEgOTQwLjAzaC0uMDFsLTE5LjQ3IDE5LjQ4LTQwLjE2IDQwLjE3LS4zMi4zMS4zMi4zMyAyMjkuMTIgMjI5LjEzIDIyOS4zMy0yMjkuMzMuMTEtLjEzLS4yMS0uMTEiLz48L2c+PC9zdmc+',
|
||||
id: 56,
|
||||
symbol: 'BNB',
|
||||
explorerurl: 'https://bscscan.com'
|
||||
},
|
||||
{
|
||||
name: 'OKExChain Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://exchainrpc.okex.org',
|
||||
id: 66,
|
||||
symbol: 'OKT',
|
||||
explorerurl: 'https://www.oklink.com/okexchain'
|
||||
},
|
||||
{
|
||||
name: 'Hoo Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://http-mainnet.hoosmartchain.com',
|
||||
id: 70,
|
||||
symbol: 'HOO',
|
||||
explorerurl: 'https://hooscan.com'
|
||||
},
|
||||
{
|
||||
name: 'Binance Smart Chain Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545/',
|
||||
id: 97,
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTAwIiBoZWlnaHQ9IjI1MDAiIHZpZXdCb3g9IjAgMCAyMDAwIDIwMDAiPjxnIGZpbGw9IiNmM2JhMmYiPjxwYXRoIGQ9Ik02MTEuNTkgODQwLjQybDM4OC40LTM4OC4zOSAzODguNiAzODguNTkgMjI2LTIyNkw5OTkuOTkgMCAzODUuNiA2MTQuNDJsMjI1Ljk5IDIyNk0uMDA2IDk5OS45NjlsMjI2LjAwNy0yMjYuMDA3IDIyNS45OTIgMjI1Ljk5M0wyMjYgMTIyNS45NnpNNjExLjU5IDExNTkuNThsMzg4LjQgMzg4LjM5IDM4OC41OS0zODguNTggMjI2LjEyIDIyNS44OC0uMTEuMTJMOTk5Ljk5IDIwMDBsLTYxNC40MS02MTQuNC0uMzItLjMyIDIyNi4zMy0yMjUuN00xNTQ4LjAxMyAxMDAwLjA5M2wyMjYuMDA3LTIyNi4wMDYgMjI1Ljk5MiAyMjUuOTkyLTIyNi4wMDYgMjI2LjAwN3oiLz48cGF0aCBkPSJNMTIyOS4yMiA5OTkuODhoLjFMOTk5Ljk5IDc3MC41NSA4MzAuNTEgOTQwLjAzaC0uMDFsLTE5LjQ3IDE5LjQ4LTQwLjE2IDQwLjE3LS4zMi4zMS4zMi4zMyAyMjkuMTIgMjI5LjEzIDIyOS4zMy0yMjkuMzMuMTEtLjEzLS4yMS0uMTEiLz48L2c+PC9zdmc+',
|
||||
symbol: 'BNB',
|
||||
explorerurl: 'https://testnet.bscscan.com'
|
||||
},
|
||||
{
|
||||
name: 'xDai Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.xdaichain.com/',
|
||||
id: 100,
|
||||
symbol: 'XDAI',
|
||||
explorerurl: 'https://blockscout.com/xdai/mainnet/'
|
||||
},
|
||||
{
|
||||
name: 'Fuse Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.fuse.io',
|
||||
id: 122,
|
||||
symbol: 'FUSE',
|
||||
explorerurl: 'https://explorer.fuse.io/'
|
||||
},
|
||||
{
|
||||
name: 'HECO Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://http-mainnet-node.huobichain.com/',
|
||||
id: 128,
|
||||
symbol: 'HT',
|
||||
explorerurl: 'https://hecoinfo.com/'
|
||||
},
|
||||
{
|
||||
name: 'Matic Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://polygon-rpc.com',
|
||||
id: 137,
|
||||
symbol: 'MATIC',
|
||||
explorerurl: 'https://explorer.matic.network/'
|
||||
},
|
||||
{
|
||||
name: 'Fantom Opera Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.ftm.tools/',
|
||||
id: 250,
|
||||
symbol: 'FTM',
|
||||
explorerurl: 'https://ftmscan.com'
|
||||
},
|
||||
{
|
||||
name: 'HECO Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://http-testnet.hecochain.com',
|
||||
id: 256,
|
||||
symbol: 'HT',
|
||||
explorerurl: 'https://testnet.hecoinfo.com/'
|
||||
},
|
||||
{
|
||||
name: 'KCC Mainnet',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc-mainnet.kcc.network',
|
||||
id: 321,
|
||||
logo: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzMiAzMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzIgMzI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojMDA5M0REO30KCS5zdDF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPGc+Cgk8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIxNiIgY3k9IjE2IiByPSIxNiIvPgoJPHBhdGggY2xhc3M9InN0MSIgZD0iTTEzLjUsMTZsNS4yLDUuM0wyMiwxOGMwLjYtMC42LDEuNS0wLjYsMiwwYzAsMCwwLDAsMCwwYzAuNiwwLjYsMC42LDEuNiwwLDIuMmwtNC4zLDQuNAoJCWMtMC42LDAuNi0xLjUsMC42LTIuMSwwYzAsMCwwLDAsMCwwbC02LjItNi40VjIyYzAsMC44LTAuNywxLjUtMS41LDEuNWMtMC44LDAtMS41LTAuNy0xLjUtMS41VjEwYzAtMC44LDAuNy0xLjUsMS41LTEuNQoJCWMwLjgsMCwxLjUsMC43LDEuNSwxLjV2My44bDYuMi02LjRjMC42LTAuNiwxLjUtMC42LDIuMSwwYzAsMCwwLDAsMCwwbDQuMyw0LjRjMC42LDAuNiwwLjYsMS42LDAsMi4yYy0wLjYsMC42LTEuNSwwLjYtMiwwCgkJYzAsMCwwLDAsMCwwbC0zLjMtMy40TDEzLjUsMTZ6IE0xOC43LDE0LjVjMC44LDAsMS41LDAuNywxLjUsMS41cy0wLjcsMS41LTEuNSwxLjVzLTEuNS0wLjctMS41LTEuNQoJCUMxNy4yLDE1LjIsMTcuOSwxNC41LDE4LjcsMTQuNXoiLz4KPC9nPgo8L3N2Zz4K',
|
||||
symbol: 'KCS',
|
||||
explorerurl: 'https://scan.kcc.network'
|
||||
},
|
||||
{
|
||||
name: 'KCC Testnet',
|
||||
type: 'Testnet',
|
||||
logo: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzMiAzMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzIgMzI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojMDA5M0REO30KCS5zdDF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPGc+Cgk8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIxNiIgY3k9IjE2IiByPSIxNiIvPgoJPHBhdGggY2xhc3M9InN0MSIgZD0iTTEzLjUsMTZsNS4yLDUuM0wyMiwxOGMwLjYtMC42LDEuNS0wLjYsMiwwYzAsMCwwLDAsMCwwYzAuNiwwLjYsMC42LDEuNiwwLDIuMmwtNC4zLDQuNAoJCWMtMC42LDAuNi0xLjUsMC42LTIuMSwwYzAsMCwwLDAsMCwwbC02LjItNi40VjIyYzAsMC44LTAuNywxLjUtMS41LDEuNWMtMC44LDAtMS41LTAuNy0xLjUtMS41VjEwYzAtMC44LDAuNy0xLjUsMS41LTEuNQoJCWMwLjgsMCwxLjUsMC43LDEuNSwxLjV2My44bDYuMi02LjRjMC42LTAuNiwxLjUtMC42LDIuMSwwYzAsMCwwLDAsMCwwbDQuMyw0LjRjMC42LDAuNiwwLjYsMS42LDAsMi4yYy0wLjYsMC42LTEuNSwwLjYtMiwwCgkJYzAsMCwwLDAsMCwwbC0zLjMtMy40TDEzLjUsMTZ6IE0xOC43LDE0LjVjMC44LDAsMS41LDAuNywxLjUsMS41cy0wLjcsMS41LTEuNSwxLjVzLTEuNS0wLjctMS41LTEuNQoJCUMxNy4yLDE1LjIsMTcuOSwxNC41LDE4LjcsMTQuNXoiLz4KPC9nPgo8L3N2Zz4K',
|
||||
rpc: 'https://rpc-testnet.kcc.network',
|
||||
id: 322,
|
||||
symbol: 'tKCS',
|
||||
explorerurl: 'https://scan-testnet.kcc.network'
|
||||
},
|
||||
{
|
||||
name: 'Moonriver Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.moonriver.moonbeam.network',
|
||||
id: 1285,
|
||||
symbol: 'MOVR',
|
||||
explorerurl: 'https://blockscout.moonriver.moonbeam.network/'
|
||||
},
|
||||
{
|
||||
name: 'Fantom Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://rpc.testnet.fantom.network/',
|
||||
id: 4002,
|
||||
symbol: 'FTM',
|
||||
explorerurl: 'https://testnet.ftmscan.com'
|
||||
},
|
||||
{
|
||||
name: 'IoTeX Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://babel-api.mainnet.iotex.io',
|
||||
id: 4689,
|
||||
symbol: 'IOTEX',
|
||||
explorerurl: 'https://iotexscan.io/'
|
||||
},
|
||||
{
|
||||
name: 'Nahmii Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://l2.nahmii.io/',
|
||||
id: 5551,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://explorer.nahmii.io/'
|
||||
},
|
||||
{
|
||||
name: 'Nahmii Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://l2.testnet.nahmii.io/',
|
||||
id: 5553,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://explorer.testnet.nahmii.io/'
|
||||
},
|
||||
{
|
||||
name: 'Arbitrum One',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://arbitrum-one.public.blastapi.io',
|
||||
id: 42161,
|
||||
symbol: 'ETH',
|
||||
explorerurl: 'https://explorer.arbitrum.io'
|
||||
},
|
||||
{
|
||||
name: 'Arbitrum Goerli',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://arbitrum-goerli.public.blastapi.io',
|
||||
id: 421613,
|
||||
symbol: 'AGOR',
|
||||
explorerurl: 'https://goerli-rollup-explorer.arbitrum.io'
|
||||
},
|
||||
{
|
||||
name: 'Celo Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.ankr.com/celo',
|
||||
id: 42220,
|
||||
symbol: 'CELO',
|
||||
explorerurl: 'https://celoscan.com'
|
||||
},
|
||||
{
|
||||
name: 'Avalanche C Chain Local RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://localhost:9650/ext/bc/C/rpc',
|
||||
id: 43112,
|
||||
symbol: 'AVAX',
|
||||
explorerurl: 'https://snowtrace.io'
|
||||
},
|
||||
{
|
||||
name: 'Avalanche FUJI Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://api.avax-test.network/ext/bc/C/rpc',
|
||||
id: 43113,
|
||||
symbol: 'AVAX',
|
||||
explorerurl: 'https://testnet.explorer.avax.network/'
|
||||
},
|
||||
{
|
||||
name: 'Avalanche C Chain Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://rpc.ankr.com/avalanche',
|
||||
id: 43114,
|
||||
symbol: 'AVAX',
|
||||
explorerurl: 'https://snowtrace.io'
|
||||
},
|
||||
{
|
||||
name: 'Matic Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://rpc-mumbai.maticvigil.com',
|
||||
id: 80001,
|
||||
symbol: 'MATIC',
|
||||
explorerurl: 'https://mumbai.polygonscan.com/'
|
||||
},
|
||||
{
|
||||
name: 'Harmony Mainnet RPC',
|
||||
type: 'Mainnet',
|
||||
rpc: 'https://api.harmony.one/',
|
||||
id: 1666600000,
|
||||
symbol: 'ONE',
|
||||
explorerurl: 'https://explorer.harmony.one'
|
||||
},
|
||||
{
|
||||
name: 'Harmony Testnet RPC',
|
||||
type: 'Testnet',
|
||||
rpc: 'https://api.s0.b.hmny.io/',
|
||||
id: 1666700000,
|
||||
symbol: 'ONE',
|
||||
explorerurl: 'https://explorer.harmony.one'
|
||||
}
|
||||
]
|
59
src/configs/configchain.js
Normal file
3398
src/configs/contracts.ts
Normal file
4
src/configs/global.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export namespace Global {
|
||||
export const MEDAL_REWARDS_Address: string = "0x54f6e2B13d9F754f7676494d3F53426C594D65b3"; // 分发地址
|
||||
export const LIMIT_ABI_Address: string = "0x8E2ab40CA9dc6871131AacC1F82bf73B28DB75F9"; // 徽章地址
|
||||
}
|
75
src/configs/information.js
Normal file
@ -0,0 +1,75 @@
|
||||
export const HeroList = [
|
||||
{
|
||||
id: 1,
|
||||
img: new URL("@/assets/img/home/hero/001.png", import.meta.url).href,
|
||||
name: "midif",
|
||||
slogan:
|
||||
"Coming from the Black Forest region on the West Coast, Aoi is rumored to be a descendant of the Grand Druid. Because of her fondness for candy, she often seals her cure magics in lollipops.",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
img: new URL("@/assets/img/home/hero/002.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Canoe, the Priest of the Church of Fallen Angels, is a master summoner of hordes of mechs. Her greatest pleasure is fueled by her opponents' desperation.",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
img: new URL("@/assets/img/home/hero/003.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Mariana was originally a fur trapper in the Beast Valley of the South. After accidentally touching the blood of Beshimus, Mariana gained the powerful shape-shifting ability.",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
img: new URL("@/assets/img/home/hero/004.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"The Fox Clan of Hill has been there for a long time. They are good charmers. The prettier they are, the greater their strength. And Hill is at the top of her craft.",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
img: new URL("@/assets/img/home/hero/005.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Raised by a group of assassins after losing her parents at an early age, Astral grows into an agile and skilled assassin.",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
img: new URL("@/assets/img/home/hero/006.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Miffy likes to play hide-and-seek with people and observe them in the dark. No one knows why. Maybe she's just timid and wants to play with everyone.",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
img: new URL("@/assets/img/home/hero/007.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Yamato is a gifted scholar who can easily build the most powerful bombs yet often forgets the trifles of life.",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
img: new URL("@/assets/img/home/hero/008.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Dragonscale's origin is obscure. It is said that he came here from a mysterious land in the East in search of an ancient artifact that would relieve his people of their misery.",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
img: new URL("@/assets/img/home/hero/009.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Kurosawa is the youngest of the king's guards in Shata, with a resolute and steady personality unlike his peers. Imbued with royal protocol, he also has an amazing flair for food and tasting.",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
img: new URL("@/assets/img/home/hero/010.png", import.meta.url).href,
|
||||
name: "ChipCard",
|
||||
slogan:
|
||||
"Lazer was born in the Exile Street, where he grew up poor and often fought in underground boxing matches for a living. He takes the law of the jungle as his creed and shows no mercy to enemies.",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
HeroList,
|
||||
};
|
25
src/hooks/useCopyToClipboard.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { ref } from "vue";
|
||||
|
||||
export function useCopyToClipboard() {
|
||||
const copied = ref(false);
|
||||
const error = ref(null);
|
||||
|
||||
const reset = () => {
|
||||
copied.value = false;
|
||||
error.value = null;
|
||||
};
|
||||
const copyToClipboard = async (text) => {
|
||||
try {
|
||||
if (!navigator.clipboard) {
|
||||
throw new Error("Clipboard API not available");
|
||||
}
|
||||
await navigator.clipboard.writeText(text);
|
||||
copied.value = true;
|
||||
} catch (err) {
|
||||
error.value = err;
|
||||
//console.error("Failed to copy text: ", err);
|
||||
}
|
||||
};
|
||||
|
||||
return { copied, error, reset, copyToClipboard };
|
||||
}
|
17
src/hooks/useDebounce.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
function useDebounce(value, delay = 500) {
|
||||
const debouncedValue = ref(value)
|
||||
let timer
|
||||
|
||||
const debounce = () => {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
debouncedValue.value = value.value
|
||||
}, delay)
|
||||
}
|
||||
|
||||
debounce()
|
||||
|
||||
return debouncedValue
|
||||
}
|
3
src/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
36
src/main.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { createApp } from "vue";
|
||||
// import './style.css'
|
||||
import "./style/rest.css";
|
||||
import "normalize.css";
|
||||
import "@/assets/text/text.css";
|
||||
import "./index.css"; // 导入 Tailwind CSS 样式
|
||||
import Antd from "ant-design-vue";
|
||||
import "ant-design-vue/dist/antd.css";
|
||||
import pinia from "@/store";
|
||||
import router from "./router/index";
|
||||
import VueAnimXyz from "@animxyz/vue3";
|
||||
import "@animxyz/core"; // Import css here if you haven't elsewhere
|
||||
import App from "./App.vue";
|
||||
import vue3dLoader from "vue-3d-loader";
|
||||
import VueClipboard from "vue3-clipboard";
|
||||
import Vue3Autocounter from 'vue3-autocounter';
|
||||
import { notification } from 'ant-design-vue';
|
||||
|
||||
notification.config({
|
||||
placement: 'topRight',
|
||||
top: '90px',
|
||||
duration: 100,
|
||||
rtl: true,
|
||||
});
|
||||
const app = createApp(App);
|
||||
|
||||
app.config.globalProperties.$log = console.log.bind(console);
|
||||
|
||||
app
|
||||
.use(pinia)
|
||||
.use(VueClipboard)
|
||||
.use(VueAnimXyz)
|
||||
.use(vue3dLoader)
|
||||
.use(Antd)
|
||||
.use(router)
|
||||
.mount("#app");
|
107
src/router/index.js
Normal file
@ -0,0 +1,107 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: "/",
|
||||
name: "index1",
|
||||
component: () =>
|
||||
import(/* webpackChunkName "index1" */ "@/views/MapView.vue"),
|
||||
meta: {
|
||||
title: "Planet",
|
||||
canonical: "https://gacha.counterfire.games",
|
||||
alternate: "https://m.gacha.counterfire.games",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/quest",
|
||||
name: "QUEST",
|
||||
meta: {
|
||||
title: "Planet Quest",
|
||||
canonical: "https://gacha.counterfire.games/quest",
|
||||
alternate: "https://m.gacha.counterfire.games/quest",
|
||||
},
|
||||
component: () =>
|
||||
import(/* webpackChunkName "marketplace" */ "@/views/TaskView.vue"),
|
||||
},
|
||||
{
|
||||
path: "/index.html",
|
||||
name: "index",
|
||||
component: () =>
|
||||
import(/* webpackChunkName "index" */ "@/views/TaskView.vue"),
|
||||
meta: {
|
||||
title: "Gacha index",
|
||||
canonical: "https://gacha.counterfire.games/index.html",
|
||||
alternate: "https://m.gacha.counterfire.games/index.html",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/undertest",
|
||||
name: "TaskOne",
|
||||
meta: {
|
||||
title: "Gacha Undertest",
|
||||
canonical: "https://gacha.counterfire.games/undertest",
|
||||
alternate: "https://m.gacha.counterfire.games/undertest",
|
||||
},
|
||||
component: () =>
|
||||
import(/* webpackChunkName "TaskOne" */ "@/components/task/TaskOne.vue"),
|
||||
},
|
||||
{
|
||||
path: "/taskTwo",
|
||||
name: "TaskTwo",
|
||||
meta: {
|
||||
title: "Gacha TaskTwo",
|
||||
canonical: "https://gacha.counterfire.games/taskTwo",
|
||||
alternate: "https://m.gacha.counterfire.games/taskTwo",
|
||||
},
|
||||
component: () =>
|
||||
import(/* webpackChunkName "TaskTwo" */ "@/components/task/TaskTwo.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
return { top: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
function isMobileDevice(userAgent) {
|
||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||||
userAgent
|
||||
);
|
||||
}
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const isMobile = isMobileDevice(window.navigator.userAgent);
|
||||
|
||||
// 对于 PC 端官网项目:
|
||||
if (!isMobile) {
|
||||
if (to.meta.title) {
|
||||
document.title = to.meta.title;
|
||||
}
|
||||
let link = document.querySelector("link[rel='canonical']");
|
||||
if (!link) {
|
||||
link = document.createElement("link");
|
||||
link.rel = "canonical";
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
link.href = to.meta.canonical;
|
||||
|
||||
let alternateLink = document.querySelector("link[rel='alternate']");
|
||||
if (!alternateLink) {
|
||||
alternateLink = document.createElement("link");
|
||||
alternateLink.rel = "alternate";
|
||||
alternateLink.media = "only screen and (max-width: 640px)";
|
||||
document.head.appendChild(alternateLink);
|
||||
}
|
||||
alternateLink.href = to.meta.alternate;
|
||||
|
||||
next(); // 如果是 PC 设备,继续导航
|
||||
} else {
|
||||
window.location.href = `https://m.gacha.counterfire.games${ to.query.code ? '?code=' + to.query.code : ""
|
||||
}`;
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
55
src/store/app.js
Normal file
@ -0,0 +1,55 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref } from 'vue';
|
||||
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
|
||||
const list = ref([
|
||||
{userId: "1", headpic: "/images/1667520250923113.webp"},
|
||||
{userId: "2", headpic: "/images/16555781459976085.webp"},
|
||||
{userId: "3", headpic: "/images/16595363622946259.webp"},
|
||||
{userId: "4", headpic: "/images/16620693455819353.webp"},
|
||||
]);
|
||||
|
||||
function get(userId) {
|
||||
return list.value.find(i=>i.userId==userId);
|
||||
}
|
||||
|
||||
const walletConnected = ref(false);
|
||||
const accountId = ref('');
|
||||
const chainId = ref(0);
|
||||
const presaleStatus = ref(0);
|
||||
const step = ref(0);
|
||||
const nonce = ref('');
|
||||
const token = ref('');
|
||||
|
||||
function updateWalletStatus(_connected) {
|
||||
walletConnected.value = _connected;
|
||||
}
|
||||
|
||||
function updateAccount(_accountId) {
|
||||
|
||||
accountId.value = _accountId;
|
||||
|
||||
}
|
||||
function updateChainID(_chainId) {
|
||||
chainId.value = _chainId;
|
||||
}
|
||||
function updateStep(_step) {
|
||||
step.value = _step;
|
||||
}
|
||||
function updateNonce(_nonce) {
|
||||
nonce.value = _nonce;
|
||||
}
|
||||
function updateToken(_token) {
|
||||
token.value = _token;
|
||||
}
|
||||
|
||||
return { list, get,
|
||||
accountId, updateAccount,
|
||||
chainId, updateChainID,
|
||||
walletConnected, updateWalletStatus,
|
||||
step, updateStep,
|
||||
nonce, updateNonce,
|
||||
token, updateToken,
|
||||
}
|
||||
})
|
16
src/store/chain.js
Normal file
@ -0,0 +1,16 @@
|
||||
import ChainManager from '@/chain/ChainManager';
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref } from 'vue';
|
||||
|
||||
export const useChainStore = defineStore('chain', ()=> {
|
||||
const logined = ref(false);
|
||||
const chainManager = ref(new ChainManager());
|
||||
chainManager.value.init().then(()=> {
|
||||
// console.log("chain init:", {chainManager})
|
||||
|
||||
logined.value = chainManager.value.isLogined;
|
||||
|
||||
});
|
||||
|
||||
return { chainManager, logined }
|
||||
})
|
3
src/store/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { createPinia } from "pinia";
|
||||
const pinia = createPinia();
|
||||
export default pinia;
|
95
src/store/user.js
Normal file
@ -0,0 +1,95 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
getToken,
|
||||
setToken,
|
||||
removeToken,
|
||||
getAccountId,
|
||||
setAccountId,
|
||||
removeAccountId,
|
||||
} from "@/utils/cookies";
|
||||
import glodata from "./user_global";
|
||||
|
||||
import pinia from "@/store";
|
||||
import { useAppStore } from "@/store/app";
|
||||
const AppModule = useAppStore(pinia);
|
||||
glodata.token = getToken();
|
||||
glodata.accountId = AppModule.accountId.value;
|
||||
glodata.chainId = AppModule.chainId.value;
|
||||
import { login } from "@/api/User";
|
||||
|
||||
export const useUserStore = defineStore("user", () => {
|
||||
const EIP721_DOMAIN_DATA = [
|
||||
{ name: "name", type: "string" },
|
||||
{ name: "version", type: "string" },
|
||||
];
|
||||
|
||||
const token = ref(getToken());
|
||||
const accountId = ref(getAccountId());
|
||||
AppModule.updateAccount(accountId.value);
|
||||
if (token.value && accountId.value) {
|
||||
AppModule.updateStep(1);
|
||||
}
|
||||
|
||||
async function Login({ bcInstance, account, chainId, nonce }) {
|
||||
nonce += "";
|
||||
const tips =
|
||||
"Hi!Welcome to Counter Fire.\nPlease sign to verify wallet ownership.\nSigning is gas-less and non-transactional.";
|
||||
const signMsg = {
|
||||
tips,
|
||||
nonce,
|
||||
};
|
||||
|
||||
const signObj = {
|
||||
types: {
|
||||
EIP712Domain: EIP721_DOMAIN_DATA,
|
||||
set: [
|
||||
{ name: "tips", type: "string" },
|
||||
{ name: "nonce", type: "string" },
|
||||
],
|
||||
},
|
||||
primaryType: "set",
|
||||
domain: {
|
||||
name: "Auth",
|
||||
version: "1",
|
||||
},
|
||||
message: signMsg,
|
||||
};
|
||||
const signature = await bcInstance.signData(signObj, account);
|
||||
const authData = {
|
||||
account,
|
||||
nonce,
|
||||
signature,
|
||||
tips,
|
||||
net_id: chainId,
|
||||
};
|
||||
|
||||
const res = await login(authData);
|
||||
if (!res.errcode && res.token) {
|
||||
accountId.value = account;
|
||||
setToken(res.token);
|
||||
|
||||
setAccountId(account);
|
||||
AppModule.updateAccount(account);
|
||||
AppModule.updateToken(res.token);
|
||||
token.value = res.token;
|
||||
}
|
||||
}
|
||||
|
||||
function Logout() {
|
||||
if (token === "") {
|
||||
return;
|
||||
}
|
||||
removeAccountId();
|
||||
removeToken();
|
||||
token.value = "";
|
||||
accountId.value = "";
|
||||
AppModule.updateAccount("");
|
||||
}
|
||||
|
||||
return {
|
||||
token,
|
||||
Login,
|
||||
Logout,
|
||||
};
|
||||
});
|
5
src/store/user_global.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
token:"",
|
||||
accountId:"",
|
||||
chainId:0,
|
||||
}
|
237
src/style/rest.css
Normal file
@ -0,0 +1,237 @@
|
||||
html,
|
||||
body,
|
||||
div,
|
||||
span,
|
||||
applet,
|
||||
object,
|
||||
iframe,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p,
|
||||
blockquote,
|
||||
pre,
|
||||
a,
|
||||
abbr,
|
||||
acronym,
|
||||
address,
|
||||
big,
|
||||
cite,
|
||||
code,
|
||||
del,
|
||||
dfn,
|
||||
em,
|
||||
font,
|
||||
img,
|
||||
ins,
|
||||
kbd,
|
||||
q,
|
||||
s,
|
||||
samp,
|
||||
small,
|
||||
strike,
|
||||
strong,
|
||||
sub,
|
||||
sup,
|
||||
tt,
|
||||
var,
|
||||
b,
|
||||
u,
|
||||
i,
|
||||
center,
|
||||
dl,
|
||||
dt,
|
||||
dd,
|
||||
ol,
|
||||
ul,
|
||||
li,
|
||||
fieldset,
|
||||
form,
|
||||
label,
|
||||
legend,
|
||||
caption {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
table,
|
||||
tbody,
|
||||
tfoot,
|
||||
thead,
|
||||
tr,
|
||||
th,
|
||||
td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
outline: 0;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
textarea {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
/* form elements 表单元素 */
|
||||
body,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font: normal 12px/1.5 '\5FAE\8F6F\96C5\9ED1', tahoma, arial;
|
||||
}
|
||||
|
||||
/*设置的字体,行高*/
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
th {
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/*重置标题*/
|
||||
address,
|
||||
cite,
|
||||
dfn,
|
||||
var {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* 将斜体扶正 */
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: 'courier new', courier, monospace;
|
||||
}
|
||||
|
||||
/* 统一等宽字体 */
|
||||
small {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 小于 12px 的中文很难阅读,让 small 正常化 */
|
||||
ul,
|
||||
ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/* 重置列表元素 */
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"],
|
||||
input[type="submit"],
|
||||
input[type="reset"] {
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/** 重置文本格式元素 **/
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
a:focus {
|
||||
outline: 0;
|
||||
}
|
||||
sup {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
/* 重置,减少对行高的影响 */
|
||||
sub {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
/** 重置表单元素 **/
|
||||
legend {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* for ie6 */
|
||||
fieldset,
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* img 搭车:让链接里的 img 无边框 */
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
background: transparent;
|
||||
font-size: 100%;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* 使得表单元素在 ie 下能继承字体大小 */
|
||||
/* 注:optgroup 无法扶正 */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/** 重置表格元素 **/
|
||||
/* 重置 HTML5 元素 */
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary,
|
||||
time,
|
||||
mark,
|
||||
audio,
|
||||
video {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*回复标签重置*/
|
||||
blockquote,
|
||||
q {
|
||||
quotes: none;
|
||||
}
|
||||
|
||||
blockquote:before,
|
||||
blockquote:after,
|
||||
q:before,
|
||||
q:after {
|
||||
content: '';
|
||||
display: none;
|
||||
}
|