feat:更新

This commit is contained in:
dengtongyu committed 2021-08-28 20:47:35 +08:00
1 parent 03c799e6a5
commit 04266eb0bb
48 files changed
+864 -195

No files matched your search

+2 -17
View File
@@ -7,7 +7,7 @@ let target = "";
switch (VUE_APP_PROXY) {
case 1:
target = "http://test.haloapp.vip";
target = "http://im.haloapp.vip";
break;
case 2:
target = "http://haloapp.vip";
@@ -17,22 +17,7 @@ switch (VUE_APP_PROXY) {
}
let proxyTable = {
"/zuul": {
target: target,
changeOrigin: true,
secure: false
},
"/sjht": {
target: target,
changeOrigin: true,
secure: false
},
"/media/": {
target: target,
changeOrigin: true,
secure: false
},
"/bzdb": {
"/api": {
target: target,
changeOrigin: true,
secure: false
+5 -11
View File
@@ -7,16 +7,10 @@
<style lang="scss">
@import "@/styles";
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
#app {
background-color: #18012d;
background-image: url(assets/images/bg.png);
background-repeat: no-repeat;
background-size: 100%;
}
</style>
+5 -5
View File
@@ -2,11 +2,11 @@ import ajax from "@/lib/ajax";
import config from "@/config";
// host
const HOST = config.host("/zuul", "/mrxf");
const HOST = config.host("/api", "/act");
// 来访总量统计列表
const petitionReportTotal = param => {
return ajax.post(`${HOST}/petitionReport/total`, param);
// 获取奖品信息
const queryPrizeInfo = param => {
return ajax.get(`${HOST}/queryPrizeInfo`, param);
};
export { petitionReportTotal };
export { queryPrizeInfo };
File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+7
View File
@@ -0,0 +1,7 @@
import BallContent from "./main";
BallContent.install = function(Vue) {
Vue.component(BallContent.name, BallContent);
};
export default BallContent;
+55
View File
@@ -0,0 +1,55 @@
<template>
<div class="ball-content" :class="modeClass">
<div class="ball-content-main">
<div class="ball-content-main-grid">
<lucky-grid-view :mode="mode"></lucky-grid-view>
</div>
</div>
</div>
</template>
<script>
import luckyGridView from "@/components/luckyGridView";
export default {
name: "BallContent",
components: {
luckyGridView
},
props: {
mode: {
type: String,
default: "blue"
}
},
computed: {
modeClass() {
if (this.mode === "blue") return "ball-xy";
return "ball-hh";
}
}
};
</script>
<style lang="scss" scoped>
.ball-content {
width: 676px;
height: 430px;
background-repeat: no-repeat;
background-size: cover;
padding-top: 57px;
margin: 0 auto;
&-main {
height: 414px;
padding: 8px;
&-grid {
padding-top: 78px;
}
}
}
.ball-xy {
background-image: url(../../assets/images/giftbox.png);
}
.ball-hh {
background-image: url(../../assets/images/giftbox_g.png);
}
</style>
+68
View File
@@ -0,0 +1,68 @@
<template>
<div class="balance-view" :class="modeClass">
<div class="balance-view-text">
<label>鱼券:</label>
<span>{{ value }}</span>
</div>
<div class="balance-view-btn"></div>
</div>
</template>
<script>
export default {
name: "BalanceView",
props: {
mode: {
type: String,
default: "blue"
},
value: {
type: Number,
default: 0
}
},
computed: {
modeClass() {
if (this.mode === "blue") return "balance-view-xy";
return "balance-view-hh";
}
}
};
</script>
<style lang="scss" scoped>
.balance-view {
width: 345px;
height: 84px;
background-repeat: no-repeat;
background-size: cover;
display: flex;
align-items: center;
&-text {
flex: 1;
height: 100%;
display: flex;
align-items: center;
padding-left: 30px;
font-size: 24px;
& > label {
color: #fff;
}
& > span {
color: #ffe26c;
}
}
&-btn {
width: 60px;
height: 60px;
border-radius: 50%;
margin-right: 14px;
}
}
.balance-view-xy {
background-image: url(../../assets/images/yue_bg.png);
}
.balance-view-hh {
background-image: url(../../assets/images/yue_bg_g.png);
}
</style>
+7
View File
@@ -0,0 +1,7 @@
import BottomView from "./main";
BottomView.install = function(Vue) {
Vue.component(BottomView.name, BottomView);
};
export default BottomView;
+36
View File
@@ -0,0 +1,36 @@
<template>
<div class="lottery-btn" :class="modeClass"></div>
</template>
<script>
export default {
name: "LotteryBtn",
props: {
mode: {
type: String,
default: "blue"
}
},
computed: {
modeClass() {
if (this.mode === "blue") return "lottery-btn-xy";
return "lottery-btn-hh";
}
}
};
</script>
<style lang="scss" scoped>
.lottery-btn {
width: 262px;
height: 115px;
background-repeat: no-repeat;
background-size: cover;
}
.lottery-btn-xy {
background-image: url(../../assets/images/cj_btn.png);
}
.lottery-btn-hh {
background-image: url(../../assets/images/cj_btn_g.png);
}
</style>
+98
View File
@@ -0,0 +1,98 @@
<template>
<div class="bottom-view" :class="modeClass">
<div class="bottom-view-top">
<balance-view :mode="mode"></balance-view>
<lottery-btn :mode="mode"></lottery-btn>
</div>
<div class="bottom-view-bottom">
<ticket-view
v-for="(item, key) in list"
:key="`ticket_view_${key}`"
:label="item.label"
:desc="item.desc"
:active="active === key"
:mode="mode"
></ticket-view>
</div>
</div>
</template>
<script>
import balanceView from "./balanceView.vue";
import lotteryBtn from "./lotteryBtn.vue";
import ticketView from "./ticketView.vue";
export default {
name: "BottomView",
components: {
balanceView,
lotteryBtn,
ticketView
},
props: {
mode: {
type: String,
default: "blue"
}
},
computed: {
modeClass() {
if (this.mode === "blue") return "bottom-view-xy";
return "bottom-view-hh";
}
},
data() {
return {
active: 0,
list: [
{
label: "1次",
desc: "1张鱼券",
value: 1
},
{
label: "10次",
desc: "10张鱼券",
value: 1
},
{
label: "100次",
desc: "100张鱼券",
value: 1
}
]
};
}
};
</script>
<style lang="scss" scoped>
.bottom-view {
width: 694px;
height: 300px;
background-repeat: no-repeat;
background-size: cover;
margin: 0 auto;
&-top {
display: flex;
width: 635px;
height: 115px;
margin: 0 auto;
padding-top: 18px;
justify-content: space-between;
align-items: center;
}
&-bottom {
padding-top: 20px;
padding-left: 242px;
padding-right: 34px;
display: flex;
justify-content: space-between;
}
}
.bottom-view-xy {
background-image: url(../../assets/images/bottom_bg.png);
}
.bottom-view-hh {
background-image: url(../../assets/images/bottom_bg_g.png);
}
</style>
+98
View File
@@ -0,0 +1,98 @@
<template>
<div class="ticket-view" :class="modeClass">
<div class="ticket-view-main">
<label>{{ label }}</label>
<p>({{ desc }})</p>
</div>
</div>
</template>
<script>
export default {
name: "TicketView",
props: {
mode: {
type: String,
default: "blue"
},
active: {
type: Boolean,
default: false
},
label: {
type: String,
default: ""
},
desc: {
type: String,
default: ""
}
},
computed: {
modeClass() {
let str = "";
if (this.mode === "blue") {
str = "ticket-view-xy";
} else {
str = "ticket-view-hh";
}
if (this.active) str += "-active";
return str;
}
},
data() {
return {};
}
};
</script>
<style lang="scss" scoped>
.ticket-view {
width: 130px;
height: 110px;
background-repeat: no-repeat;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
&-main {
// width: 104px;
width: 100%;
height: 84px;
color: #7525b6;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
& > label {
font-size: 26px;
font-weight: bold;
// -webkit-transform: scale(0.5);
// transform: scale(0.5);
}
& > p {
font-size: 20px;
-webkit-transform: scale(0.7);
transform: scale(0.7);
}
}
}
.ticket-view-xy {
background-image: url(../../assets/images/tikect_bg_nomal.png);
}
.ticket-view-hh {
background-image: url(../../assets/images/tikect_bg_nomal_g.png);
.ticket-view-main {
color: #8b3410;
}
}
.ticket-view-xy-active {
background-image: url(../../assets/images/tikect_bg_active.png);
}
.ticket-view-hh-active {
background-image: url(../../assets/images/tikect_bg_active_g.png);
.ticket-view-main {
color: #8b3410;
}
}
</style>
+53
View File
@@ -0,0 +1,53 @@
<template>
<div class="btn-view" :class="modeClass">
<div class="btn-view-touch">{{ text }}</div>
</div>
</template>
<script>
export default {
name: "BtnView",
props: {
mode: {
type: String,
default: "blue"
},
text: {
type: String,
default: ""
}
},
computed: {
modeClass() {
if (this.mode === "blue") return "btn-view-xy";
return "btn-view-hh";
}
}
};
</script>
<style lang="scss" scoped>
.btn-view {
width: 107px;
height: 61px;
background-repeat: no-repeat;
background-size: cover;
padding-top: 8px;
&-touch {
width: 100%;
height: 100%;
line-height: 61px;
color: #fff;
text-align: center;
text-shadow: 0 1px 2px #333;
font-size: 28px;
font-weight: 600;
}
}
.btn-view-xy {
background-image: url(../../assets/images/enter_btn_bg.png);
}
.btn-view-hh {
background-image: url(../../assets/images/enter_btn_bg_g.png);
}
</style>
+7
View File
@@ -0,0 +1,7 @@
import EnterView from "./main";
EnterView.install = function(Vue) {
Vue.component(EnterView.name, EnterView);
};
export default EnterView;
+66
View File
@@ -0,0 +1,66 @@
<template>
<div class="enter-view" :class="modeClass">
<div class="enter-view-list">
<btn-view
v-for="(item, key) in btnList"
:key="`enter_view_list_${key}`"
:text="item"
:mode="mode"
></btn-view>
</div>
</div>
</template>
<script>
import btnView from "./btnView.vue";
export default {
name: "EnterView",
components: {
btnView
},
props: {
mode: {
type: String,
default: "blue"
}
},
computed: {
modeClass() {
if (this.mode === "blue") return "enter-view-xy";
return "enter-view-hh";
}
},
data() {
return {
btnList: ["规则", "奖品", "排行", "记录"]
};
}
};
</script>
<style lang="scss" scoped>
.enter-view {
width: 676px;
height: 79px;
background-repeat: no-repeat;
background-size: cover;
background-position-y: -98px;
background-position-x: center;
margin: 0 auto;
&-list {
display: flex;
width: 563px;
height: 100%;
justify-content: space-between;
align-items: flex-end;
margin: 0 auto;
}
}
.enter-view-xy {
background-image: url(../../assets/images/enter_bg.png);
}
.enter-view-hh {
background-image: url(../../assets/images/enter_bg_g.png);
}
</style>
+7
View File
@@ -0,0 +1,7 @@
import LuckyGridView from "./main";
LuckyGridView.install = function(Vue) {
Vue.component(LuckyGridView.name, LuckyGridView);
};
export default LuckyGridView;
+184
View File
@@ -0,0 +1,184 @@
<template>
<div class="lucky-grid-view">
<LuckyGrid
class="lucky-grid"
ref="LuckDraw"
rows="2"
cols="4"
:prizes="prizes"
:blocks="blocks"
:default-config="defaultConfig"
:default-style="defaultStyle"
:active-style="activeStyle"
@start="startCallBack"
@end="endCallBack"
/>
</div>
</template>
<script>
import { LuckyGrid } from "vue-luck-draw";
import { queryPrizeInfo } from "@/api";
export default {
name: "LuckyGridView",
components: {
LuckyGrid
},
props: {
mode: {
type: String,
default: "blue"
}
},
data() {
return {
luckyNum: 0,
prizes: [],
blocks: [
// { padding: "15px", background: "#ffc27a", borderRadius: 28 },
// { padding: "4px", background: "#ff4a4c", borderRadius: 23 },
// { padding: "4px", background: "#ff625b", borderRadius: 20 }
],
defaultConfig: {
gutter: 5
},
defaultStyle: {},
activeStyle: {
background: "linear-gradient(270deg, #FFDCB8, #FDC689)",
shadow: ""
},
axis: [
[0, 0],
[1, 0],
[2, 0],
[3, 0],
[3, 1],
[2, 1],
[1, 1],
[0, 1]
]
};
},
computed: {
drawType() {
if (this.mode === "blue") return "turntable1";
return "turntable2";
}
},
mounted() {
this.getQueryPrizeInfo();
},
methods: {
getQueryPrizeInfo() {
queryPrizeInfo({ drawType: this.drawType }).then(res => {
const { code, data } = res;
if (code === 200) {
this.prizes = this.configPrizes(data);
}
});
},
configPrizes(prizeInfo) {
const data = [
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
},
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
},
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
},
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
},
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
},
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
},
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
},
{
img: [
require("@/assets/images/ball_02.png"),
require("@/assets/images/ball_01.png")
]
}
];
const prizes = [];
this.luckyNum = 1;
for (let i = 0; i < 8; i++) {
let item = data[i];
let prizeItem = prizeInfo[i];
prizes.push({
index: i,
x: this.axis[i][0],
y: this.axis[i][1],
// fonts: [{ text: item.name, top: "70%" }],
imgs: [
{ src: item.img[0], width: "80%", top: "10%" },
{ src: prizeItem.prizeImgUrl, width: "50%", top: "30%" },
{ src: item.img[1], width: "80%", top: "10%" }
]
});
}
return prizes;
},
unitFunc(num, unit) {
console.log(num, unit);
if (unit === "vw") {
return (window.innerWidth / 100) * num;
}
},
startCallBack() {
if (!this.luckyNum) return alert("还剩0次抽奖机会");
this.$refs.LuckDraw.play();
setTimeout(() => {
this.$refs.LuckDraw.stop((Math.random() * 7) >> 0);
}, 2000);
},
endCallBack(prize) {
alert(`恭喜你获得大奖: ${prize.fonts[0].text}`);
this.luckyNum--;
},
clickHander() {
this.startCallBack();
}
}
};
</script>
<style lang="scss" scoped>
.lucky-grid-view {
width: 660px;
height: 330px;
margin: 0 auto;
.lucky-grid {
width: 100%;
height: 100%;
}
}
</style>
+7
View File
@@ -0,0 +1,7 @@
import TopButton from "./main";
TopButton.install = function(Vue) {
Vue.component(TopButton.name, TopButton);
};
export default TopButton;
+43
View File
@@ -0,0 +1,43 @@
<template>
<div class="top-button-large" :class="buttonClass">
<div class="top-button-large-touch"></div>
</div>
</template>
<script>
export default {
name: "LargeTopButton",
props: {
mode: {
type: String,
default: "blue"
}
},
computed: {
buttonClass() {
if (this.mode === "blue") return "top-button-xy";
return "top-button-hh";
}
}
};
</script>
<style lang="scss" scoped>
.top-button-large {
width: 276px;
height: 107px;
background-repeat: no-repeat;
background-size: cover;
&-touch {
width: 100%;
height: 96px;
cursor: pointer;
}
}
.top-button-hh {
background-image: url(../../assets/images/hh_btn_g.png);
}
.top-button-xy {
background-image: url(../../assets/images/xy_btn.png);
}
</style>
+36
View File
@@ -0,0 +1,36 @@
<template>
<div class="top-button">
<large-top-button :mode="mode"></large-top-button>
<small-top-button :mode="mode"></small-top-button>
</div>
</template>
<script>
import largeTopButton from "./large.vue";
import smallTopButton from "./small.vue";
export default {
name: "TopButton",
components: {
largeTopButton,
smallTopButton
},
props: {
mode: {
type: String,
default: "blue"
}
},
computed: {}
};
</script>
<style lang="scss" scoped>
.top-button {
display: flex;
width: 560px;
justify-content: space-between;
align-items: flex-end;
margin: 0 auto;
}
</style>
+43
View File
@@ -0,0 +1,43 @@
<template>
<div class="top-button-small" :class="buttonClass">
<div class="top-button-small-touch"></div>
</div>
</template>
<script>
export default {
name: "SmallTopButton",
props: {
mode: {
type: String,
default: "blue"
}
},
computed: {
buttonClass() {
if (this.mode === "blue") return "top-button-hh";
return "top-button-xy";
}
}
};
</script>
<style lang="scss" scoped>
.top-button-small {
width: 244px;
height: 78px;
background-repeat: no-repeat;
background-size: cover;
&-touch {
width: 100%;
height: 68px;
cursor: pointer;
}
}
.top-button-hh {
background-image: url(../../assets/images/hh_btn.png);
}
.top-button-xy {
background-image: url(../../assets/images/xy_btn_g.png);
}
</style>
+1 -1
View File
@@ -1,5 +1,5 @@
// 应用的名称
const appName = "每日信访动态报送";
const appName = "扭蛋机";
// 是否启用YApi
const YApi = false;
+36 -161
View File
@@ -1,189 +1,64 @@
<template>
<div class="home">
<div class="lucky-box">
<LuckyGrid
class="lucky-grid"
ref="LuckDraw"
rows="2"
cols="4"
:prizes="prizes"
:blocks="blocks"
:default-config="defaultConfig"
:default-style="defaultStyle"
:active-style="activeStyle"
@start="startCallBack"
@end="endCallBack"
/>
<div class="top-btn-and-box">
<div class="top-btn-box">
<top-button :mode="mode"></top-button>
</div>
<div class="top-ball-box">
<ball-content :mode="mode"></ball-content>
</div>
</div>
<div>
<enter-view :mode="mode"></enter-view>
</div>
<div>
<bottom-view :mode="mode"></bottom-view>
</div>
<button @click="clickHander">抽奖</button>
</div>
</template>
<script>
import { LuckyGrid } from "vue-luck-draw";
import topButton from "@/components/topButton";
import ballContent from "@/components/ballContent";
import enterView from "@/components/enterView";
import bottomView from "@/components/bottomView";
export default {
name: "Home",
components: {
LuckyGrid
topButton,
ballContent,
enterView,
bottomView
},
data() {
return {
luckyNum: 0,
prizes: [],
blocks: [
{ padding: "15px", background: "#ffc27a", borderRadius: 28 },
{ padding: "4px", background: "#ff4a4c", borderRadius: 23 },
{ padding: "4px", background: "#ff625b", borderRadius: 20 }
],
defaultConfig: {
gutter: 5
},
defaultStyle: {
borderRadius: 15,
fontColor: "#DF424B",
fontSize: "14px",
textAlign: "center",
background: "#fff",
shadow: "0 5 1 #ebf1f4"
},
activeStyle: {
background: "linear-gradient(270deg, #FFDCB8, #FDC689)",
shadow: ""
}
mode: "blue" // blue gold
};
},
computed: {
// buttons() {
// return [
// {
// x: 1,
// y: 1,
// background: "linear-gradient(270deg, #FFDCB8, #FDC689)",
// shadow: "0 5 1 #e89b4f",
// fonts: [
// {
// text: `${this.luckyNum} 次`,
// fontColor: "#fff",
// top: "73%",
// fontSize: "11px"
// }
// ]
// imgs: [
// { src: require("./img/button.png"), width: "65%", top: "13%" },
// { src: require("./img/btn.png"), width: "50%", top: "73%" }
// ]
// }
// ];
// }
},
mounted() {
this.getPrizeList();
},
methods: {
getPrizeList() {
// 模拟接口请求奖品列表
setTimeout(() => {
const data = [
{
name: "1元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
},
{
name: "100元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
},
{
name: "0.5元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
},
{
name: "2元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
},
{
name: "10元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
},
{
name: "50元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
},
{
name: "0.3元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
},
{
name: "5元红包",
img: [require("@/assets/logo.png"), require("@/assets/avatar.jpg")]
}
];
const prizes = [];
this.luckyNum = 1;
let axis = [
[0, 0],
[1, 0],
[2, 0],
[3, 0],
[3, 1],
[2, 1],
[1, 1],
[0, 1]
];
for (let i = 0; i < 8; i++) {
let item = data[i];
prizes.push({
index: i,
x: axis[i][0],
y: axis[i][1],
fonts: [{ text: item.name, top: "70%" }],
imgs: [
{ src: item.img[0], width: "55%", top: "8%" },
{ src: item.img[1], width: "70%" }
]
});
}
this.prizes = prizes;
}, 0);
},
unitFunc(num, unit) {
console.log(num, unit);
if (unit === "vw") {
return (window.innerWidth / 100) * num;
}
},
startCallBack() {
if (!this.luckyNum) return alert("还剩0次抽奖机会");
this.$refs.LuckDraw.play();
setTimeout(() => {
this.$refs.LuckDraw.stop((Math.random() * 7) >> 0);
}, 2000);
},
endCallBack(prize) {
alert(`恭喜你获得大奖: ${prize.fonts[0].text}`);
this.luckyNum--;
},
clickHander() {
this.startCallBack();
}
}
computed: {},
mounted() {},
methods: {}
};
</script>
<style lang="scss" scoped>
.home {
padding: 30px;
padding: 20px 25px;
height: 100%;
box-sizing: border-box;
.lucky-box {
}
.top-btn-and-box {
position: relative;
.top-btn-box {
position: absolute;
top: 0;
left: 50%;
width: 600px;
height: 300px;
margin: 0 auto;
.lucky-grid {
width: 100%;
height: 100%;
margin-left: -300px;
}
.top-ball-box {
padding-top: 64px;
}
}
</style>