瀏覽代碼

no message

zhejiushizhuce 2 年之前
父節點
當前提交
cc82d76d52
共有 49 個文件被更改,包括 1670 次插入 和 78 次删除
  1. 1 0
      package.json
  2. 9 2
      src/App.js
  3. 2 0
      src/Global.js
  4. 19 11
      src/api/config.js
  5. 6 4
      src/api/request.js
  6. 3 1
      src/app/store.js
  7. 二進制
      src/assets/pay/fpayimg.png
  8. 二進制
      src/assets/pay/img_sc_66.png
  9. 二進制
      src/assets/pay/svglogo.png
  10. 3 0
      src/assets/singlesvg/back/boxbg.svg
  11. 4 0
      src/assets/singlesvg/back/boxclose.svg
  12. 4 0
      src/assets/singlesvg/back/circlearrow.svg
  13. 22 0
      src/assets/singlesvg/back/circlebg.svg
  14. 2 0
      src/assets/singlesvg/pix.svg
  15. 2 0
      src/assets/singlesvg/video.svg
  16. 16 3
      src/components/GameItem/index.jsx
  17. 8 1
      src/components/SubScreen/index.jsx
  18. 6 1
      src/constants/app.js
  19. 2 1
      src/constants/localkey.js
  20. 5 1
      src/constants/routes.js
  21. 14 1
      src/db/routes.js
  22. 82 2
      src/features/api.js
  23. 36 10
      src/features/mainSlice.js
  24. 166 0
      src/features/paySlice.js
  25. 1 1
      src/index.js
  26. 7 6
      src/layout/BottomNav/index.jsx
  27. 1 1
      src/layout/Navbar/index.jsx
  28. 2 2
      src/layout/Routes/RouteWrapper.jsx
  29. 4 3
      src/layout/Routes/index.jsx
  30. 31 0
      src/locales/languages/en_US.json
  31. 10 0
      src/pages/Deposit.jsx
  32. 10 0
      src/pages/PaymentOrder.jsx
  33. 9 1
      src/pages/index.jsx
  34. 17 0
      src/styles/_elements.scss
  35. 4 0
      src/styles/theme.js
  36. 69 0
      src/utils/helpers.js
  37. 17 14
      src/widgets/ModuleGroup/index.jsx
  38. 3 3
      src/widgets/UserSettings/index.jsx
  39. 182 0
      src/widgets/WDeposit/BR/BRDeposit.jsx
  40. 194 0
      src/widgets/WDeposit/BR/styles.module.scss
  41. 53 0
      src/widgets/WDeposit/DepositHeader.jsx
  42. 10 0
      src/widgets/WDeposit/index.jsx
  43. 91 0
      src/widgets/WDeposit/styles.module.scss
  44. 141 9
      src/widgets/WGame/index.jsx
  45. 119 0
      src/widgets/WGame/styles.module.scss
  46. 154 0
      src/widgets/WPaymentOrder/BR/BRPayOrder.jsx
  47. 114 0
      src/widgets/WPaymentOrder/BR/styles.module.scss
  48. 10 0
      src/widgets/WPaymentOrder/index.jsx
  49. 5 0
      src/widgets/WPaymentOrder/styles.module.scss

+ 1 - 0
package.json

@@ -42,6 +42,7 @@
     "nanoid": "^4.0.1",
     "or": "^0.2.0",
     "prop-types": "^15.8.1",
+    "qrcode.react": "^3.1.0",
     "query-string": "^9.0.0",
     "react": "^18.2.0",
     "react-big-calendar": "^1.6.8",

+ 9 - 2
src/App.js

@@ -41,21 +41,23 @@ import createCache from '@emotion/cache';
 import {BrowserRouter, HashRouter, Route, Routes, useLocation} from 'react-router-dom';
 import {ToastContainer} from 'react-toastify';
 import Layout from "@layout/Layout";
-import {getFetchStatus} from '@features/mainSlice';
+import {getFetchStatus, getUserID, getUserInfo} from '@features/mainSlice';
 import {useDispatch, useSelector} from "react-redux";
 import {REQ_STATUS} from "@api/config";
 import {reqGetRoutes} from "@features/api";
 import LoadingScreen from "@components/LoadingScreen";
+import {reqPayConfig} from "@features/paySlice";
 
 
 const App = () => {
     const dispatch = useDispatch();
     const fetchStatus=useSelector(getFetchStatus);
+    const userInfo=useSelector(getUserInfo);
+    const userID=useSelector(getUserID);
     const appRef = useRef(null);
     const {theme, direction} = useThemeProvider();
     const gaKey = process.env.REACT_APP_PUBLIC_GA;
     gaKey && ReactGA.initialize(gaKey);
-
     // auto RTL support for Material-UI components and styled-components
 
     const plugins = direction === 'rtl' ? [rtlPlugin] : [];
@@ -78,6 +80,11 @@ const App = () => {
         appRef.current && appRef.current.scrollTo(0, 0);
         preventDefault();
     }, []);
