Files
sway-ball/src/pages/index/index.vue
Huakk 8b4484d8ab
All checks were successful
continuous-integration/drone/push Build is passing
update
2024-07-15 19:48:40 +08:00

879 lines
21 KiB
Vue

<template>
<view class="relative">
<!-- 直播区域 -->
<view id="Player" class="w-full h-[420px]"></view>
<!-- <view id="J_prismPlayer"></view> -->
<!-- <view class="player" id="mse"></view> -->
<!-- 头部 -->
<view
class="z-50 bg-[#EB1313] w-full h-[110px] p-[18px] text-[30px] flex text-white justify-between items-center"
>
<view>积分: {{ user.integral }}</view>
<view class="flex items-center justify-center">
<view class="pr-[10px] text-[25px]">
<view></view>
<view></view>
</view>
<nut-popover
v-model:visible="showSelector"
:list="selector"
location="bottom"
@choose="onChange"
>
<template #reference>
<!-- @click.stop="showSelector = !showSelector" -->
<view
@click.stop="showSelector = !showSelector"
class="w-[200px] h-[70px] pl-2 pr-2 border-2 rounded-md border-white flex items-center justify-center"
>
<view>{{ formData.selectorChecked }}</view>
<down theme="filled" size="25" fill="#fff" />
</view>
</template>
</nut-popover>
</view>
<!-- <nut-popover
v-model:visible="showOpt"
:list="selectorOpt"
location="bottom"
@choose="onChangeOpt"
>
<template #reference>
<view
class="flex w-[100px] justify-center"
@ckick.stop="showOpt = !showOpt"
>
<view class="dot mr-1"></view>
<view class="dot mr-1"></view>
<view class="dot"></view>
</view>
</template>
</nut-popover> -->
<navigator
:url="`/pages/bet_record/index?uid=${uid}`"
open-type="navigate"
hover-class="none"
class="flex items-center"
>
<view>投注记录</view>
<right theme="filled" size="25" fill="#ffffff" />
</navigator>
</view>
<!-- 开奖 -->
<view class="flex justify-between items-center p-[20px]">
<view class="text-center relative aft">
<view class="text-[28px] text-[#333333]">{{ pStr }}期截止时间</view>
<view class="text-[red] text-[40px]">{{ tStr }}</view>
</view>
<view class="flex flex-col items-center popover">
<nut-popover
v-model:visible="showTable"
location="bottom"
@open="openTable"
>
<template #reference>
<view
class="flex items-center"
@click.stop="showTable = !showTable"
>
<text class="text-[#333333] text-[28px]">近期开奖</text>
<down class="mr-1" theme="filled" size="25" fill="#333333" />
</view>
</template>
<template #content>
<nut-table
style="width: 900px"
:columns="columns"
:data="data"
striped
:bordered="true"
></nut-table>
</template>
</nut-popover>
<view class="flex">
<view
class="m-[5px] rounded-full w-[44px] h-[44px] text-white text-[28px] text-center leading-[44px]"
v-for="(item, index) in numList"
:key="index"
>
<view v-if="!item.num" class="m-[5px]">
<plus-cross theme="filled" size="20" fill="#333333" />
</view>
<view
class="rounded-full"
:style="{
backgroundColor: item.color,
}"
>{{ item.num }}</view
>
</view>
</view>
</view>
</view>
<!-- 投注 -->
<!-- <scroll-view scroll-y class="h-[800px]"> -->
<template v-if="formData.betType !== 2">
<view class="grid gap-1 grid-cols-4 place-items-center p-[20px]">
<view
v-for="(item, index) in betList"
:key="index"
class="shadow-md border border-[#E6E6E6] rounded-[10px] w-[150px] mb-[20px] h-[150px] max-[150px] bg-[red] text-center flex justify-center items-center"
:class="
formData.betIndexs.includes(item.value)
? 'bg-[#EB1313]'
: 'bg-white'
"
@click="betSelect(item)"
>
<view
:class="formData.betIndexs.includes(item.value) ? 'text-white' : ''"
><view>{{ item.label }}</view>
<view
:class="[
formData.betIndexs.includes(item.value)
? 'text-white'
: 'text-[#EB1313]',
'text-[30px]',
]"
>{{ item.odds }}</view
>
<!-- <viwe v-if="item.betVal > 0">{{ item.betVal }}</viwe> -->
</view>
</view>
</view>
</template>
<template v-else>
<view class="grid gap-5 grid-cols-6 place-items-center p-[20px]">
<view
v-for="(item, index) in betList"
:key="index"
class="shadow-md border border-[#E6E6E6] rounded-full w-[80px] mb-[20px] h-[80px] max-[200px]: bg-[red] text-center leading-[80px]"
:class="
formData.betIndexs.includes(item.value)
? 'bg-[#EB1313]'
: 'bg-white'
"
@click="betSelect(item)"
>
<view
:style="{
color: formData.betIndexs.includes(item.value)
? 'white'
: getTextColor(item.label),
}"
><view>{{ item.label }}</view>
<view class="text-[28px] text-[#EB1313] leading-[50px]">{{
item.odds
}}</view>
<!-- <view>{{ item.betVal }}</view> -->
</view>
</view>
</view>
</template>
<!-- </scroll-view> -->
<view class="h-[350px]"></view>
<!-- 操作栏 -->
<view class="fixed bottom-0 w-full">
<!-- 投注信息 -->
<view
v-if="formData.betIndexs.length > 0"
class="bg-[#F5F5F5] w-full text-[28px] p-[26px] flex justify-between items-center"
>
<view
>
<text class="text-[#EB1313]">{{ formData.betIndexs.length }}</text>
<text class="text-[#EB1313]">{{
formData.betIndexs.length * formData.value
}}</text>
豆子</view
>
<!-- <view> 单注最多可赢 <text class="text-[#EB1313]">100</text> 积分 </view> -->
</view>
<view
class="bg-white p-[30px] w-full text-[28px] flex justify-between items-center"
>
<view
@click="clearbet"
class="bg-[#FFE8E8] rounded-[10px] border border-[#FF0204] w-[100px] h-[60px] text-[#FF0204] text-center leading-[60px]"
>清空</view
>
<view>
<view
>可用豆子:
<text class="text-[#EB1313]">{{ user.pulse }}</text> 豆子</view
>
<!-- @input="betIput" -->
<view class="flex"
>单注:
<input
v-model="formData.value"
type="number"
class="ml-1 mr-1 border border-[#D9D9D9] rounded-[10px] w-[140px] pl-[10px] pr-[10px] text-[#FF0204] text-center"
placeholder=""
/>
豆子</view
>
</view>
</view>
<!-- 确认投注 -->
<view
class="text-[36px] h-[100px] bg-[red] text-white text-center leading-[100px]"
shape="square"
block
type="primary"
@click="submit"
>一键投注</view
>
<!-- <button @click="lottieFn(2, 1000)">text</button> -->
</view>
<view id="lottie" v-show="isLottie"></view>
</view>
</template>
<script setup>
import { ref, onMounted, nextTick, h, computed, watch } from "vue";
import Taro from "@tarojs/taro";
import { Down, PlusCross, Right } from "@icon-park/vue-next";
import TCPlayer from "tcplayer.js";
import Lottie from "lottie-web";
import {
GetBetOptList,
GetUserInfo,
GetLotteryRecord,
GetPeriod,
GetBetRecord,
GetIsWin,
} from "../../api";
import "tcplayer.js/dist/tcplayer.min.css";
// import Srs from "../../utils/srs.sdk";
import Player from "xgplayer";
import FlvPlugin from "xgplayer-flv";
// import webRtcPlugin from "../../utils/webRtcPlugin";
import "xgplayer/dist/index.min.css";
import "./index.scss";
import wzj from "../../static/wzj.json";
import zj from "../../static/zj.json";
onMounted(() => {});
const player = ref(null);
const showTop = ref(false);
const aliPlayer = ref(null);
// 动画相关
const isLottie = ref(false); // 是否显示动画
Taro.useLoad((options) => {
uid.value = options.uid;
initWs(options);
loadTplayer();
});
const ws = ref(null);
const tStr = ref("···");
const pStr = ref("");
const initWs = (options) => {
ws.value = new WebSocket(
`wss://${process.env.TARO_APP_WS}/dice/home?uid=${options.uid}&game_id=4`
);
ws.value.onopen = () => {
setInterval(() => {
ws.value.send("ping");
}, 10000);
};
ws.value.onmessage = async ({ data }) => {
const res = JSON.parse(data);
switch (res.code) {
case 5:
case 400:
case 302:
case 301:
case 401:
case 400:
case 402:
Taro.showToast({
title: res.msg,
icon: "none",
});
break;
case 200:
if (Number(res.data) === 0 || Number(res.data) === 1) {
tStr.value = "开奖中";
return;
}
tStr.value = `${res.data}`;
break;
case 201:
await getWin();
break;
}
};
ws.value.onerror = () => {
initWs();
};
};
Taro.useDidShow(() => {
// loadAliplayer();
// initPlayer();
getUserInfo();
getBetList();
getRecord();
getNum();
});
const uid = ref("");
const user = ref({});
const getRecord = async () => {
const res = await GetLotteryRecord(uid.value);
data.value = res.data.map((item) => ({
qs: `${item.Periods}`,
hm: [
{
num: item.A,
color: getTextColor(item.A),
},
{ num: item.B, color: getTextColor(item.B) },
{ num: item.C, color: getTextColor(item.C) },
{ num: item.D, color: getTextColor(item.D) },
{ num: item.E, color: getTextColor(item.E) },
{ num: item.F, color: getTextColor(item.F) },
{},
{ num: item.G, color: getTextColor(item.G) },
],
tt: item.Name,
t: item.DrawTime,
}));
numList.value = data.value[0].hm;
};
const getWin = async () => {
await getNum();
await getRecord();
const res = await GetIsWin(uid.value);
if (res.number > 0) {
console.log(res.number);
lottieFn(1, res.number);
}
};
const getNum = async () => {
const res = await GetPeriod();
pStr.value = res.periods;
};
const getTextColor = (text) => {
const redArr = [
"1",
"2",
"7",
"8",
"12",
"13",
"18",
"19",
"23",
"24",
"29",
"30",
"34",
"35",
"40",
"45",
"46",
];
const blueArr = [
"3",
"4",
"9",
"10",
"14",
"15",
"20",
"25",
"26",
"31",
"36",
"37",
"41",
"42",
"47",
"48",
];
const greenArr = [
"5",
"6",
"11",
"16",
"17",
"21",
"22",
"27",
"28",
"32",
"33",
"38",
"39",
"43",
"44",
"49",
];
if (redArr.includes(text)) return "#FF0204";
if (blueArr.includes(text)) return "#0500FA";
if (greenArr.includes(text)) return "#088207";
};
const getUserInfo = async () => {
const res = await GetUserInfo(uid.value);
user.value = res.data;
};
const loadAliplayer = () => {
new Aliplayer(
{
id: "J_prismPlayer",
height: "10rem",
source: "https://srs.huakk.top/live/livestream.flv",
autoplay: true,
isLive: true,
rePlay: true,
playsinline: true,
isVBR: true,
preload: true,
language: "zh-cn",
controlBarVisibility: "always",
useH5Prism: true,
skinLayout: [
{
name: "errorDisplay",
align: "tlabs",
x: 0,
y: 0,
},
{
name: "controlBar",
align: "blabs",
x: 0,
y: 0,
children: [
{
name: "liveDisplay",
align: "tlabs",
x: 15,
y: 6,
},
],
},
],
},
function (player) {
player.mute();
}
);
};
const loadTplayer = () => {
const el = document.getElementById("Player");
const videoEl = document.createElement("video");
videoEl.setAttribute("preload", "auto");
videoEl.setAttribute("style", "object-fit: cover;");
videoEl.setAttribute("muted", "");
videoEl.setAttribute("autoplay", "");
videoEl.setAttribute("id", "player-container-id");
videoEl.setAttribute("class", "w-full h-full");
videoEl.setAttribute("playsinline", "");
videoEl.setAttribute("webkit-playsinline", "");
videoEl.setAttribute("x5-playsinline", "");
el.appendChild(videoEl);
player.value = TCPlayer("player-container-id", {
autoplay: true,
muted: true,
preload: "auto",
controlBar: {
playToggle: true,
progressControl: false,
volumePanel: false,
currentTimeDisplay: false,
durationDisplay: false,
timeDivider: false,
playbackRateMenuButton: false,
fullscreenToggle: false,
QualitySwitcherMenuButton: false,
},
sources: [
// {
// src: "rtmp://jdt-live.wanzhuanyongcheng.cn/live/jdt",
// },
// {
// src: "http://jdt-live.wanzhuanyongcheng.cn/live/jdt.flv",
// },
// {
// src: "http://jdt-live.wanzhuanyongcheng.cn/live/jdt.m3u8",
// },
{
src: "webrtc://jdt-live.wanzhuanyongcheng.cn/live/jdt",
},
],
licenseUrl:
"https://license.vod2.myqcloud.com/license/v2/1327927250_1/v_cube.license", // license 地址,参考准备工作部分,在视立方控制台申请 license 后可获得 licenseUrl
});
player.value.muted(true);
};
const initPlayer = () => {
let player = new Player({
id: "mse",
url: FlvPlugin.isSupported()
? "https://srs.huakk.top/live/livestream.flv"
: "https://srs.huakk.top/live/livestream.m3u8",
playsinline: true,
controls: {
autoHide: false,
mode: "flex",
},
plugins: [FlvPlugin],
ignores: ["start", "volume", "playbackrate", "fullscreen", "play"],
autoplay: true,
autoplayMuted: true,
fluid: true,
isLive: true,
loop: true,
height: "300",
videoFillMode: "fillWidth",
});
// player.on("error", (error) => {
// alert(JSON.stringify(error));
// });
};
const showSelector = ref(false);
const selector = ref([
{
name: "头尾数",
value: 1,
},
{ name: "特码", value: 2 },
{ name: "单双", value: 3 },
]);
const onChange = async ({ name, value }) => {
formData.value.selectorChecked = name;
formData.value.betType = value;
showSelector.value = !showSelector.value;
betList.value = [];
formData.value.betIndexs = [];
await getBetList();
};
// const showOpt = ref(false);
// const selectorOpt = ref([
// {
// name: "开奖记录",
// value: "/pages/lottery_record/index",
// },
// {
// name: "投注记录",
// value: "/pages/bet_record/index",
// },
// {
// name: "玩法说明",
// value: "/pages/about/index",
// },
// ]);
// const onChangeOpt = ({ value }) => {
// if (!value)
// return Taro.showToast({
// title: "开发中",
// icon: "none",
// });
// Taro.navigateTo({
// url: `${value}?uid=${uid.value}`,
// });
// };
const showTable = ref(false);
const columns = ref([
{
title: "期数",
key: "qs",
align: "center",
stylehead: "color: #959BB1",
stylecolumn: "color: #959BB1",
},
{
title: "开奖号码",
key: "hm",
align: "center",
stylecolumn: "width: 300px; padding: 0px",
render: ({ hm }) => {
let el = [];
el = hm.map((item) => {
return h(
"view",
{
style: {
backgroundColor: item.color,
},
class: `m-[5px] rounded-full w-[44px] h-[44px] text-white text-[28px] text-center leading-[44px]`,
},
{
default: () => {
let el = [];
if (!item.num) {
el.push(
h(
"view",
{
class: "m-[5px]",
},
{
default: () => {
let el = [];
el.push(
h(PlusCross, {
theme: "filled",
size: "20",
fill: "#333333",
})
);
return el;
},
}
)
);
}
el.push(
h(
"view",
{
class: `rounded-full`,
},
{
default: () => `${item.num}`,
}
)
);
return el;
},
}
);
});
return h(
"view",
{
class: "flex justify-center",
},
{
default: () => el,
}
);
},
},
{
title: "特头-特尾-特码-单双",
key: "tt",
align: "center",
stylehead: "color: #959BB1",
stylecolumn: "color: #959BB1",
},
{
title: "开奖时间",
key: "t",
align: "center",
stylehead: "color: #959BB1",
stylecolumn: "color: #959BB1",
},
]);
const data = ref([]);
const openTable = () => {};
const numList = ref([]);
const formData = ref({
selectorChecked: "头尾数",
betType: 1,
betIndexs: [],
value: "",
total: 0,
});
const getTotalNum = computed(() => {
let num = 0;
betList.value.forEach((item) => {
formData.value.betIndexs.forEach((i) => {
if (i === item.value) {
num += item.betVal;
}
});
});
return num;
});
const betList = ref([]);
const betSelect = (item) => {
if (formData.value.betIndexs.includes(item.value)) {
betList.value.forEach((itm) => {
if (itm.value === item.value) {
itm.betVal = 0;
}
});
formData.value.betIndexs = formData.value.betIndexs.filter(
(i) => i !== item.value
);
} else {
formData.value.betIndexs.push(item.value);
}
// formData.value.value = "";
};
const getBetList = async () => {
const res = await GetBetOptList(formData.value.betType.toString());
betList.value = res.data.map((item) => {
return {
label: item.name,
value: item.ID,
odds: item.odds,
betVal: 0,
};
});
};
const betIput = ({ detail }) => {
formData.value.value = detail.value;
betList.value.forEach((item) => {
if (
formData.value.betIndexs[formData.value.betIndexs.length - 1] ===
item.value
) {
if (Number(detail.value) % 100 === 0) {
item.betVal = Number(detail.value);
}
}
});
};
const clearbet = () => {
formData.value.betIndexs = [];
betList.value.forEach((item) => {
item.betVal = 0;
});
formData.value.value = "";
};
const submit = async () => {
if (formData.value.betIndexs.length === 0)
return Taro.showToast({
title: "请选择投注项",
icon: "none",
});
if (Number(formData.value.value) % 100 !== 0) {
Taro.showToast({
title: "请输入100的倍数",
icon: "none",
});
return;
}
const arr = [];
betList.value.forEach((item) => {
formData.value.betIndexs.forEach((i) => {
if (i === item.value) {
arr.push({
sid: item.value,
number: Number(formData.value.value),
name: item.label,
});
}
});
});
ws.value.send(
JSON.stringify({
type: 1,
data: arr,
})
);
await getUserInfo();
isBet.value = true;
clearbet();
};
const isBet = ref(false);
const getBetJl = async () => {
const res = await GetBetRecord(uid.value);
const data = res.data.data[0];
const t = dayjs().format("YYYY-MM-DD");
// 是否为今天
if (data.DrawTime === t) {
// 是否下注
if (isBet.value) {
// 是否中奖
if (data.DrawNum > 0) {
lottieFn(1, data.DrawNum);
} else {
lottieFn(2);
}
isBet.value = false;
}
}
};
const lottieFn = (type, num = 0) => {
isLottie.value = true;
const lottieEle = document.getElementById("lottie");
const ctx = Lottie.loadAnimation({
container: lottieEle,
renderer: "svg",
loop: false,
autoplay: true,
animationData: type === 1 ? zj : wzj,
});
if (type === 1) {
const text = document.createElement("view");
text.className = "lottie-text";
// text.innerHTML = `单`
const view = document.createElement("view");
view.className = "lottie-bg";
view.innerHTML = `<view class="lottie-num">恭喜你中了${num}积分</view>`;
const els = [view, text];
for (const i in els) {
lottieEle.appendChild(els[i]);
}
}
ctx.addEventListener("complete", () => {
isLottie.value = false;
ctx.destroy();
});
};
</script>
<style lang="scss"></style>