Explorar o código

限时优惠储值

zhejiushizhuce %!s(int64=2) %!d(string=hai) anos
pai
achega
105119c1ab

+ 6 - 0
src/Global.js

@@ -165,4 +165,10 @@ global.showSaveAccount=(info)=>{
 global.hideSaveAccount=()=>{
     if (global.saveAccount)global.saveAccount.hide();
 }
+global.showBonusPack=()=>{
+    if (global.bonusPack)global.bonusPack.show();
+}
+global.hideBonusPack=()=>{
+    if (global.bonusPack)global.bonusPack.hide();
+}
 //wd pass

BIN=BIN
src/assets/bonusPack/bglight.png


BIN=BIN
src/assets/bonusPack/button.png


BIN=BIN
src/assets/bonusPack/clock.png


BIN=BIN
src/assets/bonusPack/en.png


BIN=BIN
src/assets/bonusPack/es.png


BIN=BIN
src/assets/bonusPack/pack.png


BIN=BIN
src/assets/bonusPack/percent.png


BIN=BIN
src/assets/bonusPack/pt.png


BIN=BIN
src/assets/bonusPack/pu.png


BIN=BIN
src/assets/welfare/bonuspack.png


+ 2 - 1
src/constants/app.js

@@ -19,7 +19,8 @@ const APP_SERVER={
 const APP_WELFARE={
     PROTECT:0,
     FIRST_PAY:1,
-    BIND:2
+    BIND:2,
+    BONUS_PACK:3
 }
 //id,phone,sms,mail,guest
 const APP_LOGIN_TYPE={

+ 4 - 0
src/features/api.js

@@ -62,6 +62,7 @@ import {toast} from "react-toastify";
 import {preDelMail} from "@features/mailSlice";
 import {getInAppBrowser} from "@utils/UAUtils";
 import {APP_LOGIN_TYPE} from "@constants/app";
+import {updateBonusPack} from "@features/paySlice";
 const i18n=global.i18n;
 export const buildReqReducer=(builder,thunk,callback,statusCB=null)=>{
     if (builder==null||thunk==null)return;
@@ -619,6 +620,9 @@ export const reqGameInfo=createAsyncThunk(
             url:APP_GAME_INFO
         }
         const response=await Http.get(params);
+        if (response&&response.code===200){
+            thunkAPI.dispatch(updateBonusPack(response.data));
+        }
         return response;
     }
 )

+ 60 - 7
src/features/paySlice.js

@@ -2,12 +2,19 @@ import {createSlice} from "@reduxjs/toolkit";
 import {REQ_STATUS} from "@api/config";
 import {
     buildReqReducer,
-    reqChangePayPass, reqCPFSave,
-    reqFirstPayConfig, reqFirstPayMulti, reqForgetPayPass,
-    reqGetAccountsPayInfo, reqGetSecond, reqMexWithdrawSetInfo,
-    reqPaymentOrder, reqPaymentOrderQR,
+    reqChangePayPass,
+    reqCPFSave,
+    reqFirstPayConfig,
+    reqFirstPayMulti,
+    reqForgetPayPass, reqGameInfo,
+    reqGetAccountsPayInfo,
+    reqGetSecond,
+    reqMexWithdrawSetInfo,
+    reqPaymentOrder,
+    reqPaymentOrderQR,
     reqPayOrderList,
-    reqRechargeConfig, reqRuWithdrawSetInfo,
+    reqRechargeConfig,
+    reqRuWithdrawSetInfo,
     reqWithdrawBaseInfo,
     reqWithdrawInfo,
     reqWithdrawPayout,
@@ -17,6 +24,7 @@ import {
 } from "@features/api";
 import {getHttpMsg} from "@utils/helpers";
 import {toast} from "react-toastify";
+
 const i18n=global.i18n;
 const objInfo={}
 const reducerRechargeConfig=(state,action,arg)=>{
@@ -322,6 +330,31 @@ const getSecondStatus=(state,status,arg)=>{
     state.status.GetSecond=status;
 }
 //FirstPayMulti
+//bonus pack
+const clearBonusPackCDTimer=()=>{
+    if (objInfo.bpCDTimer!=null){
+        clearInterval(objInfo.bpCDTimer);
+        objInfo.bpCDTimer=null;
+    }
+}
+const checkBonusPackLeftTime=(data)=>{
+    clearBonusPackCDTimer();
+    let timeleft=data.timeleft;
+    if (timeleft>0){
+        objInfo.bpCDTimer=setInterval(()=>{
+            timeleft--;
+            if (timeleft<=0){
+                global.dispatch(reqGameInfo());
+                clearBonusPackCDTimer();
+            }
+            else
+            {
+                global.dispatch(updateBonusPackCD(timeleft));
+            }
+        },1000);
+    }
+}
+//bonus pack
 export const Pay=createSlice({
     name: 'pay',
     initialState: {
@@ -356,7 +389,8 @@ export const Pay=createSlice({
         changePayPassType:0,
         showBonus:false,
         cpfFirst:false,
-        firstPayMulti:null
+        firstPayMulti:null,
+        bonusPack:null
     },
     reducers: {
         updatePayFinish:((state, action) => {
@@ -380,6 +414,21 @@ export const Pay=createSlice({
                 }
             }
         }),
+        updateBonusPack:((state, action) => {
+            let payload=action.payload;
+            if (payload!=null){
+                state.bonusPack=payload.bonus_pack;
+                checkBonusPackLeftTime(payload.bonus_pack);
+            }
+        }),
+        updateBonusPackCD:((state, action) => {
+            let payload=action.payload;
+            if (payload!=null){
+                if (state.bonusPack!=null){
+                    state.bonusPack.timeleft=payload;
+                }
+            }
+        })
     },
     extraReducers: (builder) => {
         buildReqReducer(builder,reqRechargeConfig,reducerRechargeConfig,rechargeConfigStatus);
@@ -403,7 +452,7 @@ export const Pay=createSlice({
         buildReqReducer(builder,reqGetSecond,reducerGetSecond,getSecondStatus);
     },
 })
-export const {updatePayFinish,setChangePayPassType,updateMultiCD} = Pay.actions;
+export const {updatePayFinish,setChangePayPassType,updateMultiCD,updateBonusPack,updateBonusPackCD} = Pay.actions;
 export const getConfig=(state)=>{
     return state.pay.config;
 }
@@ -520,6 +569,10 @@ export const getFirstPayMulti=(state)=>{
 export const getGetSecondStatus=(state)=>{
     return state.pay.status.GetSecond;
 }
+//bonus pack
+export const getBonusPack=(state)=>{
+    return state.pay.bonusPack;
+}
 export default Pay.reducer;
 
 export const reqPayConfig=(dispatch,userInfo)=>{

+ 2 - 0
src/layout/Layout.jsx

@@ -39,6 +39,7 @@ import LoadingCircular from "@components/Loading/LoadingCircular";
 import WFirstPay from "@widgets/WFirstPay";
 import WAreaSelect from "@widgets/WAreaSelect";
 import WSaveAccount from "@widgets/WSaveAccount";
+import WBonusPack from "@widgets/WBonusPack";
 const PageNotFound = lazy(() => import('@pages/PageNotFound'));
 
 const Layout=({...props})=>{
@@ -136,6 +137,7 @@ const Layout=({...props})=>{
                 <WProtect/>
                 <WFirstPay/>
                 <WSaveAccount/>
+                <WBonusPack/>
             </>
         )
     }

+ 4 - 0
src/locales/languages/en_US.json

@@ -777,6 +777,10 @@
     "tips": "Please save your account in time to avoid loss",
     "save_success": "Saved locally"
   },
+  "bonusPack": {
+    "only_need": "Only need",
+    "event_cd": "Event Countdown"
+  },
   "web": {
     "activity": {
       "redpack_not_available": "There is no RedPack",

+ 4 - 0
src/locales/languages/es_MX.json

@@ -764,6 +764,10 @@
     "tips": "Guarde su cuenta a tiempo para evitar pérdidas.",
     "save_success": "Guardado localmente"
   },
+  "bonusPack": {
+    "only_need": "Solo necesito",
+    "event_cd": "Cuenta regresiva del evento"
+  },
   "web": {
     "activity": {
       "redpack_not_available": "No hay RedPack",

+ 4 - 0
src/locales/languages/pt_BR.json

@@ -764,6 +764,10 @@
     "tips": "Por favor, salve sua conta a tempo para evitar perdas",
     "save_success": "Salvo localmente"
   },
+  "bonusPack": {
+    "only_need": "Só precisa",
+    "event_cd": "Contagem regressiva do evento"
+  },
   "web": {
     "activity": {
       "redpack_not_available": "Não há RedPack",

+ 4 - 0
src/locales/languages/ru_RU.json

@@ -764,6 +764,10 @@
     "tips": "Пожалуйста, сохраните данные аккаунта, чтобы не утратить доступ к нему.",
     "save_success": "Сохранено локально"
   },
+  "bonusPack": {
+    "only_need": "Нужно только",
+    "event_cd": "Обратный отсчет событий"
+  },
   "web": {
     "activity": {
       "redpack_not_available": "RedPack недоступен",

+ 4 - 0
src/locales/languages/zh_TW.json

@@ -764,6 +764,10 @@
     "tips": "請及時保存您的帳戶,以免造成損失",
     "save_success": "保存在本地"
   },
+  "bonusPack": {
+    "only_need": "只需要",
+    "event_cd": "活動倒數"
+  },
   "web": {
     "activity": {
       "redpack_not_available": "沒有紅包",

+ 212 - 0
src/widgets/WBonusPack/index.jsx

@@ -0,0 +1,212 @@
+import React, {useEffect, useState} from "react";
+import {APP_COUNTRY_CODE, APP_WELFARE} from "@constants/app";
+import {useThemeProvider} from "@contexts/themeContext";
+import styles from "./styles.module.scss";
+import Fade from "@mui/material/Fade";
+import Modal from "@mui/material/Modal";
+import Grow from "@mui/material/Grow";
+import {useDispatch, useSelector} from "react-redux";
+import {getBonusPack, getCPFFirst, getPaymentOrderStatus} from "@features/paySlice";
+import {REQ_STATUS} from "@api/config";
+import SmallLoading from "@components/SmallLoading";
+import {getUserInfo, isLogined} from "@features/mainSlice";
+import {ROUTE_PATH} from "@constants/routes";
+import {reqPaymentOrder} from "@features/api";
+import {useNavigate} from "react-router-dom";
+import RUPaytypeSelect from "@widgets/WDeposit/RU/RUPaytypeSelect";
+import BRCPFSave from "@widgets/WDeposit/BR/BRCPFSave/BRCPFSave";
+import {formatTime} from "@utils/helpers";
+const i18n=global.i18n;
+const WBonusPack = () => {
+    const [isShow, setIsShow] = useState(false);
+    const {setWelfTabState}=useThemeProvider();
+    const bonusPack=useSelector(getBonusPack);
+    const user=useSelector(getUserInfo);
+    const orderStatus=useSelector(getPaymentOrderStatus);
+    const isLogin=useSelector(isLogined);
+    const dispatch = useDispatch();
+    const navigate=useNavigate();
+    const cpfFirst=useSelector(getCPFFirst);
+    const areaItem=global.getLocalAreaItem();
+    const show=()=>{
+        setIsShow(true);
+        setWelfTabState(APP_WELFARE.BONUS_PACK);
+    }
+    const hide=()=>{
+        setIsShow(false);
+        setWelfTabState(-1);
+    }
+    const onGetPaymentCallback=()=>{
+        hide();
+        navigate(ROUTE_PATH.PAY_ORDER);
+    }
+    const onGetPaymentOder=(data)=>{
+        if (!isLogin){
+            hide();
+            navigate(ROUTE_PATH.SIGN_IN);
+            return;
+        }
+        if (orderStatus===REQ_STATUS.LOADING)return;
+        let reqOrder=()=>{
+            data.user=user;
+            data.callback=onGetPaymentCallback;
+            dispatch(reqPaymentOrder(data));
+        }
+        if (areaItem.code===APP_COUNTRY_CODE.RU){
+            if (global.ruPaytypeSelect!=null){
+                global.ruPaytypeSelect.show((eventType)=>{
+                    data.eventType=eventType;
+                    reqOrder();
+                });
+            }
+        }
+        else if (areaItem.code===APP_COUNTRY_CODE.BR){
+            if (cpfFirst){
+                if (global.brCPFSave!=null){
+                    global.brCPFSave.show(()=>{
+                        data.cpf_first=1;
+                        reqOrder();
+                    })
+                }
+            }
+            else
+            {
+                reqOrder();
+            }
+        }
+        else{
+            reqOrder();
+        }
+    }
+    useEffect(()=>{
+        const bonusPack={
+            show,
+            hide
+        };
+        global.bonusPack=bonusPack;
+        return ()=>{
+        }
+    },[])
+    const renderMain=()=>{
+        let payItem=bonusPack;
+        if (payItem==null)return (<></>);
+        let give=0;
+        let money=0;
+        let total=0;
+        let second_give=0;
+        let precent="";
+        if (payItem.gear){
+            give=Number(payItem.gear.give);
+            money=Number(payItem.gear.money);
+            second_give=Number(payItem.gear.second_give);
+            total=give+money;
+            precent='+'+Math.floor((give)*100/money)+'%';
+        }
+        return (
+            <div className={styles.f_main}>
+                <img className={styles.bglight} src={require('@assets/bonusPack/bglight.png')}/>
+                <div className={styles.pack_con}>
+                    <div className={styles.percent_con}>
+                        <div data-title={precent} className={styles.text}>{precent}</div>
+                    </div>
+                    <div className={styles.bonus_con}>
+                        <div data-title={global.DOLLAR+total} className={styles.p_text}>{global.DOLLAR+total}</div>
+                    </div>
+                </div>
+            </div>
+        )
+    }
+    const renderPayBtn=()=>{
+        let payItem = bonusPack;
+        if (payItem == null) return (<></>);
+        let money = 0;
+        let payType = 0;
+        let gift_id=0;
+        if (payItem.gear){
+            money = Number(payItem.gear.money);
+            payType=payItem.gear.id;
+            gift_id=payItem.gear.gift_id;
+        }
+        return (
+            <button className={styles.f_btnpay} onClick={() => {
+                onGetPaymentOder(
+                    {
+                        price:money,
+                        goodsName:"firstpay",
+                        payType:payType,
+                        GiftsID:gift_id
+                    }
+                )
+            }}>
+                {
+                    orderStatus===REQ_STATUS.LOADING?(<SmallLoading fill={"#fff"}/>):(
+                        <>
+                            <span data-title={i18n.t("bonusPack.only_need")}
+                                  className={styles.label}>{i18n.t("bonusPack.only_need")}</span>
+                            <span data-title={global.DOLLAR + money}
+                                  className={styles.pay_num}>{global.DOLLAR + money}</span>
+                        </>
+                    )
+                }
+            </button>
+        )
+    }
+    const renderLeftTime=()=>{
+        let payItem = bonusPack;
+        if (payItem == null) return (<></>);
+        let countdown=payItem.timeleft;
+        let d=Math.floor(countdown/86400);
+        let time=countdown-d*86400;
+        let stime=formatTime(time);
+        let sd=i18n.language==="ru"?'д':'d';
+        let dstr=d>0?d+sd:"";
+        return (
+            <div className={styles.f_leftcon}>
+                <div className={styles.f_cd_title}>
+                    <img className={styles.clock} src={require('assets/bonusPack/clock.png')}/>
+                    <span>{i18n.t("bonusPack.event_cd")}</span>
+                </div>
+                <span className={styles.f_cd}>{dstr+" "+stime}</span>
+            </div>
+        )
+    }
+    const renderPaytypeSelect=()=>{
+        if (areaItem.code===APP_COUNTRY_CODE.RU){
+            return (<RUPaytypeSelect/>)
+        }
+        else
+        {
+            return (<></>);
+        }
+    }
+    const renderCPFSave=()=>{
+        if (areaItem.code===APP_COUNTRY_CODE.BR){
+            return (<BRCPFSave/>)
+        }
+        else
+        {
+            return (<></>)
+        }
+    }
+    return (
+        <>
+            <Modal open={isShow} onClose={hide} closeAfterTransition>
+                <Fade in={isShow} timeout={500}>
+                    <div className={styles.container}>
+                        <Grow in={isShow} timeout={500}>
+                            <div className={styles.f_con}>
+                                <img className={styles.title} src={require(`@assets/bonusPack/${i18n.language}.png`)}/>
+                                {renderLeftTime()}
+                                {renderMain()}
+                                {renderPayBtn()}
+                            </div>
+                        </Grow>
+                    </div>
+                </Fade>
+            </Modal>
+            {renderPaytypeSelect()}
+            {renderCPFSave()}
+        </>
+    )
+}
+export default WBonusPack;

+ 197 - 0
src/widgets/WBonusPack/styles.module.scss

@@ -0,0 +1,197 @@
+$bg:"./../../assets/bonusPack/pack.png";
+$btnbg:"./../../assets/bonusPack/button.png";
+$pbg:"./../../assets/bonusPack/percent.png";
+.container{
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+  padding: 1rem;
+  pointer-events: none;
+  position: relative;
+}
+.f_con {
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  max-width: 25.875rem;
+  pointer-events: auto;
+  align-items: center;
+  position: relative;
+  gap: 0.7rem;
+  & .title{
+    max-width: 90%;
+    height: auto;
+  }
+  & .f_main {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    width: 80%;
+    aspect-ratio: 583/442;
+    height: auto;
+    position: relative;
+
+    & .bglight {
+      width: 127%;
+      position: absolute;
+      z-index: 1;
+      pointer-events: none;
+      animation: bg_light_ani 20s linear infinite;
+      transform: translateZ(0);
+    }
+
+    & .pack_con {
+      display: flex;
+      flex-direction: column;
+      position: absolute;
+      align-items: center;
+      justify-content: flex-end;
+      z-index: 2;
+      width: 100%;
+      aspect-ratio: 583/442;
+      background: url($bg) no-repeat;
+      background-size: 100% 100%;
+      & .p_text{
+        &::before{
+          content: attr(data-title);
+          position: absolute;
+          background-image: linear-gradient(to bottom,#fffd5a 0%,#fffd5a 30%,#fffdea 60%,#ffb643 70%);
+          background-clip: text;
+          -webkit-background-clip: text;
+          -webkit-text-fill-color: transparent;
+          -webkit-text-stroke: 0px #483be3;
+          font-weight: bold;
+          font-size: 1.7rem;
+          pointer-events: none;
+        }
+        font-weight: bold;
+        font-size: 1.7rem;
+        filter: drop-shadow(0 3px 1px #120519);
+      }
+      & .percent_con{
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: center;
+        position: absolute;
+        z-index: 2;
+        background: url($pbg);
+        background-size: 100% 100%;
+        width: 24%;
+        aspect-ratio: 137/136;
+        right: 16%;
+        bottom: 15%;
+        transform: rotate(-10deg);
+        & .text{
+          &::before{
+            content: attr(data-title);
+            position: absolute;
+            background-image: linear-gradient(to right,#ffd63c,#ffd63c, #fdfdd1);
+            background-clip: text;
+            -webkit-background-clip: text;
+            -webkit-text-fill-color: transparent;
+            -webkit-text-stroke: 0px #483be3;
+            font-weight: bold;
+            font-size: 1rem;
+            pointer-events: none;
+          }
+          font-weight: bold;
+          font-size: 1rem;
+          -webkit-text-stroke: 2px #483be3;
+          filter: drop-shadow(0 1px 1px #3615a0);
+        }
+      }
+      & .bonus_con {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: center;
+        width: 100%;
+        height: 21%;
+      }
+    }
+  }
+  & .f_btnpay{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: center;
+    margin-top: 0.8rem;
+    width: 48%;
+    aspect-ratio: 347/91;
+    background: url($btnbg);
+    background-size: 100% 100%;
+    font-weight: bold;
+    font-size: 1.1rem;
+    gap: 0.5rem;
+    & .label{
+      margin-top: -0.3rem;
+      color: #fff;
+      -webkit-text-stroke: 4px #1c4014;
+      &::before{
+        content: attr(data-title);
+        position: absolute;
+        background-image: linear-gradient(to bottom,#fff,#fff);
+        background-clip: text;
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+        -webkit-text-stroke: 0px #1c4014;
+        font-weight: bold;
+        font-size: 1.1rem;
+      }
+    }
+    & .pay_num{
+      margin-top: -0.3rem;
+      font-size: 1.2rem;
+      color: #f4eb00;
+      -webkit-text-stroke: 4px #830662;
+      &::before{
+        content: attr(data-title);
+        position: absolute;
+        background-image: linear-gradient(to bottom,#f4eb00,#f4eb00);
+        background-clip: text;
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+        -webkit-text-stroke: 0px #830662;
+        font-weight: bold;
+        font-size: 1.2rem;
+      }
+    }
+  }
+  & .f_leftcon{
+    margin-top: -0.6rem;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    color: #fff;
+    & .f_cd_title{
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      gap: 0.2rem;
+      font-weight: bold;
+      font-size: 1.2rem;
+      & .clock{
+        width: 1.2rem;
+        height: auto;
+      }
+    }
+    & .f_cd{
+      font-weight: bold;
+      font-size: 1.5rem;
+    }
+  }
+}
+@keyframes bg_light_ani {
+  0%{
+    transform: rotate(0deg);
+  }
+  100%{
+    transform: rotate(1turn);
+  }
+}

+ 49 - 2
src/widgets/WWelfarebar/index.jsx

@@ -1,10 +1,10 @@
 import styles from './styles.module.scss';
 import React, {useEffect, useRef, useState} from "react";
-import {reqFirstPayConfig, reqFirstPayMulti, reqProtectCheck, reqRechargeConfig} from "@features/api";
+import {reqFirstPayConfig, reqFirstPayMulti, reqGameInfo, reqProtectCheck, reqRechargeConfig} from "@features/api";
 import {useDispatch, useSelector} from "react-redux";
 import {getFirstBonus, getOpenRelief, getPopBindPhone, getUpgradeBonus, getUserInfo} from "@features/mainSlice";
 import {APP_WELFARE} from "@constants/app";
-import {getCurrPayOrder, getFirstPayMulti, getOFirstPay} from "@features/paySlice";
+import {getBonusPack, getCurrPayOrder, getFirstPayMulti, getOFirstPay} from "@features/paySlice";
 import {getProtectInfo} from "@features/protectSlice";
 import {formatCash, formatTime} from "@utils/helpers";
 import {useThemeProvider} from "@contexts/themeContext";
@@ -66,6 +66,9 @@ const WWelfarebar = () => {
     const upgradBonus=useSelector(getUpgradeBonus);
     const regCoins=formatCash(upgradBonus,0);
     const firstPayMulti=useSelector(getFirstPayMulti);
+    //bonus pack
+    const [openBonusPack, setOpenBonusPack] = useState(0);
+    const bonusPack=useSelector(getBonusPack);
     const getWelfTabState=(key)=>{
         if (welfTabState===key)return true;
         return false;
@@ -85,6 +88,9 @@ const WWelfarebar = () => {
             case APP_WELFARE.BIND:
                 setOpenBind(state);
                 break;
+            case APP_WELFARE.BONUS_PACK:
+                setOpenBonusPack(state);
+                break;
         }
     }
     const checkProtect=()=>{
@@ -161,10 +167,31 @@ const WWelfarebar = () => {
         cdStr=cdStr.substring(0,cdStr.length-3);
         return cdStr;
     }
+    //bonus pack
+    const checkBonusPack=()=>{
+        let state=0;
+        if (bonusPack&&bonusPack.timeleft>0){
+            state=1;
+        }
+        changeNewState(APP_WELFARE.BONUS_PACK,state);
+    }
+    const getBonusPackCD=()=>{
+        let timeleft=-1;
+        if (bonusPack!=null){
+            timeleft=Number(bonusPack.timeleft);
+        }
+        return timeleft;
+    }
+    const formatBonusPackCD=(bonusCD)=>{
+        let cdStr=formatTime(bonusCD);
+        cdStr=cdStr.substring(0,cdStr.length-3);
+        return cdStr;
+    }
     useEffect(()=>{
         let UserID=user.UserID;
         if (UserID>0){
             dispatch(reqProtectCheck());
+            dispatch(reqGameInfo());
         }
         dispatch(reqRechargeConfig());
         // dispatch(reqFirstPayConfig());
@@ -188,6 +215,10 @@ const WWelfarebar = () => {
     useEffect(()=>{
         checkFirstPayStatus();
     },[orderInfo])
+    //bonus pack
+    useEffect(()=>{
+        checkBonusPack();
+    },[bonusPack])
     const renderBar=()=>{
         let extra='';
         if (!isMobile()){
@@ -204,6 +235,7 @@ const WWelfarebar = () => {
         const stars=Array.from({ length: 5 }, (_, index) => index);
         let symbol=getSymbol();
         let firstCD=getFirstCD();
+        let bonusCD=getBonusPackCD();
         return (
             <div className={`${styles.container} ${extra}`}>
                 <div className={`${styles.content} ${isClose?styles.content_close:''}`}>
@@ -264,6 +296,21 @@ const WWelfarebar = () => {
                                  src={require("@assets/welfare/bind_txt_" + i18n.language + ".png")}/>
                         </div>
                     </WelfareBtn>
+                    <WelfareBtn key={"bonus_pack"} open={openBonusPack}
+                                pressDown={getWelfTabState(APP_WELFARE.BONUS_PACK)}
+                                onClick={() => {
+                                    global.showBonusPack();
+                                }}>
+                        <div className={styles.wlf_bpack}>
+                            <div className={styles.wlf_bpack_mask} style={{
+                                webkitMask: `url(${require("@assets/welfare/bonuspack.png")}) 0 0/100%`
+                            }}>
+                                <img className={styles.f_img} src={require("@assets/welfare/bonuspack.png")}/>
+                            </div>
+                            <span data-title={formatBonusPackCD(bonusCD)}
+                                  className={styles.f_cdtxt}>{formatBonusPackCD(bonusCD)}</span>
+                        </div>
+                    </WelfareBtn>
                 </div>
             </div>
         )

+ 51 - 0
src/widgets/WWelfarebar/styles.module.scss

@@ -265,4 +265,55 @@ $star:"./../../assets/welfare/star.png";
     transform: scale(1);
     opacity: 0;
   }
+}
+
+.wlf_bpack{
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 3.8rem;
+  aspect-ratio: 104/115;
+  margin-left: -0.5rem;
+  position: relative;
+  &_mask{
+    width: 3.8rem;
+    aspect-ratio: 104/89;
+    flex-shrink: 0;
+    position: absolute;
+    overflow: hidden;
+    top: 0;
+    &:after{
+      content: '';
+      position: absolute;
+      inset: -20%;
+      background: linear-gradient(-45deg, rgba(255,255,255,0) 45%, rgb(255,255,255,1), rgba(255,255,255,0) 60%);
+      animation: shark-wrap 3s infinite;
+      transform: translateX(-100%);
+      mix-blend-mode: overlay;
+    }
+  }
+  & .f_img{
+    width: 3.8rem;
+    height: auto;
+  }
+  & .f_cdtxt{
+    position: absolute;
+    z-index: 2;
+    top: 2.8rem;
+    color: #fff;
+    -webkit-text-stroke: 4px #2a3f5b;
+    font-weight: 600;
+    font-size: 0.9rem;
+    &::before{
+      content: attr(data-title);
+      position: absolute;
+      background-image: linear-gradient(to bottom,#fff,#24e2fc);
+      background-clip: text;
+      -webkit-background-clip: text;
+      -webkit-text-fill-color: transparent;
+      -webkit-text-stroke: 0px #2a3f5b;
+      font-weight: 600;
+      font-size: 0.9rem;
+    }
+  }
 }