"use client"; import { receiveRedPacketApi } from "@/api/promo"; import { useRouter } from "@/i18n/routing"; import { getToken } from "@/utils/Cookies"; import { Mask } from "antd-mobile"; import clsx from "clsx"; import { useTranslations } from "next-intl"; import { FC, forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react"; import styles from "./style.module.scss"; const randomX = (len: number) => { return Math.floor(Math.random() * len); }; const mockData = Array(500) .fill(0) .map((item) => { return { phone: `55****${(randomX(99) + "").padEnd(2, "0")}`, num: `${(Math.random() * 20).toFixed(2)}`, time: "11:00", }; }); function getRandom(min: number, max: number) { const floatRandom = Math.random(); const difference = max - min; // 介于 0 和差值之间的随机数 const random = Math.round(difference * floatRandom); return random + min; } /** * @description 描述 */ type DescProps = { onClose: () => void; }; const HbyInfoDetail = (props: any) => { const { iconImg, onCloseHby } = props; const router = useRouter(); const token = getToken(); const handler = () => { if (!token) { router.push("/login"); } onCloseHby(); }; const str = "12:00".split(""); return (
{/* 下一场开始时间*/}
{str[0]}
{str[1]}
{str[2]}
{str[3]}
{str[4]}
); }; const HbyInfo = (props: any) => { const { iconImg, onCloseHby, onReciveRed } = props; if (!iconImg) return; return (
{/* {"close"} */}
{"icon"} {/*
Chuva de dinheiro
AGARRAR
*/}
//
// {"close"} //
Chuva de dinheiro
//
1.96
//
Valor máximo de queda em dinheiro:Cada sessäo de chuva de dinheiro é
//
); }; const HbyInfo2 = (props: any) => { const { iconImg, onCloseHby, redAmount } = props; const hbyInfoClass = clsx( `${styles.redopen} absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-no-repeat bg-cover` ); const t = useTranslations("packetsPopup"); return (
{"close"}
{t("title")}
{redAmount}
{redAmount > 0 ? t("receiveSuccess") : t("receiveWarring")}
); }; /** * @description 动画背景 - 下雨动效 */ type Props = { onAfterHandler?: () => void; }; export type RedPacketModalProps = { onClose: () => void; onOpen: (source: any[], index?: number) => void; }; /** * @description 红包的三种状态 * is_start 可领取 展示红包领取组件 * is_receive 已领取 展示领取详情组件 * is_end 可展示 展示说明页 */ enum Status { is_start, is_receive, is_end, } interface Snowflake { x: number; // 水平位置 y: number; // 垂直位置 scale: number; // 缩放比例 speedX: number; // 水平移动速度 speedY: number; // 垂直下落速度 rotate: number; // 当前旋转角度 rotateSpeed: number; // 旋转速度 image: HTMLImageElement; // 图片路径 } interface SnowfallProps { images: string[]; // 图片数组 snowflakeCount?: number; // 雪花数量 onClose: () => void; } const Snowfall: FC = ({ images, snowflakeCount = 80, onClose = () => {} }) => { // canvas const canvasRef = useRef(null); // 预加载图片 const imageElements = useRef([]); // 父元素 const containerRef = useRef(null); const createSnowflakes = (count: number, width: number, height: number): Snowflake[] => { return Array.from({ length: count }, () => ({ x: Math.random() * width, y: Math.random() * height - height, scale: Math.random() * (1.2 - 0.5) + 0.5, speedX: Math.random() * 1.5 - 0.75, speedY: Math.random() * 5 + 1, rotate: Math.random() * 180, rotateSpeed: Math.random() * 2 - 1, image: imageElements.current[Math.floor(Math.random() * imageElements.current.length)], })); }; useEffect(() => { // 预加载图片 imageElements.current = images.map((src) => { const img = new Image(); img.src = src; return img; }); const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const parentWidth = containerRef.current?.clientWidth || 0; const parentHeight = (canvas.height = containerRef.current?.clientHeight || 0); const width = (canvas.width = parentWidth); const height = (canvas.height = parentHeight); let snowflakes: Snowflake[] = createSnowflakes(snowflakeCount, width, height); const imgHeight = 80; const imgWidth = 80; const animate = () => { ctx.clearRect(0, 0, width, height); snowflakes.forEach((flake) => { flake.y += flake.speedY; flake.x += flake.speedX; flake.rotate += flake.rotateSpeed; if (flake.y > height) { flake.y = -44; flake.x = Math.random() * width; flake.rotate = Math.random() * 360; } if (flake.x < 0 || flake.x > width) { flake.speedX *= -1; } ctx.save(); ctx.globalAlpha = 1; ctx.translate( flake.x + (imgHeight * flake.scale) / 2, flake.y + (imgWidth * flake.scale) / 2 ); ctx.rotate((flake.rotate * Math.PI) / 180); ctx.drawImage( flake.image, (-imgHeight * flake.scale) / 2, (-imgWidth * flake.scale) / 2, imgHeight * flake.scale, imgWidth * flake.scale ); ctx.restore(); }); requestAnimationFrame(animate); }; animate(); const handleResize = () => { canvas.width = parentWidth; canvas.height = parentHeight; snowflakes = createSnowflakes(snowflakeCount, canvas.width, canvas.height); }; window.addEventListener("resize", handleResize); return () => { window.removeEventListener("resize", handleResize); }; }, []); return (
;
); }; const RedPacketModal = forwardRef(function RedPacketModal(props, ref) { const { onAfterHandler } = props; const [visible, setVisible] = useState(false); const [iconLists, setIconLists] = useState([]); // 初始状态为is_end, 展示活动详情页 const [status, setStatus] = useState(Status.is_end); const packetCurrent = useRef({}); const packets = useRef([]); const [redAmount, setRedAmount] = useState(1); const activeIndex = useRef(0); const token = getToken(); const element = useRef(null); useImperativeHandle(ref, () => { return { onClose: () => setVisible(false), onOpen: (source, index?: number) => { packets.current = source; if (index !== null && index !== undefined) { activeIndex.current = index; } getRedPacketInfo().then((res) => { setVisible(true); }); }, }; }); const getRedPacketInfo = async () => { try { let actList = packets.current; // 是否有已开始但是没领过的红包 let packetsFilter = actList .filter((aItem: any) => { return aItem.can_receive && aItem.is_start && !aItem.is_receive; }) .sort((pre: any, next: any) => pre.end_time - next.end_time); // 有可领取红包 if (packetsFilter.length > 0) { let current = packetsFilter[activeIndex.current]; let iconList = JSON.parse(current.icon); // 红包 packetCurrent.current = current; // 有可领取红包 setIconLists(iconList); if (!token) { setStatus(Status.is_end); } else { setStatus(Status.is_start); } } else { // 无可领取红包 // 展示最近可领红包详情 let packets = actList.sort((pre: any, next: any) => pre.end_time - next.end_time); packetCurrent.current = packets[0]; setIconLists(JSON.parse(packets[0].icon)); // 无可领取红包展示详情 setStatus(Status.is_end); } } catch (error) { console.log("redPacketInfo===>error:", error); } }; const onReciveRed = async () => { try { let paramsData = { id: packetCurrent.current?.id, index: packetCurrent.current?.index, }; let receiveRedPacketInfo = await receiveRedPacketApi(paramsData); let redNum = receiveRedPacketInfo.data; if (onAfterHandler) { onAfterHandler(); } setStatus(Status.is_receive); setRedAmount(redNum?.amount); } catch (error) { console.log("redPacketInfo===>error:", error); } }; useEffect(() => { element.current = document.getElementById("app"); }, []); const ImagesData = Array.from({ length: 6 }).map((_, index) => { return `/9f/money${index + 1}.png`; }); return ( setVisible(false)} /> {status === Status.is_start ? ( setVisible(false)} onReciveRed={onReciveRed} iconImg={iconLists[1]} /> ) : status === Status.is_receive ? ( setVisible(false)} redAmount={redAmount} iconImg={iconLists[2]} /> ) : ( setVisible(false)} iconImg={iconLists[0]} /> )} ); }); export default memo(RedPacketModal);