+    useEffect(()=>{
+        if (userID!=0){
+            reqPayConfig(dispatch,userInfo);
+        }
+    },[userID])
     const renderLayout=()=>{
         return (
             <>

+ 2 - 0
src/Global.js

@@ -4,3 +4,5 @@ import i18n from './locales/index';
 global.i18n=i18n;
 // global.symbol=symbol;
 // global.symbol_m=symbol_m;
+global.DOLLAR="R$";
+global.dispatch=null;

+ 19 - 11
src/api/config.js

@@ -9,25 +9,33 @@ export const REQ_STATUS={
 // export const BASE_API="https://api.24680.com/";
 export const BASE_API="https://api.ouro777.com/";
 
+export const BASE_PREFIX="game/";
+
 export const APP_AVATAR="https://cdn.moeda777.com/24680/assets/avatar/1/";
-// export const APP_ROUTES="routes";
 //路由
-export const APP_ROUTES="game/routes";
+export const APP_ROUTES=BASE_PREFIX+"routes";
 //page 模块
-export const APP_PAGE_MODULES="game/pageModules";
+export const APP_PAGE_MODULES=BASE_PREFIX+"pageModules";
 //game more
-export const APP_GAME_LIST="game/gameList";
+export const APP_GAME_LIST=BASE_PREFIX+"gameList";
 //login
-export const APP_LOGIN="game/login";
+export const APP_LOGIN=BASE_PREFIX+"login";
 //Reg
-export const APP_REGISTER="game/register";
+export const APP_REGISTER=BASE_PREFIX+"register";
 //logout
-export const APP_LOGOUT="game/logout";
+export const APP_LOGOUT=BASE_PREFIX+"logout";
 //changePass
-export const APP_CHANGE_PASS="game/changePass";
+export const APP_CHANGE_PASS=BASE_PREFIX+"changePass";
 //changeInfo
-export const APP_CHANGE_INFO="game/changeInfo";
+export const APP_CHANGE_INFO=BASE_PREFIX+"changeInfo";
 //增加/game/changePhone /game/changeEmail
-export const APP_CHANGE_PHONE="game/changePhone";
-export const APP_CHANGE_EMAIL="game/changeEmail";
+export const APP_CHANGE_PHONE=BASE_PREFIX+"changePhone";
+export const APP_CHANGE_EMAIL=BASE_PREFIX+"changeEmail";
+//pay
+export const APP_RECHARGE_CONFIG=BASE_PREFIX+"recharge/gear";
+export const APP_FIRSTPAY_CONFIG=BASE_PREFIX+"recharge/firstPayConfig";
+export const APP_ACCOUNTS_PAY_INFO=BASE_PREFIX+"api/get_accounts_pay_info";
+export const APP_PAYMENT_ORDER=BASE_PREFIX+"payment_entry/pay";
+export const APP_GAME_INFO=BASE_PREFIX+"info";
+//pay
 

+ 6 - 4
src/api/request.js

@@ -63,10 +63,12 @@ service.interceptors.response.use(
 const get=(params={})=>{
     let sign=getSign();
     if (sign!=null&&sign!=""){
-        let url=params.url;
-        if (url.indexOf("?")===-1)url=url+"?sign="+getSign();
-        else url=url+"&sign="+getSign();
-        params.url=url;
+        // let url=params.url;
+        // if (url.indexOf("?")===-1)url=url+"?sign="+getSign();
+        // else url=url+"&sign="+getSign();
+        // params.url=url;
+        if (params.params==null)params.params={};
+        params.params["sign"]=getSign();
     }
     return service({
         method: 'get',

+ 3 - 1
src/app/store.js

@@ -3,12 +3,14 @@ import TodosReducer from '../features/todos/todosSlice';
 import MainReducer from '@features/mainSlice';
 import PageReducer from '@features/pageSlice';
 import GameListReducer from '@features/gameListSlice';
+import PayReducer from '@features/paySlice';
 
 export default configureStore({
     reducer: {
         todos: TodosReducer,
         main:MainReducer,
         page:PageReducer,
-        gamelist:GameListReducer
+        gamelist:GameListReducer,
+        pay:PayReducer
     }
 });

二進制
src/assets/pay/fpayimg.png


二進制
src/assets/pay/img_sc_66.png


二進制
src/assets/pay/svglogo.png


文件差異過大導致無法顯示
+ 3 - 0
src/assets/singlesvg/back/boxbg.svg


+ 4 - 0
src/assets/singlesvg/back/boxclose.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="s-ion-icon">
+<path d="M4.34315 4.34315C3.22433 5.46197 2.4624 6.88743 2.15372 8.43928C1.84504 9.99113 2.00346 11.5997 2.60896 13.0615C3.21447 14.5233 4.23985 15.7727 5.55544 16.6518C6.87103 17.5308 8.41775 18 10 18C11.5823 18 13.129 17.5308 14.4446 16.6518C15.7602 15.7727 16.7855 14.5233 17.391 13.0615C17.9965 11.5997 18.155 9.99112 17.8463 8.43928C17.5376 6.88743 16.7757 5.46197 15.6569 4.34315" stroke="white" stroke-width="3" stroke-linecap="round"></path>
+<path d="M10 9L10 2" stroke="white" stroke-width="3" stroke-linecap="round"></path>
+</svg>

+ 4 - 0
src/assets/singlesvg/back/circlearrow.svg

@@ -0,0 +1,4 @@
+<svg width="19" height="22" viewBox="0 0 19 22" fill="none" xmlns="http://www.w3.org/2000/svg" class="s-ion-icon">
+<path d="M10.6807 19.8188L3.00023 10.9095L10.6807 2.00024" stroke="white" stroke-width="3.60514" stroke-linecap="round"></path>
+<path d="M16.9424 16.4668L11.9998 10.7334L16.9424 5.00008" stroke="white" stroke-width="3" stroke-linecap="round"></path>
+</svg>

+ 22 - 0
src/assets/singlesvg/back/circlebg.svg

@@ -0,0 +1,22 @@
+<svg width="60" height="61" viewBox="0 0 60 61" fill="none" xmlns="http://www.w3.org/2000/svg" class="s-ion-icon">
+<g filter="url(#filter0_d_5688_3825)">
+<circle cx="29" cy="25" r="24" fill="black" fill-opacity="0.55" shape-rendering="crispEdges"></circle>
+<circle cx="29" cy="25" r="24" stroke="url(#paint0_linear_5688_3825)" stroke-opacity="0.61" shape-rendering="crispEdges"></circle>
+</g>
+<defs>
+<filter id="filter0_d_5688_3825" x="0.8" y="0.5" width="58.4" height="59.7" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"></feColorMatrix>
+<feOffset dx="1" dy="6"></feOffset>
+<feGaussianBlur stdDeviation="2.35"></feGaussianBlur>
+<feComposite in2="hardAlpha" operator="out"></feComposite>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"></feColorMatrix>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5688_3825"></feBlend>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5688_3825" result="shape"></feBlend>
+</filter>
+<linearGradient id="paint0_linear_5688_3825" x1="35.5" y1="30.5" x2="32.6143" y2="3.31202" gradientUnits="userSpaceOnUse">
+<stop stop-color="white" stop-opacity="0"></stop>
+<stop offset="1" stop-color="white"></stop>
+</linearGradient>
+</defs>
+</svg>

+ 2 - 0
src/assets/singlesvg/pix.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg fill="#000000" width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M11.917 11.71a2.046 2.046 0 0 1-1.454-.602l-2.1-2.1a.4.4 0 0 0-.551 0l-2.108 2.108a2.044 2.044 0 0 1-1.454.602h-.414l2.66 2.66c.83.83 2.177.83 3.007 0l2.667-2.668h-.253zM4.25 4.282c.55 0 1.066.214 1.454.602l2.108 2.108a.39.39 0 0 0 .552 0l2.1-2.1a2.044 2.044 0 0 1 1.453-.602h.253L9.503 1.623a2.127 2.127 0 0 0-3.007 0l-2.66 2.66h.414z"/><path d="m14.377 6.496-1.612-1.612a.307.307 0 0 1-.114.023h-.733c-.379 0-.75.154-1.017.422l-2.1 2.1a1.005 1.005 0 0 1-1.425 0L5.268 5.32a1.448 1.448 0 0 0-1.018-.422h-.9a.306.306 0 0 1-.109-.021L1.623 6.496c-.83.83-.83 2.177 0 3.008l1.618 1.618a.305.305 0 0 1 .108-.022h.901c.38 0 .75-.153 1.018-.421L7.375 8.57a1.034 1.034 0 0 1 1.426 0l2.1 2.1c.267.268.638.421 1.017.421h.733c.04 0 .079.01.114.024l1.612-1.612c.83-.83.83-2.178 0-3.008z"/></svg>

文件差異過大導致無法顯示
+ 2 - 0
src/assets/singlesvg/video.svg


+ 16 - 3
src/components/GameItem/index.jsx

@@ -1,11 +1,14 @@
 import styles from "@components/GameItem/styles.module.scss";
-import {NavLink} from "react-router-dom";
+import {NavLink, useNavigate} from "react-router-dom";
 import {LazyLoadImage} from "react-lazy-load-image-component";
 import symbol from "@assets/symbol-defs.svg";
 import React from "react";
 import {ROUTE_PATH} from "@constants/routes";
+import {localStorageSet} from "@utils/helpers";
+import {LOCAL_GAME_URL} from "@constants/localkey";
 
 const GameItem=({data})=>{
+    const navigate=useNavigate();
     const renderOlicon=()=>{
         return (
             <svg xmlns="http://www.w3.org/2000/svg" width="9" height="10" viewBox="0 0 9 10" fill="none"><path d="M7.78243 7.00126C7.98931 8.18376 7.16525 9.0422 6.01681 9.23532C4.90775 9.42188 3.09993 9.42188 1.99087 9.23532C0.842435 9.04251 0.0183723 8.18438 0.225247 7.00157C0.400872 5.99813 1.25118 5.37282 2.28993 5.42657C3.04868 5.46594 3.51493 5.56469 4.05462 5.56469C4.60056 5.56469 4.96431 5.46594 5.71743 5.42657C6.75587 5.37219 7.60712 5.99782 7.78243 7.00126ZM3.86275 0.907195C4.95368 0.907195 5.83837 1.79157 5.83837 2.88313C5.83837 3.9747 4.95368 4.85907 3.86275 4.85907C2.7715 4.85907 1.88681 3.97438 1.88681 2.88313C1.88681 1.79188 2.7715 0.907195 3.86275 0.907195Z" fill="url(#paint0_linear_451_3515)"></path><path d="M7.42806 5.14407C7.95931 5.2425 8.59868 5.525 8.85493 6.28813C9.09181 6.99375 8.81275 7.54688 8.49493 7.91282C8.39368 8.02938 8.19087 7.92813 8.24118 7.78532C8.37181 7.41594 8.42431 6.94407 8.21993 6.42157C8.02118 5.91313 7.65337 5.59282 7.31962 5.39563C7.18025 5.31344 7.26681 5.11407 7.42806 5.14407ZM5.63118 0.938442C5.47243 0.825317 5.58681 0.582817 5.77868 0.631255C5.98087 0.682192 6.189 0.761567 6.38306 0.883442C7.02337 1.28657 7.33993 1.99969 7.22712 2.79188C7.17462 3.16157 7.01056 3.44907 6.82587 3.66625C6.70431 3.80969 6.46431 3.69032 6.51431 3.51157C6.63181 3.09219 6.6665 2.55657 6.44056 1.96813C6.25431 1.48344 5.93587 1.15625 5.63118 0.938442Z" fill="#26AB4B"></path><defs><linearGradient id="paint0_linear_451_3515" x1="5.21662" y1="0.333274" x2="5.21662" y2="9.37524" gradientUnits="userSpaceOnUse"><stop stop-color="#85F25E"></stop><stop offset="1" stop-color="#33EF00"></stop></linearGradient></defs></svg>
@@ -19,10 +22,20 @@ const GameItem=({data})=>{
         }
         return snum;
     }
+    const onEnterGame=()=>{
+        let id=data.id;
+        let url=data.link;
+        localStorageSet(LOCAL_GAME_URL+id,url);
+        let path=ROUTE_PATH.GAME+"/"+id;
+        navigate(path);
+    }
+    //to={ROUTE_PATH.GAME+"/"+data.id+"?url="+data.link}
     return (
         <div className={styles.grid_item}>
             {/*<NavLink to={data.link} className={styles.game_img_wrap}>*/}
-            <NavLink to={ROUTE_PATH.GAME+"/"+data.link} className={styles.game_img_wrap}>
+            <button onClick={()=>{
+                onEnterGame();
+            }} className={styles.game_img_wrap}>
                 <LazyLoadImage
                     src={data.img}
                     alt={"game-icon"}
@@ -35,7 +48,7 @@ const GameItem=({data})=>{
                     }
                     <span>{formatNum(data.online)}</span>
                 </div>
-            </NavLink>
+            </button>
             <div className={styles.bot_info}>
                 <div className={styles.game_tit}>
                     <NavLink className={styles.game_desc}>

+ 8 - 1
src/components/SubScreen/index.jsx

@@ -8,8 +8,9 @@ import {useLocation} from "react-router";
 import {sleep} from "@utils/helpers";
 const i18n=global.i18n;
 
-const SubScreen=({open,onClose,children,route,timeout})=>{
+const SubScreen=({open,onClose,children,route,timeout,header})=>{
     // const [subOpen,setSubOpen]=useState(open);
+    // console.log(header)
     const subOpen=open;
     const {pathname,hash} = useLocation();
     const duration=timeout;
@@ -51,6 +52,12 @@ const SubScreen=({open,onClose,children,route,timeout})=>{
         )
     }
     const renderBar=()=>{
+        const Header=header;
+        if (Header!=null){
+            return (
+                <Header id={'subbar'} className={styles.appbar} route={route} close={close}/>
+            )
+        }
         return (
             <div id={'subbar'} className={styles.appbar}>
                 {renderHeader()}

+ 6 - 1
src/constants/app.js

@@ -7,7 +7,12 @@ const APP_GENDER={
     MALE:1,
     OTHER:2,
 }
+const APP_CHANNEL={
+    Channel:"com.ouro777.j15",
+    ChannelNumber:271
+}
 export {
     APP_THEME,
-    APP_GENDER
+    APP_GENDER,
+    APP_CHANNEL
 };

+ 2 - 1
src/constants/localkey.js

@@ -2,4 +2,5 @@ const BASE="SG_";
 const LOCAL_USER_INFO="USER_INFO";
 const LOCAL_IS_LOGIN="IS_LOGIN";
 const LOCAL_SIGN="G_SIGN";
-export {LOCAL_USER_INFO,LOCAL_IS_LOGIN,LOCAL_SIGN};
+const LOCAL_GAME_URL="LOCAL_GAME_URL_";
+export {LOCAL_USER_INFO,LOCAL_IS_LOGIN,LOCAL_SIGN,LOCAL_GAME_URL};

+ 5 - 1
src/constants/routes.js

@@ -10,12 +10,16 @@ const SIDE_TYPE_NOMAL=1;
 const SIDE_TYPE_SPECIAL=2;
 
 const ROUTE_PATH={
+    BACK:-1,
     SIGN_IN:"#/signin",
     SIGN_UP:"#/signup",
     SETTINGS:"#/settings",
     EDIT_PROFILE:"#/editprofile",
     EDIT_PWD:"#/editpwd",
-    GAME:"/game"
+    GAME:"/game",
+    PAY:"#/pay",
+    SAQUE:"#/saque",
+    PAY_ORDER:"#/payorder"
 }
 
 export {

+ 14 - 1
src/db/routes.js

@@ -190,5 +190,18 @@ export const routes=[
         login:1,//0,1 检不检查登录
         lpath:"#/signin",//登录path
         subs:[]
-    }
+    },
+    {
+        path: "#/payorder",
+        type: 1,
+        side: 0,
+        block:1,//块排序
+        title: "Payment order",
+        icon:"",
+        fill:";;",//icon 颜色 默认 选中 本身颜色
+        component:"paymentOrder",
+        login:1,//0,1 检不检查登录
+        lpath:"#/signin",//登录path
+        subs:[]
+    },
 ]

+ 82 - 2
src/features/api.js

@@ -1,17 +1,19 @@
 import {createAsyncThunk} from "@reduxjs/toolkit";
 import {
+    APP_ACCOUNTS_PAY_INFO,
     APP_CHANGE_EMAIL,
-    APP_CHANGE_INFO, APP_CHANGE_PASS, APP_CHANGE_PHONE,
+    APP_CHANGE_INFO, APP_CHANGE_PASS, APP_CHANGE_PHONE, APP_FIRSTPAY_CONFIG, APP_GAME_INFO,
     APP_GAME_LIST,
     APP_LOGIN,
     APP_LOGOUT,
-    APP_PAGE_MODULES,
+    APP_PAGE_MODULES, APP_PAYMENT_ORDER, APP_RECHARGE_CONFIG,
     APP_REGISTER,
     APP_ROUTES,
     REQ_STATUS
 } from "@api/config";
 import Http from "@api/request";
 import {updateGameList} from "@features/pageSlice";
+import {APP_CHANNEL} from "@constants/app";
 
 export const buildReqReducer=(builder,thunk,callback,statusCB=null)=>{
     if (builder==null||thunk==null)return;
@@ -175,4 +177,82 @@ export const reqChangeEmail=createAsyncThunk(
         return response;
     },
 )
+//pay
+export const reqRechargeConfig=createAsyncThunk(
+    APP_RECHARGE_CONFIG,
+    async (arg,thunkAPI)=>{
+        let params={
+            url:APP_RECHARGE_CONFIG
+        }
+        const response=await Http.get(params);
+        return response;
+    }
+)
+export const reqFirstPayConfig=createAsyncThunk(
+    APP_FIRSTPAY_CONFIG,
+    async (arg,thunkAPI)=>{
+        let params={
+            url:APP_FIRSTPAY_CONFIG,
+            params:{
+                Channel:APP_CHANNEL.Channel,
+                ChannelNumber:APP_CHANNEL.ChannelNumber,
+                UserID:arg
+            }
+        }
+        const response=await Http.get(params);
+        return response;
+    }
+)
+export const reqGetAccountsPayInfo=createAsyncThunk(
+    APP_ACCOUNTS_PAY_INFO,
+    async (arg,thunkAPI)=>{
+        let params={
+            url:APP_ACCOUNTS_PAY_INFO,
+            params:{
+                UserID:arg
+            }
+        }
+        const response=await Http.get(params);
+        return response;
+    }
+)
+export const reqPaymentOrder=createAsyncThunk(
+    APP_PAYMENT_ORDER,
+    async (arg,thunkAPI)=>{
+        let {user,price,goodsName,payType,GiftsID}=arg;
+        let params={
+            url:APP_PAYMENT_ORDER,
+            params:{
+                userID:user.UserID,
+                tranType:"0502",
+                payAmt:price,
+                goodsName:goodsName,
+                buyIp:"",
+                pay_type:payType,
+                GiftsID:GiftsID,
+                pck:APP_CHANNEL.Channel,
+                eventType:1,
+                AdId:user.GlobalUID,
+                userName:user.NickName,
+                userEmail:user.Email,
+                userPhone:user.Phone,
+                rand_str:Date.now()
+            }
+        }
+        const response=await Http.get(params);
+        return response;
+    }
+)
+//pay
+//用户信息
+export const reqGameInfo=createAsyncThunk(
+    APP_GAME_INFO,
+    async (arg,thunkAPI)=>{
+        let params={
+            url:APP_GAME_INFO
+        }
+        const response=await Http.get(params);
+        return response;
+    }
+)
 //api

+ 36 - 10
src/features/mainSlice.js

@@ -11,7 +11,7 @@ import {REQ_STATUS} from "@api/config";
 import {
     buildReqReducer, reqChangeEmail,
     reqChangeInfo,
-    reqChangePass, reqChangePhone,
+    reqChangePass, reqChangePhone, reqGameInfo,
     reqGetRoutes,
     reqLogin,
     reqLogout,
@@ -20,6 +20,7 @@ import {
 import {toast} from 'react-toastify';
 import {getHttpMsg, localStorageGet, localStorageSet} from "@utils/helpers";
 import {LOCAL_IS_LOGIN, LOCAL_SIGN, LOCAL_USER_INFO} from "@constants/localkey";
+import {reqPayConfig} from "@features/paySlice";
 const i18n=global.i18n;
 const generateNavs=(routes)=>{
     const navs=[];
@@ -56,9 +57,9 @@ const generateRoutes=(routes,asyncRoutes=[])=>{
                     // if (route.path==="#/signin"||route.path==="#/signup"){
                     //     route.component="Login";
                     // }
-                    // if (route.path==="/slots"){
-                    //     route.login=1;
-                    // }
+                    if (route.path==="#/pay"){
+                        route.component="deposit";
+                    }
                     allMap[route.path]=route;
                     let type=route.type;
                     if (type===ROUTE_TYPE_IN||type===ROUTE_TYPE_FULL)inRoutes.push(route);
@@ -136,6 +137,8 @@ const reducerRoutes=(state,action)=>{
             if (typeof user=="object"){
                 isLogin=1;
                 userInfo=user;
+                //请求pay
+                // global.dispatch(reqPayConfig(user));
             }
         }
         Object.assign(state, {routes:state.routes,asyncRoutes:data,styles:styles,blocks:blocks,...generData,isLogin:isLogin,userInfo:userInfo});
@@ -171,7 +174,7 @@ const getMsg=(payload)=>{
     // return msg;
     return getHttpMsg(payload);
 }
-const parseLogin=(state,action,arg)=>{
+const parseLogin=(state,action,arg,isShowMsg=true)=>{
     let payload=action.payload;
     let code=payload.code;
     let msg=getMsg(payload);
@@ -184,14 +187,18 @@ const parseLogin=(state,action,arg)=>{
         // localStorageSet(LOCAL_IS_LOGIN,1);
         let sign=data.sign;
         if (sign!=null)localStorageSet(LOCAL_SIGN,sign);
-        toast.success(msg);
+        if(isShowMsg)toast.success(msg);
+        //请求pay
+        // global.dispatch(reqPayConfig(data));
     }
     else
     {
-        toast.error(msg);
+        if(isShowMsg)toast.error(msg);
+    }
+    if (arg){
+        let callback=arg.callback;
+        if (callback!=null)callback(code);
     }
-    let callback=arg.callback;
-    if (callback!=null)callback(code);
 }
 const reducerLogin=(state,action,arg)=>{
     // toast.success("success");
@@ -273,6 +280,15 @@ const changeEmailStatus=(state,status,arg)=>{
     state.modifyStatus.phone=status;
 }
 //modify
+//gameinfo
+const reducerGameInfo=(state,action,arg)=>{
+    // parseLogin(state,action,arg);
+    parseLogin(state,action,arg,false);
+}
+const gameInfoStatus=(state,status,arg)=>{
+    state.gameInfoStatus=status;
+}
+//gameinfo
 export const Main=createSlice({
     name: 'main',
     initialState: {
@@ -294,7 +310,8 @@ export const Main=createSlice({
             password:REQ_STATUS.NONE,
             phone:REQ_STATUS.NONE,
             email:REQ_STATUS.NONE
-        }
+        },
+        gameInfoStatus:REQ_STATUS.NONE
     },
     reducers: {
         logout:(state, action)=>{
@@ -315,6 +332,7 @@ export const Main=createSlice({
         buildReqReducer(builder,reqChangeInfo,reducerChangeInfo,changeInfoStatus);
         buildReqReducer(builder,reqChangePhone,reducerChangePhone,changePhoneStatus);
         buildReqReducer(builder,reqChangeEmail,reducerChangeEmail,changeEmailStatus);
+        buildReqReducer(builder,reqGameInfo,reducerGameInfo,gameInfoStatus);
     },
 })
 export const {logout} = Main.actions;
@@ -437,6 +455,14 @@ export const isLogined=(state)=>{
 export const getUserInfo=(state)=>{
     return state.main.userInfo;
 }
+export const getUserID=(state)=>{
+    let uid=0;
+    let userInfo=state.main.userInfo;
+    if (userInfo){
+        if (userInfo.UserID!=null)uid=userInfo.UserID;
+    }
+    return uid;
+}
 //数据获取
 export default Main.reducer;
 

+ 166 - 0
src/features/paySlice.js

@@ -0,0 +1,166 @@
+import {createSlice} from "@reduxjs/toolkit";
+import {REQ_STATUS} from "@api/config";
+import {
+    buildReqReducer,
+    reqFirstPayConfig,
+    reqGetAccountsPayInfo,
+    reqPaymentOrder,
+    reqRechargeConfig
+} from "@features/api";
+const reducerRechargeConfig=(state,action,arg)=>{
+    let payload=action.payload;
+    if (payload!=null&&payload.code===200){
+        let data=payload.data;
+        state.config=data;
+    }
+}
+const rechargeConfigStatus=(state,status,arg)=>{
+    state.status.RechargeConfig=status;
+}
+const reducerFirstPayConfig=(state,action,arg)=>{
+    let payload=action.payload;
+    payload={
+        "data": {
+            "first_pay": {
+                "id": "1017",
+                "money": "10",
+                "gear": "[{\"id\":\"28\",\"name\":\"PIX\\u76f4\\u8fde\",\"status\":1,\"type\":3}]",
+                "status": "1",
+                "created_at": "2022-06-09 13:57:58.000",
+                "favorable_price": 20,
+                "image": "11",
+                "give": "10",
+                "first_pay": "1",
+                "name": "\u9996\u5145\u6863\u4f4d\u914d\u7f6e",
+                "gift_id": "201",
+                "channels": "-1"
+            },
+            "recomendar_recharge": "7"
+        },
+        "result": "",
+        "msg": "success",
+        "code": 200
+    };
+    if (payload!=null&&payload.code===200){
+        let data=payload.data;
+        state.firstconfig=data;
+        console.log(state.firstconfig)
+    }
+}
+const firstPayConfigStatus=(state,status,arg)=>{
+    state.status.FirstPayConfig=status;
+}
+const reducerGetAccountsPayInfo=(state,action,arg)=>{
+    let payload=action.payload;
+    if (payload!=null&&payload.code===200){
+        let data=payload.data;
+        state.payconfig=data;
+    }
+}
+const getAccountsPayInfoStatus=(state,status,arg)=>{
+    state.status.GetAccountsPayInfo=status;
+}
+const reducerPaymentOrder=(state,action,arg)=>{
+    let payload=action.payload;
+    payload={
+        "data": {
+            "content": "00020101021226830014br.gov.bcb.pix2561pix.delbank.com.br\/v1\/qrcode\/vcharge22e43499260b46a9a5f303ca55204000053039865802BR5907DELBANK6007ARACAJU62070503***6304F3DF",
+            "money": 10,
+            "prdOrdNo": "BR5050013857473344515256"
+        },
+        "result": "",
+        "msg": "success",
+        "code": 200
+    };
+    if (payload!=null&&payload.code===200){
+        let data=payload.data;
+        data.createAt=Date.now();
+        data.deadline=15*60;
+        state.currPayOrder=data;
+        if (arg.callback!=null)arg.callback();
+    }
+    console.log(payload)
+}
+const paymentOrderStatus=(state,status,arg)=>{
+    state.status.PaymentOrder=status;
+}
+export const Pay=createSlice({
+    name: 'pay',
+    initialState: {
+        status:{
+            RechargeConfig:REQ_STATUS.NONE,
+            FirstPayConfig:REQ_STATUS.NONE,
+            GetAccountsPayInfo:REQ_STATUS.NONE,
+            PaymentOrder:REQ_STATUS.NONE
+        },
+        config:[],
+        payconfig:null,
+        firstconfig:null,
+        payType:null,
+        currPayOrder:null
+
+    },
+    reducers: {
+
+    },
+    extraReducers: (builder) => {
+        buildReqReducer(builder,reqRechargeConfig,reducerRechargeConfig,rechargeConfigStatus);
+        buildReqReducer(builder,reqFirstPayConfig,reducerFirstPayConfig,firstPayConfigStatus);
+        buildReqReducer(builder,reqGetAccountsPayInfo,reducerGetAccountsPayInfo,getAccountsPayInfoStatus);
+        buildReqReducer(builder,reqPaymentOrder,reducerPaymentOrder,paymentOrderStatus);
+    },
+})
+export const {} = Pay.actions;
+export const getConfig=(state)=>{
+    return state.pay.config;
+}
+export const getFirstPay=(state)=>{
+    let firstconfig=state.pay.firstconfig;
+    let config=state.pay.config;
+    let order=null;
+    if (firstconfig!=null){
+        let first_pay=firstconfig.first_pay;
+        let recomendar_recharge=firstconfig.recomendar_recharge;
+        if (first_pay!=null){
+            order={
+                goodsName:"firstpay",
+                goodsPrice:first_pay.money,
+                GiftsID: 201,
+                cpf_first:0,
+                give:first_pay.give,
+                gear:JSON.parse(first_pay.gear)
+            }
+        }
+        else
+        {
+            for (let i = 0; i <config.length ; i++) {
+                const elem = config[i];
+                if (elem.id===recomendar_recharge){
+                    order={
+                        goodsName: "chip",
+                        goodsPrice: elem.money,
+                        GiftsID:elem.gift_id,
+                        cpf_first:0,
+                        give:elem.give,
+                        gear:JSON.parse(elem.gear)
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    return order;
+}
+export const getPaymentOrderStatus=(state)=>{
+    return state.pay.status.PaymentOrder;
+}
+export const getCurrPayOrder=(state)=>{
+    return state.pay.currPayOrder;
+}
+export default Pay.reducer;
+
+export const reqPayConfig=(dispatch,userInfo)=>{
+    dispatch(reqRechargeConfig());
+    dispatch(reqFirstPayConfig(userInfo.UserID));
+    dispatch(reqGetAccountsPayInfo(userInfo.UserID));
+}

+ 1 - 1
src/index.js

@@ -9,7 +9,7 @@ import {ShopProvider} from '@contexts/shopContext';
 import {Provider} from 'react-redux';
 import store from './app/store';
 import * as Sentry from "@sentry/react";
-
+global.dispatch=store.dispatch;
 Sentry.init({
     dsn: "https://4686ef0d926e140fb482e63efcde1cdf@o4507102375641088.ingest.us.sentry.io/4507102380687360",
     integrations: [

+ 7 - 6
src/layout/BottomNav/index.jsx

@@ -17,6 +17,7 @@ import {ReactComponent as TabWithdraw} from '@assets/tabicon/withdraw.svg';
 import {ReactComponent as TabPay} from '@assets/tabicon/pay.svg';
 import {ReactComponent as TabMessage} from '@assets/tabicon/message.svg';
 import {ReactComponent as TabSett} from '@assets/tabicon/sett.svg';
+import {ROUTE_PATH} from "@constants/routes";
 const i18n=global.i18n;
 
 const BottomNav = () => {
@@ -63,24 +64,24 @@ const BottomNav = () => {
                 {/*<svg className={"icon"}>*/}
                 {/*    <use xlinkHref={`${ticon_gift}#gift`} />*/}
                 {/*</svg>*/}
-                <TabGift className={styles.icon}></TabGift>
+                <TabGift className={styles.icon}/>
                 <span>{i18n.t("tab.promotion")}</span>
             </button>
-            <NavLink className={styles.button} to="/" aria-label="Home">
+            <NavLink className={styles.button} to={ROUTE_PATH.SAQUE} aria-label="Home">
                 {/*<svg className={"icon"}>*/}
                 {/* <use xlinkHref={`${symbol_m}#icon_Home_1`} />*/}
                 {/*</svg>*/}
-                <TabWithdraw className={styles.icon}></TabWithdraw>
+                <TabWithdraw className={styles.icon}/>
                 <span>{i18n.t("tab.withdraw")}</span>
             </NavLink>
-            <NavLink className={styles.button} to="/promotions">
+            <NavLink className={styles.button} to={ROUTE_PATH.PAY}>
                 <div className={styles['wallet-tabbar-wrap']}>
                     <div className={styles['in-1']}>
                         <div className={styles['in-2']}>
                             {/*<svg className={"icon"}>*/}
                             {/*    <use xlinkHref={`${symbol_m}#icon_Promotions`} />*/}
                             {/*</svg>*/}
-                            <TabPay className={styles.icon_yellow}></TabPay>
+                            <TabPay className={styles.icon_yellow}/>
                         </div>
                     </div>
                 </div>
@@ -90,7 +91,7 @@ const BottomNav = () => {
                 {/*<svg className={"icon"}>*/}
                 {/*    <use xlinkHref={`${symbol_m}#icon_Account`} />*/}
                 {/*</svg>*/}
-                <TabMessage className={styles.icon}></TabMessage>
+                <TabMessage className={styles.icon}/>
                 <span>{i18n.t("tab.message")}</span>
             </button>
             <button className={styles.button}>

+ 1 - 1
src/layout/Navbar/index.jsx

@@ -228,7 +228,7 @@ const UserInfo=()=>{
                     }}>
                         <div className={styles.info}>
                             <div className={styles.nick}>{user.NickName}</div>
-                            <div className={styles.score}>{"$"+numFormatter(user.Score)}</div>
+                            <div className={styles.score}>{global.DOLLAR+" "+numFormatter(user.Score)}</div>
                         </div>
                         <LazyImage wrapperClassName={styles.avatar} src={user.img} alt={"Head"}/>
                     </div>

+ 2 - 2
src/layout/Routes/RouteWrapper.jsx

@@ -1,7 +1,7 @@
 import React, {useMemo, useState, useEffect, useRef} from 'react';
 import Popup from "@components/Popup";
 import { useNavigate } from 'react-router-dom';
-import {ROUTE_TYPE_FULL, ROUTE_TYPE_IN, ROUTE_TYPE_POP, ROUTE_TYPE_POP_OR_FULL} from "@constants/routes";
+import {ROUTE_PATH, ROUTE_TYPE_FULL, ROUTE_TYPE_IN, ROUTE_TYPE_POP, ROUTE_TYPE_POP_OR_FULL} from "@constants/routes";
 import {useThemeProvider} from "@contexts/themeContext";
 import SubScreen from "@components/SubScreen";
 import useScrollLock from "@hooks/useScrollLock";
@@ -38,7 +38,7 @@ const RouteWrapper = (props) => {
         );
     }
     const handleClose = () => {
-        navigate(-1);
+        navigate(ROUTE_PATH.BACK);
     }
     const renderPop=()=>{
         let comp=(<></>);

+ 4 - 3
src/layout/Routes/index.jsx

@@ -1,4 +1,4 @@
-import AllComponents from '@pages/index';
+import AllComponents, {Header} from '@pages/index';
 import {Route, Routes, useNavigate} from 'react-router-dom';
 import React, {cloneElement, lazy, Suspense} from "react";
 import SmallLoading from "@components/SmallLoading";
@@ -8,6 +8,7 @@ import SubScreen from "@components/SubScreen";
 import RouteContainer from "@layout/Routes/RouteContainer";
 import {Navigate, useLocation} from "react-router";
 import usePreviousRoute from "@hooks/usePreviousRoute";
+import {ROUTE_PATH} from "@constants/routes";
 const RouteWrapper = lazy(() => import('@layout/Routes/RouteWrapper'));
 
 const PageNotFound = lazy(() => import('@pages/PageNotFound'));
@@ -69,7 +70,7 @@ const CHashRouter=(props)=>{
         return null;
     }
     const handleClose = () => {
-        navigate(-1);
+        navigate(ROUTE_PATH.BACK);
     }
     return (
         <TransitionGroup
@@ -91,7 +92,7 @@ const CHashRouter=(props)=>{
                     }
                     return (
                         <CSSTransition timeout={timeout}>
-                            <RouteContainer route={route} timeout={timeout} onClose={handleClose}>
+                            <RouteContainer route={route} timeout={timeout} onClose={handleClose} header={Header[route.component]}>
                                 <Suspense fallback={<SmallLoading/>}>
                                     <Routes key={index} location={{pathname:currpath,hash:hash,search}}>
                                         {

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

@@ -138,5 +138,36 @@
     "info": {
       "modi_success": "Modified information"
     }
+  },
+  "deposit": {
+    "uid": "UID:",
+    "banner":{
+      "first_title": "New Arrival Offer",
+      "recommend_title": "To recommend"
+    },
+    "list": {
+      "title": "More deposits",
+      "extra": "Extra"
+    },
+    "pay_btn": "Deposit Now",
+    "order_info": {
+      "pay_type_pix": "PixPay",
+      "tips": "expireAt {0}",
+      "create_date": "Creation date",
+      "time": "Time",
+      "order": "Request number",
+      "content": "Pay the rope",
+      "value": "Value",
+      "copyButton": "Copy pix code",
+      "lookButton": "Already paid",
+      "tips1": "Copy successfully,please open pix",
+      "tips2": "Thank you for your patronage"
+    }
+  },
+  "game": {
+    "back": "Back",
+    "msg_title": "Leave the game",
+    "msg_content": "Are you sure you want to leave?",
+    "cancel": "Cancel"
   }
 }

+ 10 - 0
src/pages/Deposit.jsx

@@ -0,0 +1,10 @@
+import WDeposit from "@widgets/WDeposit";
+
+const Deposit=({...props})=>{
+    return (
+        <>
+            <WDeposit {...props}/>
+        </>
+    )
+}
+export default Deposit;

+ 10 - 0
src/pages/PaymentOrder.jsx

@@ -0,0 +1,10 @@
+import WPaymentOrder from "@widgets/WPaymentOrder";
+
+const PaymentOrder=({...props})=>{
+    return (
+        <>
+            <WPaymentOrder {...props}/>
+        </>
+    )
+}
+export default PaymentOrder;

+ 9 - 1
src/pages/index.jsx

@@ -1,4 +1,5 @@
 import {lazy} from "react";
+import DepositHeader from "@widgets/WDeposit/DepositHeader";
 const ModulePage=lazy(()=>import('@pages/ModulePage'));
 const Home=lazy(()=>import('@pages/Home'));
 const Login=lazy(()=>import("@pages/Login"));
@@ -6,6 +7,8 @@ const Settings=lazy(()=>import("@pages/Settings"));
 const EditProfile=lazy(()=>import("@pages/EditProfile"));
 const EditPassword=lazy(()=>import("@pages/EditPassword"));
 const Game=lazy(()=>import("@pages/Game"));
+const Deposit=lazy(()=>import("@pages/Deposit"));
+const PaymentOrder=lazy(()=>import("@pages/PaymentOrder"))
 export default {
     ModulePage:ModulePage,
     Home:Home,
@@ -13,5 +16,10 @@ export default {
     settings:Settings,
     editProfile:EditProfile,
     editPassword:EditPassword,
-    game:Game
+    game:Game,
+    deposit:Deposit,
+    paymentOrder:PaymentOrder
+}
+export const Header={
+    deposit: DepositHeader
 }

+ 17 - 0
src/styles/_elements.scss

@@ -733,4 +733,21 @@ a {
     transition: transform .2s cubic-bezier(.36,.66,.04,1);
     text-transform: capitalize;
 }
+.button-yellow{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: relative;
+    width: 100%;
+    min-height: 2.75rem;
+    color: #fff;
+    background-color: #f19511b3;
+    background-image: conic-gradient(from 1turn, #F6C722, #F19511);
+    user-select: none;
+    border-radius: var(--border-radius);
+    font-weight: 700;
+    cursor: pointer;
+    transition: transform .2s cubic-bezier(.36,.66,.04,1);
+    text-transform: capitalize;
+}
 

+ 4 - 0
src/styles/theme.js

@@ -111,5 +111,9 @@ export default createGlobalStyle`
         light: 'rgba(0,0,0,.05)',
         dark: 'rgba(255,255,255,.05)',
     })};
+    --pay-btn-bg: ${theme('theme', {
+        light: '#FFFFFF',
+        dark:'rgba(69,70,80,0.5)'
+    })};
   }
 `;

+ 69 - 0
src/utils/helpers.js

@@ -144,3 +144,72 @@ export const sleep=async (time)=>{
         }, time);
     });
 }
+export const stringFormat=(str,args)=>{
+    if (str==null)return str;
+    if (args==null)args=[];
+    return str.replace(/{(\d+)}/g, function(match, number) {
+        return typeof args[number] != 'undefined'
+            ? args[number]
+            : match
+            ;
+    });
+}
+export const formatDate=(timestamp,format=null)=>{
+    let date=new Date(timestamp);
+    let year = `${date.getFullYear()}`;
+    let month = `${date.getMonth() + 1}`;
+    if (month.length === 1) {
+        month = `0${month}`;
+    }
+    let day = `${date.getDate()}`;
+    if (day.length === 1) {
+        day = `0${day}`;
+    }
+
+    let hours = `${date.getHours()}`;
+    if (hours.length === 1) {
+        hours = `0${hours}`;
+    }
+    let minutes = `${date.getMinutes()}`;
+    if (minutes.length === 1) {
+        minutes = `0${minutes}`;
+    }
+    let seconds = `${date.getSeconds()}`;
+    if (seconds.length === 1) {
+        seconds = `0${seconds}`;
+    }
+
+    return (format || "yyyy-MM-dd hh:mm:ss")
+        .replace(/yyyy/g, year)
+        .replace(/MM/g, month)
+        .replace(/dd/g, day)
+
+        .replace(/hh/g, hours)
+        .replace(/mm/g, minutes)
+        .replace(/ss/g, seconds);
+}
+export const formatTime=(time,isms=false)=>{
+    if (time==null)return "";
+    let seconds=time;
+    //毫秒
+    if(isms)seconds=Math.floor(time/1000);
+    let hours = Math.floor(seconds / 3600);
+    let minutes = Math.floor((seconds % 3600) / 60);
+    let remainingSeconds = seconds % 60;
+
+    let formattedTime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
+
+    return formattedTime;
+}
+export const openFullScreen=()=>{
+    var elem = document.documentElement; // 获取整个文档的根元素
+    if (elem.requestFullscreen) {
+        elem.requestFullscreen();
+    } else if (elem.mozRequestFullScreen) {
+        elem.mozRequestFullScreen();
+    } else if (elem.webkitRequestFullscreen) {
+        elem.webkitRequestFullscreen();
+    } else if (elem.msRequestFullscreen) {
+        elem.msRequestFullscreen();
+    }
+}

+ 17 - 14
src/widgets/ModuleGroup/index.jsx

@@ -8,6 +8,7 @@ import LoadingScreen from "@components/LoadingScreen";
 import AllWidgets from "@widgets/index";
 import styles from "./styles.module.scss";
 import BreadCrumb from "@layout/BreadCrumb";
+import Spring from "@components/Spring";
 
 const ModuleGroup=({pageID})=>{
     const dispatch = useDispatch();
@@ -24,20 +25,22 @@ const ModuleGroup=({pageID})=>{
             if (modules==null)return (<></>)
             return (
                 <Suspense fallback={<LoadingScreen />}>
-                    <div className={`${styles.container} ${isMobile()?'':'page-max-width-wrap'}`}>
-                        <BreadCrumb />
-                        {
-                            modules.map((item,index)=>{
-                                let Comp=AllWidgets[item.type];
-                                if (Comp==null)return (<></>);
-                                return (
-                                    <Fragment key={index}>
-                                        <Comp data={item}></Comp>
-                                    </Fragment>
-                                )
-                            })
-                        }
-                    </div>
+                    <Spring type={"slideUp"}>
+                        <div className={`${styles.container} ${isMobile()?'':'page-max-width-wrap'}`}>
+                            <BreadCrumb />
+                            {
+                                modules.map((item,index)=>{
+                                    let Comp=AllWidgets[item.type];
+                                    if (Comp==null)return (<></>);
+                                    return (
+                                        <Fragment key={index}>
+                                            <Comp data={item}></Comp>
+                                        </Fragment>
+                                    )
+                                })
+                            }
+                        </div>
+                    </Spring>
                 </Suspense>
             )
         }

+ 3 - 3
src/widgets/UserSettings/index.jsx

@@ -128,13 +128,13 @@ const UserSettings=()=>{
                                     <div className={styles.text}>{i18n.t("settings.user_info.id")}</div>
                                     <div className={styles.text}>{user.UserID}</div>
                                     <button>
-                                        <SvgIcon className={styles.icon_copy} herf={"icon_Copy"}></SvgIcon>
+                                        <SvgIcon className={styles.icon_copy} herf={"icon_Copy"}/>
                                     </button>
                                 </div>
                             </CopyToClipboard>
                             <div className={styles.info_item}>
                                 <img className={styles.icon_golds} src={USD}/>
-                                <div className={styles.golds}>{"$"+numFormatter(user.Score)}</div>
+                                <div className={styles.golds}>{global.DOLLAR+""+numFormatter(user.Score)}</div>
                             </div>
                         </div>
                     </div>
@@ -142,7 +142,7 @@ const UserSettings=()=>{
                         <button className={styles.edit_btn} onClick={()=>{
                             navigate(ROUTE_PATH.EDIT_PROFILE);
                         }}>
-                            <SvgIcon className={styles.icon} herf={"icon_Edit"}></SvgIcon>
+                            <SvgIcon className={styles.icon} herf={"icon_Edit"}/>
                         </button>
                     </div>
                 </div>

+ 182 - 0
src/widgets/WDeposit/BR/BRDeposit.jsx

@@ -0,0 +1,182 @@
+import styles from './styles.module.scss';
+import {useDispatch, useSelector} from "react-redux";
+import {getUserInfo} from "@features/mainSlice";
+import {getConfig, getFirstPay, getPaymentOrderStatus} from "@features/paySlice";
+import fpayimg from "@assets/pay/fpayimg.png";
+import img_sc from "@assets/pay/img_sc_66.png";
+import React, {useState} from "react";
+import Spring from "@components/Spring";
+import {REQ_STATUS} from "@api/config";
+import SmallLoading from "@components/SmallLoading";
+import {reqPaymentOrder} from "@features/api";
+import {useNavigate} from "react-router-dom";
+import {ROUTE_PATH} from "@constants/routes";
+const i18n=global.i18n;
+const BRDeposit=()=>{
+    const dispatch = useDispatch();
+    const navigate=useNavigate();
+    const user=useSelector(getUserInfo);
+    const firstpay=useSelector(getFirstPay);
+    const config=useSelector(getConfig);
+    const orderStatus=useSelector(getPaymentOrderStatus);
+    const [selectedID,setSelectedID]=useState("0");
+    const getSelectedConfig=()=>{
+        let selected=null;
+        if (config){
+            for (let i = 0; i <config.length ; i++) {
+                let item=config[i];
+                if (item.id===selectedID){
+                    selected=item;
+                    break;
+                }
+            }
+        }
+        return selected;
+    }
+    const onGetPaymentCallback=()=>{
+        navigate(ROUTE_PATH.PAY_ORDER);
+    }
+    const onGetPaymentOder=(data)=>{
+        if (orderStatus===REQ_STATUS.LOADING)return;
+        data.user=user;
+        data.callback=onGetPaymentCallback;
+        dispatch(reqPaymentOrder(data));
+    }
+    const renderFirst=()=>{
+        if (firstpay==null)return (<></>);
+        let price=Number(firstpay.goodsPrice);
+        let give=Number(firstpay.give);
+        let total=price+give;
+        let title=firstpay.goodsName==="firstpay"?i18n.t("deposit.banner.first_title"):i18n.t("deposit.banner.recommend_title");
+        return (
+            <button className={styles.first_pay} onClick={()=>{
+                onGetPaymentOder({
+                    price:firstpay.goodsPrice,
+                    goodsName:firstpay.goodsName,
+                    payType:firstpay.gear.id,
+                    GiftsID:firstpay.GiftsID
+                })
+            }}>
+                <div className={styles.pay_info}>
+                    <div className={styles.title}>{title}</div>
+                    <div className={styles.price_con}>
+                        <div className={styles.total}>{global.DOLLAR+total}</div>
+                        <div className={styles.origin}>
+                            {global.DOLLAR+price}
+                            <div className={styles.ori_line}/>
+                        </div>
+                    </div>
+                    <button className={styles.price_btn}>
+                        {global.DOLLAR+price}
+                    </button>
+                </div>
+                <img className={styles.gift_img} src={fpayimg}/>
+                <div className={styles.percent}>
+                    <img src={img_sc} className={styles.percent}/>
+                    <div className={styles.text}>
+                        {'+'+Math.floor(give*100/price)+'%'}
+                    </div>
+                </div>
+            </button>
+        )
+    }
+    const renderTitle=()=>{
+        return (
+            <div className={styles.title}>{i18n.t("deposit.list.title")}</div>
+        )
+    }
+    const renderBar=()=>{
+        let item=getSelectedConfig();
+        let price=0;
+        let give=0;
+        if (item){
+            price=Number(item.money);
+            give=Number(item.give);
+        }
+        let total=price+give;
+        return (
+            <div className={styles.total_bar}>
+                <div className={styles.left}>
+                    <div className={styles.label}>{global.DOLLAR}</div>
+                    <div>{total}</div>
+                </div>
+                <div className={styles.right}>
+                    <div className={styles.extra}>{i18n.t("deposit.list.extra")}</div>
+                    <div>{"+"+give}</div>
+                </div>
+            </div>
+        )
+    }
+    const renderList=()=>{
+        let list=config;
+        if (list==null)list=[];
+        let selected=getSelectedConfig();
+        let selectedID="";
+        if (selected)selectedID=selected.id;
+        return (
+            <div className={styles.list}>
+                {
+                    list.map((item,index)=>{
+                        let price=Number(item.money);
+                        let give=Number(item.give);
+                        let extra="+"+Math.floor(give*100/price)+'%';
+                        return (
+                            <button key={index} className={`${styles.list_btn} ${selectedID===item.id?styles.active:''}`}
+                                    onClick={()=>{
+                                        setSelectedID(item.id);
+                                    }}
+                            >
+                                <div>{global.DOLLAR}</div>
+                                <div>{item.money}</div>
+                                {
+                                    give>0?(
+                                        <div className={styles.flag}>
+                                            <div className={styles.text}>
+                                                {extra}
+                                            </div>
+                                        </div>
+                                    ):(<></>)
+                                }
+
+                            </button>
+                        )
+                    })
+                }
+            </div>
+        )
+    }
+    const renderDeposits=()=>{
+        return (
+            <div className={styles.list_con}>
+                {renderTitle()}
+                {renderBar()}
+                {renderList()}
+            </div>
+        )
+    }
+    const renderDepositBtn=()=>{
+        return (
+            <button className={"button-green"} onClick={()=>{
+                let payItem=getSelectedConfig();
+                if (payItem==null)return;
+                let gear=payItem.gear!=null?JSON.parse(payItem.gear):{};
+                onGetPaymentOder({
+                    price:payItem.money,
+                    goodsName:"chip",
+                    payType:gear.id,
+                    GiftsID:payItem.gift_id
+                })
+            }}>
+                {orderStatus===REQ_STATUS.LOADING?(<SmallLoading fill={"#fff"}/>):i18n.t("deposit.pay_btn")}
+            </button>
+        )
+    }
+    return (
+        <Spring type="slideUp" className={styles.container}>
+            {renderFirst()}
+            {renderDeposits()}
+            {renderDepositBtn()}
+        </Spring>
+    )
+}
+export default BRDeposit;

+ 194 - 0
src/widgets/WDeposit/BR/styles.module.scss

@@ -0,0 +1,194 @@
+.container{
+  display: flex;
+  flex-direction: column;
+  position: relative;
+  padding: 1rem;
+  width: 100%;
+  gap: 1rem;
+}
+.first_pay{
+  display: flex;
+  flex-direction: column;
+  position: relative;
+  border-radius: 0.44rem;
+  border: 1px solid #346f41;
+  //background-image: linear-gradient(135deg, #faf8de 0%, #f79315 100%);
+  //background-image: linear-gradient(135deg,  #f29e1f 0%, #d0b552 100%);
+  //background-image: linear-gradient(135deg,  #234e33 0%, #346f41 100%);
+  background-image: linear-gradient(135deg,  #1d803ab3 0%, rgba(29, 128, 58, 1) 100%);
+  width: 100%;
+  height: 12rem;
+  & .pay_info{
+    padding: 1.2rem;
+    position: relative;
+    & .title{
+      color: #fff;
+      font-size: 1.2rem;
+      font-weight: 700;
+    }
+    & .price_btn{
+      margin-top: 1rem;
+      border-radius: 3rem;
+      font-size: 1.2rem;
+      font-weight: 600;
+      padding: 0.3rem 2.2rem;
+      color: #fff;
+      background: linear-gradient(0deg, #f17e0a 0%, #faea93 100%);
+      border: 1px solid #f0c461;
+      text-shadow: -1px -1px 0 #987233, 1px -1px 0 #987233, -1px 1px 0 #987233, ;
+    }
+    & .price_con{
+      margin-top: 1rem;
+      width: 50%;
+      height: 3rem;
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      gap: 1rem;
+      & .total{
+        color: #f9f462;
+        font-weight: 700;
+        font-size: 2rem;
+      }
+      & .origin{
+        position: relative;
+        color: #bfbf89;
+        font-size: 1rem;
+        font-weight: 500;
+        align-items: center;
+        & .ori_line{
+          position: absolute;
+          left: -0.5rem;
+          right: -0.5rem;
+          top: 50%;
+          border-top: 1px solid #bfbf89;
+        }
+      }
+    }
+  }
+  & .gift_img{
+    position: absolute;
+    z-index: 2;
+    top: 0;
+    right: 0;
+    width: auto;
+    height: 100%;
+  }
+  & .percent{
+    display: flex;
+    position: absolute;
+    z-index: 3;
+    right: 1rem;
+    top: 1rem;
+    height: 5rem;
+    width: 5rem;
+    align-items: center;
+    justify-content: center;
+    img{
+      position: absolute;
+      z-index: 1;
+      right: 10%;
+      height: 3.5rem;
+      width: auto;
+    }
+    & .text{
+      position: absolute;
+      z-index: 2;
+      color: #f0f786;
+      font-size: 1rem;
+      font-weight: 600;
+    }
+  }
+}
+.list_con{
+  display: flex;
+  flex-direction: column;
+  gap: 1rem;
+  & .title{
+    color: var(--text);
+    font-weight: 600;
+  }
+  & .total_bar{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+    background-color: var(--pay-btn-bg);
+    padding: 0.8rem;
+    border-radius: var(--border-radius);
+    & .left{
+      display: flex;
+      flex-direction: row;
+      font-size: 1.1rem;
+      color: var(--header);
+      font-weight: 500;
+      gap: 0.5rem;
+      & .label{
+        font-weight: 800;
+        color: #edc349;
+      }
+    }
+    & .right{
+      display: flex;
+      flex-direction: row;
+      font-size: 1rem;
+      color: var(--header);
+      font-weight: 500;
+      gap: 0.5rem;
+      & .extra{
+        color: var(--text);
+      }
+    }
+  }
+  & .list{
+    display: grid;
+    gap: 0.5rem;
+    grid-template-columns: repeat(3, minmax(0, 1fr));
+    & .list_btn{
+      position: relative;
+      border-radius: var(--border-radius);
+      background-color: var(--pay-btn-bg);
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      gap: 0.5rem;
+      padding: 0.6rem;
+      font-size: 1rem;
+      font-weight: 500;
+      color: var(--text);
+      overflow: hidden;
+      min-height: 2rem;
+      & .flag{
+        content: '';
+        position: absolute;
+        top: 0;
+        right: 0;
+        border-width: 0 2rem 2rem 0;
+        border-color: transparent rgba(0, 0, 0, 0.2) transparent transparent;
+        border-style: solid;
+        & .text{
+          width: 2rem;
+          height: 2rem;
+          text-align: center;
+          position: absolute;
+          transform: rotate(45deg);
+          font-size: 0.65rem;
+          font-weight: 700;
+          color: var(--text);
+        }
+      }
+      &.active{
+        border: 1px solid var(--primary-color);
+        color: var(--header);
+        font-weight: 700;
+        & .flag{
+          border-color: transparent #1d803a transparent transparent;
+          & .text{
+            font-weight: 800;
+            color: var(--header);
+          }
+        }
+      }
+    }
+  }
+}

+ 53 - 0
src/widgets/WDeposit/DepositHeader.jsx

@@ -0,0 +1,53 @@
+import styles from "./styles.module.scss";
+import SvgIcon from "@components/SvgIcon";
+import {ReactComponent as Video} from '@assets/singlesvg/video.svg';
+import {useSelector} from "react-redux";
+import {getUserInfo} from "@features/mainSlice";
+import USD from "@assets/lvicon/USD.black.png";
+import {numFormatter} from "@utils/helpers";
+const i18n=global.i18n;
+const DepositHeader=({...props})=>{
+    const route=props.route;
+    const close=props.close;
+    const user=useSelector(getUserInfo);
+    const renderHeader=()=>{
+        let title=route?route.title:"";
+        return (
+            <div className={styles.header}>
+                <div className={styles.hcontent}>
+                    {i18n.t(title)}
+                </div>
+                <div className={styles.top}>
+                    <div className={styles.left}>
+                        <button className={styles.close} onClick={()=>{
+                            close();
+                        }}>
+                            <SvgIcon className={styles.arrow} herf={"icon_Arrow"}/>
+                        </button>
+                        <div className={styles.user}>
+                            <div className={styles.uid}>{i18n.t("deposit.uid")+""+user.UserID}</div>
+                            <div className={styles.gold_con}>
+                                <img className={styles.icon_golds} src={USD}/>
+                                <div className={styles.golds}>{global.DOLLAR+""+numFormatter(user.Score)}</div>
+                            </div>
+                        </div>
+                    </div>
+                    <div className={styles.right}>
+                        <button className={styles.right_btn}>
+                            <Video className={styles.icon}/>
+                        </button>
+                        <button className={styles.right_btn}>
+                            <SvgIcon className={styles.icon} herf={"icon_History"}/>
+                        </button>
+                    </div>
+                </div>
+            </div>
+        )
+    }
+    return (
+       <div id={props.id} className={props.className}>
+           {renderHeader()}
+       </div>
+    )
+}
+export default DepositHeader;

+ 10 - 0
src/widgets/WDeposit/index.jsx

@@ -0,0 +1,10 @@
+import styles from './styles.module.scss';
+import BRDeposit from "@widgets/WDeposit/BR/BRDeposit";
+const WDeposit=({close})=>{
+    return (
+        <div className={styles.container}>
+            <BRDeposit/>
+        </div>
+    )
+}
+export default WDeposit;

+ 91 - 0
src/widgets/WDeposit/styles.module.scss

@@ -0,0 +1,91 @@
+.container{
+  width: 100%;
+  min-height: 100%;
+  background-color: var(--widget-bg);
+}
+.header{
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width:100%;
+  background: var(--widget);
+  border-bottom: 1px solid var(--border);
+  box-shadow:var(--widget-shadow);
+  position:relative;
+  height:3.75rem;
+  padding: 0px 10px;
+  & .top{
+    display: flex;
+    align-items: center;
+    position:fixed;
+    justify-content: space-between;
+    left: 10px;
+    right: 10px;
+    & .left{
+      display: flex;
+      align-items: center;
+      gap: 0.25rem;
+      & .close{
+        display: flex;
+        align-items: center;
+        height: 3.75rem;
+        width: 2rem;
+        & .arrow{
+          width: 1.4rem;
+          height: 1.8em;
+          transform: rotate(-180deg);
+          fill: var(--text);
+        }
+      }
+      & .user{
+        display: flex;
+        align-items: flex-start;
+        flex-direction: column;
+        justify-content: center;
+        & .uid{
+          color: var(--text);
+          font-weight: 600;
+        }
+        & .gold_con{
+          display: flex;
+          align-items: center;
+          gap: 0.25rem;
+          & .icon_golds{
+            width: 1rem;
+            height: 1rem;
+          }
+          & .golds{
+            font-size: 0.875rem;
+            font-weight: 600;
+            color: #edc349;
+          }
+        }
+      }
+    }
+    & .right{
+      display: flex;
+      align-items: center;
+      & .right_btn{
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 2.5rem;
+        width: 2.5rem;
+        & .icon{
+          width: 1.4rem;
+          height: 1.4rem;
+          fill: var(--text);
+        }
+      }
+    }
+  }
+  & .hcontent {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex: 1;
+    font-size: 1rem;
+    font-weight: 600;
+    color: var(--header);
+  }
+}

+ 141 - 9
src/widgets/WGame/index.jsx

@@ -1,38 +1,170 @@
 import styles from "./styles.module.scss";
-import {useEffect} from 'react';
+import {useEffect, useState} from 'react';
 import {toast} from "react-toastify";
 import {useNavigate} from "react-router-dom";
+import {useLocation} from "react-use";
+import {localStorageGet, localStorageSet, openFullScreen} from "@utils/helpers";
+import {LOCAL_GAME_URL, LOCAL_SIGN} from "@constants/localkey";
+import {ReactComponent as Boxbg} from '@assets/singlesvg/back/boxbg.svg';
+import {ReactComponent as Boxclose} from '@assets/singlesvg/back/boxclose.svg';
+import {ReactComponent as Circlebg} from '@assets/singlesvg/back/circlebg.svg';
+import {ReactComponent as Circlearrow} from '@assets/singlesvg/back/circlearrow.svg';
+import Fade from "@mui/material/Fade";
+import {ClickAwayListener} from "@mui/base/ClickAwayListener";
+import Grow from "@mui/material/Grow";
+import Modal from "@mui/material/Modal";
+import LoadingScreen from "@components/LoadingScreen";
+import {ROUTE_PATH} from "@constants/routes";
+import {useDispatch} from "react-redux";
+import {reqGameInfo} from "@features/api";
+const i18n=global.i18n;
+
 const WGame=()=>{
+    const dispatch = useDispatch();
+    const {pathname}=useLocation();
+    const gameid=pathname.split("/").pop();
+    const [openBox,setOpenBox]=useState(false);
+    const [openPrompt,setOpenPrompt]=useState(false);
+    const [isGameLoad,setIsGameLoad]=useState(false);
+    var gameURL="";
     const navigate=useNavigate();
+    const onBack=()=>{
+        dispatch(reqGameInfo());
+        navigate(ROUTE_PATH.BACK);
+    }
     const receiveMessage=(event)=>{
         let data=event.data;
         // console.log(data);
         if (data&&data.cmd!=null){
             // toast.success(JSON.stringify(data))
-            if (data.cmd=="back"){
-                navigate(-1)
+            if (data.cmd==="back"){
+                onBack();
+            }
+            else if (data.cmd==="pay"){
+                navigate(ROUTE_PATH.PAY);
+            }
+            else if (data.cmd==="withdraw"){
+                navigate(ROUTE_PATH.SAQUE);
             }
-            else if (data.cmd=="pay"){
-                navigate("#/pay")
+            else if (data.cmd==="fullScreen"){
+                openFullScreen();
             }
         }
     }
+    const parseURL=()=>{
+        let key=LOCAL_GAME_URL+gameid;
+        let sign=localStorageGet(LOCAL_SIGN);
+        let url=localStorageGet(key);
+        if (url==null)return;
+        if (url.indexOf("?")===-1)url=url+"?sign="+sign;
+        else url=url+"&sign="+sign;
+        // setGameURL(url);
+        gameURL=url;
+    }
+    parseURL();
+    const handleLoadGame=()=>{
+        setIsGameLoad(true);
+    }
     useEffect(() => {
+        const gameFrame = document.getElementById('game');
+        if(gameFrame!=null){
+            gameFrame.addEventListener('load', handleLoadGame);
+        }
         window.addEventListener("message", receiveMessage, false);
         return () => {
-            window.removeEventListener("message", receiveMessage)
+            window.removeEventListener("message", receiveMessage);
+            if(gameFrame!=null){
+                gameFrame.removeEventListener('load', handleLoadGame);
+            }
         };
     }, []);
-    return (
-        <div className={styles.container}>
+    const renderBackBox=()=>{
+        return (
+            <div className={`${styles.backbox} ${openBox?styles.open:styles.close}`} onClick={()=>{
+                setOpenBox(!openBox);
+            }}>
+                <button className={styles.back_btn}>
+                    <Circlebg className={styles.back_bg}/>
+                    <Circlearrow className={`${styles.arrow} ${openBox?styles.a_open:styles.a_close}`}/>
+                </button>
+                <button className={styles.close_box} onClick={()=>{
+                    openMsgBox();
+                }}>
+                    <Boxbg className={styles.bg}/>
+                    <div className={styles.close_info}>
+                        <div>{i18n.t("game.back")}</div>
+                        <div className={styles.line}></div>
+                        <Boxclose className={styles.close}></Boxclose>
+                    </div>
+                </button>
+            </div>
+        )
+    }
+    const renderGame=()=>{
+        return (
             <iframe
+                id={"game"}
                 title={"game"}
-                src="http://192.168.1.5:7456/build/?time=123456789"
+                src={gameURL}
                 // src={"https://j15.gamej15.top/pwa.html"}
                 className={styles.content}
+                allow="fullscreen"
                 sandbox='allow-same-origin allow-scripts allow-popups allow-forms'
             >
             </iframe>
+        )
+    }
+    const closeMsgBox=()=>{
+        setOpenPrompt(false);
+    }
+    const openMsgBox=()=>{
+        setOpenPrompt(true);
+    }
+    const renderMsgBox=()=>{
+        return (
+            <Modal open={openPrompt} onClose={closeMsgBox} closeAfterTransition>
+                <Fade in={openPrompt} timeout={500}>
+                    <div className="popup-container">
+                        <ClickAwayListener onClickAway={closeMsgBox}>
+                            <Grow in={openPrompt} timeout={500}>
+                                <div className={`popup card card-padded ${styles.msg_box}`}>
+                                    <div className={styles.msg_content}>
+                                        <div className={styles.title}>{i18n.t("game.msg_title")}</div>
+                                        <div className={styles.content}>{i18n.t("game.msg_content")}</div>
+                                        <div className={styles.msg_btn}>
+                                            <button className={"button-gray"} onClick={closeMsgBox}>
+                                                {i18n.t("game.cancel")}
+                                            </button>
+                                            <button className={"button-green"} onClick={()=>{
+                                                onBack();
+                                                closeMsgBox();
+                                            }}>
+                                                {i18n.t("game.back")}
+                                            </button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </Grow>
+                        </ClickAwayListener>
+                    </div>
+                </Fade>
+            </Modal>
+        )
+    }
+    const renderLoading=()=>{
+        if (isGameLoad)return(<></>);
+        return (
+            <div className={styles.loading}>
+                <LoadingScreen/>
+            </div>
+        )
+    }
+    return (
+        <div className={styles.container}>
+            {renderGame()}
+            {renderBackBox()}
+            {renderMsgBox()}
+            {renderLoading()}
         </div>
     )
 }

+ 119 - 0
src/widgets/WGame/styles.module.scss

@@ -7,4 +7,123 @@
     border: none;
     //flex: none;
   }
+  & .backbox{
+    display: flex;
+    position: fixed;
+    top: 2.5rem;
+    right: -14.5rem;
+    width: 17.6875rem;
+    height: 3.2rem;
+    z-index: var(--zindex-second);
+    overflow: hidden;
+    &.open{
+      transition: all .3s;
+      transform: translate(-7.875rem);
+    }
+    &.close{
+      transition: all .3s;
+      transform: translate(0);
+    }
+    & .back_btn{
+      display: flex;
+      position: relative;
+      align-items: center;
+      justify-content: center;
+      z-index: 2;
+      width: 3.1rem;
+      height: 3.1rem;
+      & .back_bg{
+        width: 100%;
+        height: auto;
+      }
+      & .arrow{
+        position: absolute;
+        width: 25%;
+        height: auto;
+        top: .88rem;
+        left: 1.1rem;
+        &.a_open{
+          transition: all .3s;
+          transform: rotate(180deg);
+        }
+        &.a_close{
+          transition: all .3s;
+          transform: rotate(0);
+        }
+      }
+    }
+    & .close_box{
+      display: flex;
+      position: relative;
+      align-items: center;
+      justify-content: center;
+      z-index: 1;
+      width: 9.5rem;
+      margin-top: 2rem;
+      margin-left: -1.2rem;
+      & .bg{
+        width: 100%;
+      }
+      & .close_info{
+        position: absolute;
+        left: 2rem;
+        right: 1.3rem;
+        top: -0.3rem;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        color: #fff;
+      }
+      & .line{
+        transform: rotate(-72deg);
+        opacity: .3;
+        background-color: #fff;
+        width: 1.25rem;
+        height: .0625rem;
+      }
+      & .close{
+        width: 1.2rem;
+        height: 1.2rem;
+      }
+    }
+  }
+}
+.msg_box{
+  width: 90%;
+  & .msg_content{
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    color: var(--header);
+    gap: 0.5rem;
+    & .title{
+      font-size: 1.2rem;
+    }
+    & .content{
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 1rem;
+      width: 100%;
+      height: 5rem;
+      text-align: center;
+      word-wrap: break-word;
+      word-break: break-all;
+      text-align: center;
+    }
+    & .msg_btn{
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      width: 100%;
+      gap: 2rem;
+    }
+  }
+}
+.loading{
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
 }

+ 154 - 0
src/widgets/WPaymentOrder/BR/BRPayOrder.jsx

@@ -0,0 +1,154 @@
+import styles from "./styles.module.scss";
+import Spring from "@components/Spring";
+import React, {useEffect, useState} from "react";
+import {useNavigate} from "react-router-dom";
+import {useSelector} from "react-redux";
+import {getUserInfo} from "@features/mainSlice";
+import {getCurrPayOrder} from "@features/paySlice";
+import {ReactComponent as PixLogo} from '@assets/singlesvg/pix.svg';
+import {formatDate, formatTime, stringFormat} from "@utils/helpers";
+import SvgIcon from "@components/SvgIcon";
+import {CopyToClipboard} from "react-copy-to-clipboard";
+import {toast} from "react-toastify";
+import QRCode from 'qrcode.react';
+const i18n=global.i18n;
+const BRPayOrder=()=>{
+    const navigate=useNavigate();
+    const user=useSelector(getUserInfo);
+    const orderInfo=useSelector(getCurrPayOrder);
+    const [leftTime,setLeftTime]=useState(0);
+    const getLeftTime=()=>{
+        if (orderInfo==null)return 0;
+        let deadline=Number(orderInfo.deadline);
+        let createAt=Number(orderInfo.createAt);
+        let expireAt=createAt+deadline*1000;
+        let now=Date.now();
+        let left=expireAt-now;
+        if (left<0)left=0;
+        return left;
+    }
+    const updateLeftTime=(timer)=>{
+        let left=getLeftTime();
+        setLeftTime(left);
+        if (left<=0){
+            clearInterval(timer);
+            timer=null;
+        }
+        return timer;
+    }
+    useEffect(()=>{
+        let timer=null;
+        if (orderInfo){
+            setLeftTime(getLeftTime());
+            timer=setInterval(()=>{
+                timer=updateLeftTime(timer);
+            },1000)
+        }
+        return () => {
+            if (timer!=null){
+                clearInterval(timer);
+                timer=null;
+            }
+        };
+    },[orderInfo])
+
+    const renderTitle=()=>{
+        return (
+            <div className={styles.title}>
+                <PixLogo className={styles.logo}/>
+                {i18n.t("deposit.order_info.pay_type_pix")}
+            </div>
+        )
+    }
+    const renderBasic=()=>{
+        let deadline=Number(orderInfo.deadline);
+        let createAt=Number(orderInfo.createAt);
+        let expireAt=createAt+deadline*1000;
+        return (
+            <>
+                <div className={styles.tips}>
+                    {stringFormat(i18n.t("deposit.order_info.tips"),[formatDate(expireAt)])}
+                </div>
+                <div className={styles.base_info}>
+                    <div className={styles.info_row}>
+                        <div className={styles.label}>
+                            {i18n.t("deposit.order_info.create_date")}
+                        </div>
+                        {formatDate(createAt)}
+                    </div>
+                    {/*<div className={styles.line}></div>*/}
+                    <div className={styles.info_row}>
+                        <div className={styles.label}>
+                            {i18n.t("deposit.order_info.time")}
+                        </div>
+                        {formatTime(leftTime,true)}
+                    </div>
+                    {/*<div className={styles.line}></div>*/}
+                    <CopyToClipboard text={orderInfo.prdOrdNo} onCopy={()=>{
+                        toast.success(i18n.t("copy_success"));
+                    }}>
+                        <div className={styles.info_row}>
+                            <div className={styles.label}>
+                                {i18n.t("deposit.order_info.order")}
+                            </div>
+                            <div className={styles.order}>
+                                {orderInfo.prdOrdNo}
+                                <SvgIcon className={styles.logo} herf={"icon_Copy"}/>
+                            </div>
+                        </div>
+                    </CopyToClipboard>
+                    <div className={styles.info_row}>
+                        <div className={styles.label}>
+                            {i18n.t("deposit.order_info.value")}
+                        </div>
+                        <div className={styles.money}>
+                            {global.DOLLAR+orderInfo.money}
+                        </div>
+                    </div>
+                </div>
+            </>
+        )
+    }
+    const renderPayInfo=()=>{
+        return (
+            <div className={styles.pay_info}>
+                <div className={styles.pay_label}>{i18n.t("deposit.order_info.content")}</div>
+                <div className={styles.pay_content}>{orderInfo.content}</div>
+                <QRCode className={styles.pay_qr} value={orderInfo.content} />
+                <div className={styles.pay_btn}>
+                    <CopyToClipboard text={orderInfo.content} onCopy={()=>{
+                        toast.success(i18n.t("deposit.order_info.tips1"));
+                    }}>
+                        <button className={"button-green"}>
+                            {i18n.t("deposit.order_info.copyButton")}
+                        </button>
+                    </CopyToClipboard>
+                    <button className={styles.btn_already}>
+                        {i18n.t("deposit.order_info.lookButton")}
+                    </button>
+                </div>
+            </div>
+        )
+    }
+    const renderOrderInfo=()=>{
+        return (
+            <div className={styles.order_info}>
+                {renderBasic()}
+                {renderPayInfo()}
+            </div>
+        )
+    }
+    return (
+        <>
+            {
+                orderInfo!=null?(
+                    <Spring type="slideUp" className={styles.container}>
+                        {renderTitle()}
+                        {renderOrderInfo()}
+                    </Spring>
+                ):(<></>)
+            }
+        </>
+    )
+}
+export default BRPayOrder;

+ 114 - 0
src/widgets/WPaymentOrder/BR/styles.module.scss

@@ -0,0 +1,114 @@
+.container{
+  display: flex;
+  flex-direction: column;
+  position: relative;
+  padding: 1rem;
+  width: 100%;
+  gap: 0.5rem;
+}
+.title{
+  display: flex;
+  width: 100%;
+  gap: 0.5rem;
+  color: var(--text);
+  font-size: 1rem;
+  font-weight: 600;
+  & .logo{
+    width: 1.4rem;
+    height: 1.4rem;
+    fill: #37b4aa;
+  }
+}
+.order_info{
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  gap: 0.5rem;
+  & .tips{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    width: 100%;
+    color: var(--text);
+    gap: 0.5rem;
+    //font-size: 0.7rem;
+  }
+  & .base_info{
+    display: flex;
+    flex-direction: column;
+    border-radius: var(--border-radius);
+    padding: 1rem;
+    background: var(--card-bg);
+    gap: 0.8rem;
+  }
+  & .info_row{
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: var(--text);
+    & .label{
+      color: var(--header);
+    }
+    & .logo{
+      width: 1.4rem;
+      height: 1.4rem;
+      fill: var(--text);
+    }
+    & .order{
+      display: flex;
+      align-items: center;
+      gap: 0.2rem;
+      user-select: text;
+    }
+    & .money{
+      font-size: 1.1rem;
+      font-weight: 600;
+      color: #edc349;
+    }
+  }
+  & .pay_info{
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    border-radius: var(--border-radius);
+    padding: 1rem;
+    background: var(--card-bg);
+    gap: 1rem;
+    color: var(--header);
+    & .pay_label{
+      font-size: 1rem;
+      color: var(--header);
+    }
+    & .pay_content{
+      word-wrap: break-word;
+      word-break: break-all;
+      text-align: center;
+      //opacity: 0.75;
+      color: var(--text);
+      user-select: text;
+    }
+    & .pay_qr{
+      width: 60% !important;
+      height: 60% !important;
+      border: 2px solid #fff;
+    }
+    & .pay_btn{
+      display: flex;
+      flex-direction: column;
+      //justify-content: space-between;
+      align-items: center;
+      width: 100%;
+      gap: 0.5rem;
+      margin-top: 1rem;
+      margin-bottom: 0.5rem;
+      & .btn_already{
+        color: var(--text);
+        min-height: 1.5rem;
+      }
+    }
+  }
+}
+.line{
+  border-top: 1px solid var(--card-line);
+}

+ 10 - 0
src/widgets/WPaymentOrder/index.jsx

@@ -0,0 +1,10 @@
+import styles from './styles.module.scss';
+import BRPayOrder from "@widgets/WPaymentOrder/BR/BRPayOrder";
+const WPaymentOrder=({close})=>{
+    return (
+        <div className={styles.container}>
+            <BRPayOrder></BRPayOrder>
+        </div>
+    )
+}
+export default WPaymentOrder;

+ 5 - 0
src/widgets/WPaymentOrder/styles.module.scss

@@ -0,0 +1,5 @@
+.container{
+  width: 100%;
+  min-height: 100%;
+  background-color: var(--widget-bg);
+}

部分文件因文件數量過多而無法顯示