zhejiushizhuce před 1 rokem
rodič
revize
ede396be22

+ 5 - 3
src/App.js

@@ -80,6 +80,8 @@ import {isInAppBrowser, isShowInstallBox, openUrlUseChrome} from "@utils/UAUtils
 import WInstallBox from "@widgets/WInstallBox";
 import WMaintainBox from "@widgets/WMaintainBox";
 import WAreaSelect from "@widgets/WAreaSelect";
+import WDownBox from "@widgets/WInstallBox/WDownBox";
+import WShortcutGuide from "@widgets/WInstallBox/WShortcutGuide";
 const objInfo={
     gameID:0
 }
@@ -441,9 +443,9 @@ const App = () => {
         if (isSelectArea)return (<></>);
         return (
             <>
-                {
-                    <WInstallBox/>
-                }
+                {<WInstallBox/>}
+                {<WDownBox/>}
+                {<WShortcutGuide/>}
             </>
         )
     }

+ 13 - 0
src/Global.js

@@ -198,4 +198,17 @@ global.getUrlvars=()=>{
     return localStorageGet("urlvars", "");
 }
 
+global.showDownBox=()=>{
+    if (global.downloadBox)global.downloadBox.show();
+}
+global.hideDownBox=()=>{
+    if (global.downloadBox)global.downloadBox.hide();
+}
+global.showShortcutGuide=()=>{
+    if (global.shortcutGuide)global.shortcutGuide.show();
+}
+global.hideShortcutGuide=()=>{
+    if (global.shortcutGuide)global.shortcutGuide.hide();
+}
+
 //wd pass

+ 2 - 2
src/api/request.js

@@ -203,9 +203,9 @@ const buildQuery=(param)=>{
 
     return param;
 }
-const getAPKUrl=()=>{
+const getAPKUrl=(apkUrl=null)=>{
     let params=getComParams();
-    let url=BASE_API+APP_GAME_APK;
+    let url=apkUrl==null?BASE_API+APP_GAME_APK:apkUrl;
     if (!window.location.host.includes("localhost")){
         url+="?lz="+LZString.compressToBase64(JSON.stringify(params));
     }

binární
src/assets/shortcut/img_android_jc_1.avif


binární
src/assets/shortcut/img_android_jc_2_zh.avif


binární
src/assets/shortcut/img_ios_jc_1.avif


binární
src/assets/shortcut/img_ios_jc_2_zh.avif


binární
src/assets/shortcut/pointer.avif


+ 4 - 0
src/assets/singlesvg/close-circle.svg

@@ -0,0 +1,4 @@
+<?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 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
+    <path d="M16 0c-8.836 0-16 7.163-16 16s7.163 16 16 16c8.837 0 16-7.163 16-16s-7.163-16-16-16zM16 30.032c-7.72 0-14-6.312-14-14.032s6.28-14 14-14 14 6.28 14 14-6.28 14.032-14 14.032zM21.657 10.344c-0.39-0.39-1.023-0.39-1.414 0l-4.242 4.242-4.242-4.242c-0.39-0.39-1.024-0.39-1.415 0s-0.39 1.024 0 1.414l4.242 4.242-4.242 4.242c-0.39 0.39-0.39 1.024 0 1.414s1.024 0.39 1.415 0l4.242-4.242 4.242 4.242c0.39 0.39 1.023 0.39 1.414 0s0.39-1.024 0-1.414l-4.242-4.242 4.242-4.242c0.391-0.391 0.391-1.024 0-1.414z"></path>
+</svg>

+ 9 - 2
src/features/mainSlice.js

@@ -262,6 +262,7 @@ const reducerRoutes=(state,action)=>{
         let bbConf=null;
         let popFirst=0;
         let showInstall=0;
+        let download= {};
         if (conf){
             if (!!conf.hall)hallServerUrl=conf.hall;
             if (!!conf.DOLLAR)global.DOLLAR=conf.DOLLAR;
@@ -294,10 +295,12 @@ const reducerRoutes=(state,action)=>{
             if (!!conf.registerOpen)registerOpen=conf.registerOpen;
             if (!!conf.popFirst)popFirst=conf.popFirst;
             if (!!conf.showInstall)showInstall=conf.showInstall;
+            //download 配置
+            if (!!conf.download)download=conf.download;
         }
         //favorites
         // let favorites=getFavorites(json.favorites);
-        Object.assign(state, {routes:state.routes,asyncRoutes:data,styles,blocks,...generData,isLogin:isLogin,userInfo,hallServerUrl,promoteInstall,guest,upgradeBonus,popWheel,popBindPhone,firstBonus,openRelief,bbConf,accountLogin,area,loginOpen,registerOpen,popFirst,showInstall});
+        Object.assign(state, {routes:state.routes,asyncRoutes:data,styles,blocks,...generData,isLogin:isLogin,userInfo,hallServerUrl,promoteInstall,guest,upgradeBonus,popWheel,popBindPhone,firstBonus,openRelief,bbConf,accountLogin,area,loginOpen,registerOpen,popFirst,showInstall,download});
         // Object.assign(state, {routes:state.routes,asyncRoutes:data,styles:styles,blocks:blocks,...generData,isLogin:isLogin,userInfo:userInfo,hallServerUrl:hallServerUrl,promoteInstall:promoteInstall,guest:guest,upgradeBonus:upgradeBonus});
     }
 }
@@ -639,7 +642,8 @@ export const Main=createSlice({
         loginOpen:"",
         registerOpen:"",
         popFirst:0,
-        showInstall:0
+        showInstall:0,
+        download:{}
     },
     reducers: {
         logout:(state, action)=>{
@@ -992,6 +996,9 @@ export const getPopFirst=(state)=>{
 export const getShowInstall=(state)=>{
     return state.main.showInstall;
 }
+export const getDownloadConf=(state)=>{
+    return state.main.download;
+}
 //数据获取
 export default Main.reducer;
 

+ 22 - 1
src/locales/languages/en_US.json

@@ -743,7 +743,28 @@
   "installBox": {
     "tips": "We would love to add 24680.com to your home screen for the latest free bets and bonus updates.",
     "btn_cancel": "Cancel",
-    "btn_install": "Install"
+    "btn_install": "Install",
+    "tips_1": "Download and use the APP to receive {0} and enjoy",
+    "btn_downnow": "Download Now",
+    "down_type_1": "Web App",
+    "down_type_2": "Fast App",
+    "down_type_3": "Deluxe App",
+    "shortcut": {
+      "title": "Add to Home Screen",
+      "sub_1": "1. Tap the \"More\" icon, then tap Add to Home Screen",
+      "sub_2": "2. Click Add and select “Add”",
+      "ios_op_1": "Add to quick memo",
+      "ios_op_2": "Find on page",
+      "ios_op_3": "Add to Home Screen",
+      "ios_op_4": "Marker",
+      "cancel": "Cancel",
+      "add": "To add",
+      "tips_1": "An icon will be added to your home screen to quickly access this website.",
+      "android_op_1": "Share...",
+      "android_op_2": "Search the web page",
+      "android_op_3": "Add to Home Screen",
+      "android_op_4": "Computer website"
+    }
   },
   "bindPhone": {
     "title_link_phone": "Account Upgrade",

+ 23 - 2
src/locales/languages/es_MX.json

@@ -728,9 +728,30 @@
     "disconnected": "La red se ha desconectado. ¿Quieres volver a conectarte?"
   },
   "installBox": {
-    "tips": "Nos encantaría añadir 24680.com a tu pantalla de inicio para las últimas apuestas gratuitas y actualizaciones de bonos.",
+    "tips": "Nos encantaría agregar 24680.com a tu pantalla de inicio para las últimas actualizaciones de apuestas gratuitas y bonos.",
     "btn_cancel": "Cancelar",
-    "btn_install": "Instalar"
+    "btn_install": "Instalar",
+    "tips_1": "Descarga y usa la APP para recibir {0} y disfrutar",
+    "btn_downnow": "Descargar Ahora",
+    "down_type_1": "Aplicación Web",
+    "down_type_2": "Aplicación Rápida",
+    "down_type_3": "Aplicación Deluxe",
+    "shortcut": {
+      "title": "Agregar a la pantalla de inicio",
+      "sub_1": "1. Toca el ícono \"Más\" y luego toca Agregar a la Pantalla de Inicio",
+      "sub_2": "2. Haz clic en Agregar y selecciona “Agregar”",
+      "ios_op_1": "Agregar a nota rápida",
+      "ios_op_2": "Buscar en la página",
+      "ios_op_3": "Agregar a la Pantalla de Inicio",
+      "ios_op_4": "Marcador",
+      "cancel": "Cancelar",
+      "add": "Agregar",
+      "tips_1": "Se agregará un ícono a tu pantalla de inicio para acceder rápidamente a este sitio web.",
+      "android_op_1": "Compartir...",
+      "android_op_2": "Buscar en la página web",
+      "android_op_3": "Agregar a la Pantalla de Inicio",
+      "android_op_4": "Sitio web de computadora"
+    }
   },
   "bindPhone": {
     "title_link_phone": "Actualización de la Cuenta",

+ 23 - 2
src/locales/languages/pt_BR.json

@@ -728,9 +728,30 @@
     "disconnected": "A rede foi desconectada. Deseja reconectar?"
   },
   "installBox": {
-    "tips": "Adoraríamos adicionar 24680.com à sua tela inicial para as últimas apostas gratuitas e atualizações de bônus.",
+    "tips": "Adoraríamos adicionar 24680.com à sua tela inicial para as últimas atualizações de apostas gratuitas e bônus.",
     "btn_cancel": "Cancelar",
-    "btn_install": "Instalar"
+    "btn_install": "Instalar",
+    "tips_1": "Baixe e use o APP para receber {0} e aproveitar",
+    "btn_downnow": "Baixar Agora",
+    "down_type_1": "Aplicativo Web",
+    "down_type_2": "Aplicativo Rápido",
+    "down_type_3": "Aplicativo Deluxe",
+    "shortcut": {
+      "title": "Adicionar à Tela Inicial",
+      "sub_1": "1. Toque no ícone \"Mais\" e depois em Adicionar à Tela Inicial",
+      "sub_2": "2. Clique em Adicionar e selecione “Adicionar”",
+      "ios_op_1": "Adicionar ao memorando rápido",
+      "ios_op_2": "Encontrar na página",
+      "ios_op_3": "Adicionar à Tela Inicial",
+      "ios_op_4": "Marcador",
+      "cancel": "Cancelar",
+      "add": "Adicionar",
+      "tips_1": "Um ícone será adicionado à sua tela inicial para acessar rapidamente este site.",
+      "android_op_1": "Compartilhar...",
+      "android_op_2": "Pesquisar na página da web",
+      "android_op_3": "Adicionar à Tela Inicial",
+      "android_op_4": "Site de computador"
+    }
   },
   "bindPhone": {
     "title_link_phone": "Atualização da Conta",

+ 23 - 2
src/locales/languages/ru_RU.json

@@ -728,9 +728,30 @@
     "disconnected": "Соединение прервано. Хотите восстановить?"
   },
   "installBox": {
-    "tips": "Мы бы хотели добавить 24680.com на ваш рабочий стол для последних бесплатных ставок и обновлений бонусов.",
+    "tips": "Мы хотели бы добавить 24680.com на ваш домашний экран для получения последних обновлений о бесплатных ставках и бонусах.",
     "btn_cancel": "Отмена",
-    "btn_install": "Установить"
+    "btn_install": "Установить",
+    "tips_1": "Скачайте и используйте приложение, чтобы получить {0} и наслаждаться",
+    "btn_downnow": "Скачать Сейчас",
+    "down_type_1": "Веб-приложение",
+    "down_type_2": "Быстрое приложение",
+    "down_type_3": "Deluxe приложение",
+    "shortcut": {
+      "title": "Добавить на Домашний Экран",
+      "sub_1": "1. Нажмите значок \"Еще\", затем нажмите Добавить на Домашний Экран",
+      "sub_2": "2. Нажмите Добавить и выберите “Добавить”",
+      "ios_op_1": "Добавить в быструю заметку",
+      "ios_op_2": "Найти на странице",
+      "ios_op_3": "Добавить на Домашний Экран",
+      "ios_op_4": "Маркер",
+      "cancel": "Отмена",
+      "add": "Добавить",
+      "tips_1": "На ваш домашний экран будет добавлен значок для быстрого доступа к этому сайту.",
+      "android_op_1": "Поделиться...",
+      "android_op_2": "Искать на веб-странице",
+      "android_op_3": "Добавить на Домашний Экран",
+      "android_op_4": "Сайт для компьютера"
+    }
   },
   "bindPhone": {
     "title_link_phone": "Повышение учетной записи",

+ 22 - 1
src/locales/languages/zh_TW.json

@@ -730,7 +730,28 @@
   "installBox": {
     "tips": "我們希望將 24680.com 添加到您的主屏幕,以獲取最新的免費投注和獎金更新。",
     "btn_cancel": "取消",
-    "btn_install": "安裝"
+    "btn_install": "安裝",
+    "tips_1": "下載並使用 APP 以接收 {0} 並享受",
+    "btn_downnow": "立即下載",
+    "down_type_1": "網頁應用",
+    "down_type_2": "快速應用",
+    "down_type_3": "豪華應用",
+    "shortcut": {
+      "title": "添加到主屏幕",
+      "sub_1": "1. 點擊“更多”圖標,然後點擊添加到主屏幕",
+      "sub_2": "2. 點擊添加並選擇“添加”",
+      "ios_op_1": "添加到快速備忘錄",
+      "ios_op_2": "在頁面中查找",
+      "ios_op_3": "添加到主屏幕",
+      "ios_op_4": "標記",
+      "cancel": "取消",
+      "add": "添加",
+      "tips_1": "一個圖標將添加到您的主屏幕,以便快速訪問此網站。",
+      "android_op_1": "分享...",
+      "android_op_2": "搜索網頁",
+      "android_op_3": "添加到主屏幕",
+      "android_op_4": "電腦網站"
+    }
   },
   "bindPhone": {
     "title_link_phone": "帳戶升級",

+ 158 - 0
src/widgets/WInstallBox/WDownBox/index.jsx

@@ -0,0 +1,158 @@
+import {useEffect, useState} from "react";
+import Fade from "@mui/material/Fade";
+import Grow from "@mui/material/Grow";
+import styles from "./styles.module.scss";
+import Modal from "@mui/material/Modal";
+import {useSelector} from "react-redux";
+import {getDownloadConf} from "@features/mainSlice";
+import {stringFormat} from "@utils/helpers";
+import {ReactComponent as CloseIcon} from "@assets/singlesvg/close-circle.svg";
+import Http from "@api/request";
+import {useThemeProvider} from "@contexts/themeContext";
+import {openProgressierInstall} from "@utils/UAUtils";
+const i18n=global.i18n;
+const objInfo={
+    count:0,
+    timer:null
+}
+const WDownBox = () => {
+    const [isShow, setIsShow] = useState(false);
+    const [iconUrl, setIconUrl] = useState("");
+    const downloadConf= useSelector(getDownloadConf);
+    const {isMobile} = useThemeProvider();
+    const show=()=>{
+        setIsShow(true);
+    }
+    const hide=()=>{
+        setIsShow(false);
+    }
+    const clearTimer=()=>{
+        if (objInfo.timer!=null){
+            clearInterval(objInfo.timer);
+            objInfo.timer=null;
+            objInfo.count=0;
+        }
+    }
+    const getTips=()=>{
+        let bonus=0;
+        if(downloadConf!=null&&downloadConf.bonus!=null){
+            bonus=Number(downloadConf.bonus)
+        }
+        return stringFormat(i18n.t("installBox.tips_1"),[global.DOLLAR+" "+bonus]);
+    }
+    const openShotcut=()=>{
+        if(isMobile()){
+            global.showShortcutGuide();
+            setIsShow(false);
+        }
+        else
+        {
+            openProgressierInstall();
+            setIsShow(false);
+        }
+    }
+    const downFast=()=>{
+        let light=downloadConf.light;
+        if (light==null)return;
+        let apkUrl=Http.getAPKUrl(light);
+        window.open(apkUrl);
+        setIsShow(false);
+    }
+    const downFull=()=>{
+        let full=downloadConf.full;
+        if (full==null)return;
+        let apkUrl=Http.getAPKUrl(full);
+        window.open(apkUrl);
+        setIsShow(false);
+    }
+    useEffect(()=>{
+        const downloadBox={
+            show,
+            hide
+        };
+        global.downloadBox=downloadBox;
+        if (window.progressier!=null){
+            let iconUrl="";
+            let initIconUrl=()=>{
+                if (window.progressier.data!=null){
+                    let params=window.progressier.data.params;
+                    if (params!=null){
+                        // setIconUrl(params.icon180);
+                        iconUrl=params.icon180;
+                    }
+                }
+            }
+            clearTimer();
+            if (iconUrl==null||iconUrl===""){
+                objInfo.timer=setInterval(()=>{
+                    if (objInfo.count>=10){
+                        clearTimer();
+                        return;
+                    }
+                    initIconUrl();
+                    if (iconUrl!=null&&iconUrl!==""){
+                        setIconUrl(iconUrl);
+                        clearTimer();
+                    }
+                    objInfo.count++;
+                },200);
+            }
+            else
+            {
+                setIconUrl(iconUrl);
+            }
+        }
+        return ()=>{
+            clearTimer();
+        }
+    },[])
+    const renderDownBox=()=>{
+        return (
+            <>
+                <div className={styles.continer}>
+                    <div className={styles.install_con}>
+                        <img src={iconUrl}/>
+                        {/*<span>{i18n.t("installBox.tips")}</span>*/}
+                        <span>{getTips()}</span>
+                    </div>
+                    <div className={styles.install_btn_con}>
+                        <button className={styles.install_btn} onClick={openShotcut}>
+                            <span>{i18n.t("installBox.down_type_1")}</span>
+                        </button>
+                        <button className={styles.install_btn} onClick={downFast}>
+                            <span>{i18n.t("installBox.down_type_2")}</span>
+                        </button>
+                    </div>
+                    <div className={`${styles.install_btn_con} ${styles.install_btn_con_full}`}>
+                        <button className={`${styles.install_btn} ${styles.btn_green}`} onClick={downFull}>
+                            <span>{i18n.t("installBox.down_type_3")}</span>
+                        </button>
+                    </div>
+                </div>
+            </>
+        )
+    }
+    return (
+        <>
+            <Modal open={isShow} onClose={() => {
+                hide();
+            }} closeAfterTransition>
+            <Fade in={isShow} timeout={500}>
+                    <div className="popup-container">
+                        <Grow in={isShow} timeout={500}>
+                            <div className={styles.popup_con}>
+                                <div className={styles.pop_con}>
+                                    {renderDownBox()}
+                                </div>
+                                <button className={styles.pop_close_btn} onClick={hide}>
+                                    <CloseIcon className={styles.icon}></CloseIcon>
+                                </button>
+                            </div>
+                        </Grow>
+                    </div>
+                </Fade>
+            </Modal>
+        </>
+    )
+}
+export default WDownBox;

+ 80 - 0
src/widgets/WInstallBox/WDownBox/styles.module.scss

@@ -0,0 +1,80 @@
+.popup_con{
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+}
+.pop_close_btn{
+  margin-top: 1.2rem;
+  width: 100%;
+  pointer-events: auto;
+  & .icon{
+    path{
+      stroke: #FFFFFF;
+    }
+    fill:#FFFFFF;
+    width: 2.2rem;
+    height: 2.2rem;
+  }
+}
+.pop_con{
+  display: flex;
+  padding: 1.2rem 0.8rem;
+  border-radius: 0.71rem;
+  background-color: #fff;
+  width: 100%;
+  max-width: 25.875rem;
+  pointer-events: auto;
+}
+.continer{
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  gap: 0.9rem;
+  & .install_con{
+    display: flex;
+    flex-direction: row;
+    gap: 0.8rem;
+    font-size: 0.99rem;
+    line-height: 1.42rem;
+    color: var(--text-light);
+    align-items: center;
+    img{
+      width: 4.26rem;
+      height: 4.26rem;
+      border-radius: 0.71rem;
+    }
+  }
+  & .install_btn_con{
+    display: grid;
+    width: 100%;
+    font-size: 0.85rem;
+    gap: 0.7rem;
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+    &_full{
+      grid-template-columns: repeat(1, minmax(0, 1fr));
+    }
+    & .install_btn{
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      padding: 0.5rem;
+      //border: 2px solid #59c055;
+      color: #59c055;
+      border: 1.5px solid #59c055;
+      border-radius: 0.5rem;
+      width: 100%;
+      min-height: 2.6rem;
+      font-weight: 600;
+    }
+    & .btn_green{
+      color: #fff;
+      //background: var(--accent);
+      border: none;
+      background-color: #15ab37;
+      //background-image: conic-gradient(from 1turn, rgba(88, 175, 16, 1), rgba(29, 128, 58, 1));
+    }
+  }
+}

+ 232 - 0
src/widgets/WInstallBox/WShortcutGuide/index.jsx

@@ -0,0 +1,232 @@
+import {useEffect, useState} from "react";
+import {isAndroid} from "@utils/helpers";
+import MuiDrawer from "@mui/material/Drawer";
+import styles from "./styles.module.scss";
+import img_hand from "@assets/shortcut/pointer.avif"
+
+const i18n=global.i18n;
+
+const objInfo={
+    count:0,
+    timer:null
+}
+
+const WShortcutGuide = () => {
+    const [isShow, setIsShow] = useState(false);
+    const [iconUrl, setIconUrl] = useState("");
+    const show=()=>{
+        setIsShow(true);
+    }
+    const hide=()=>{
+        setIsShow(false);
+    }
+    const clearTimer=()=>{
+        if (objInfo.timer!=null){
+            clearInterval(objInfo.timer);
+            objInfo.timer=null;
+            objInfo.count=0;
+        }
+    }
+    useEffect(()=>{
+        const shortcutGuide={
+            show,
+            hide
+        };
+        global.shortcutGuide=shortcutGuide;
+        if (window.progressier!=null){
+            let iconUrl="";
+            let initIconUrl=()=>{
+                if (window.progressier.data!=null){
+                    let params=window.progressier.data.params;
+                    if (params!=null){
+                        // setIconUrl(params.icon180);
+                        iconUrl=params.icon180;
+                    }
+                }
+            }
+            clearTimer();
+            if (iconUrl==null||iconUrl===""){
+                objInfo.timer=setInterval(()=>{
+                    if (objInfo.count>=10){
+                        clearTimer();
+                        return;
+                    }
+                    initIconUrl();
+                    if (iconUrl!=null&&iconUrl!==""){
+                        setIconUrl(iconUrl);
+                        clearTimer();
+                    }
+                    objInfo.count++;
+                },200);
+            }
+            else
+            {
+                setIconUrl(iconUrl);
+            }
+        }
+        return ()=>{
+            clearTimer();
+        }
+    },[])
+    const getMainDomain=()=>{
+        // 获取完整的域名
+        const fullDomain = window.location.hostname;
+
+        // 将域名分割成部分
+        const parts = fullDomain.split('.');
+
+        // 如果域名部分少于2个,直接返回完整域名
+        if (parts.length <= 2) {
+            return parts[0]; // 返回第一个部分(如 localhost)
+        }
+
+        // 提取主域名并去除后缀(最后一部分)
+        return parts.slice(-2, -1).join('');
+    }
+    const renderAndroidContent=()=>{
+        let mainDomain = getMainDomain();
+        if(mainDomain!=null)mainDomain=mainDomain.toUpperCase();
+        return (
+            <div className={styles.container}>
+                <div className={styles.header}>
+                    <span className={styles.title}>
+                        {i18n.t("installBox.shortcut.title")}
+                    </span>
+                </div>
+                <div className={styles.content}>
+                    <span className={styles.sub_title}>{i18n.t("installBox.shortcut.sub_1")}</span>
+                    <div className={styles.android_op_1}>
+                        <span>{i18n.t("installBox.shortcut.android_op_1")}</span>
+                        <span>{i18n.t("installBox.shortcut.android_op_2")}</span>
+                        <span>{i18n.t("installBox.shortcut.android_op_3")}</span>
+                        <span>{i18n.t("installBox.shortcut.android_op_4")}</span>
+                    </div>
+                    <span className={styles.sub_title}>{i18n.t("installBox.shortcut.sub_2")}</span>
+                    <div className={styles.android_op_2}>
+                        <span className={styles.header}>{i18n.t("installBox.shortcut.title")}</span>
+                        <div className={styles.app_info_con}>
+                            <img className={styles.icon} src={iconUrl}/>
+                            <span>{mainDomain}</span>
+                        </div>
+                        <div className={styles.app_btns}>
+                            <span>{i18n.t("installBox.shortcut.cancel")}</span>
+                            <span>{i18n.t("installBox.shortcut.add")}</span>
+                        </div>
+                    </div>
+                </div>
+                <div className={styles.t_guide_con}>
+                    <img className={styles.t_hand} src={img_hand}/>
+                </div>
+            </div>
+        )
+    }
+    const renderAndroid = () => {
+        return (
+            <MuiDrawer open={isShow}
+                       anchor={"top"}
+                       sx={{
+                           pointerEvents: 'auto',
+                           zIndex: 'var(--zindex-install)',
+                           "& .MuiDrawer-paper": {
+                               boxSizing: "border-box",
+                               overflow: 'visible !important',
+                               backgroundColor:'var(--standard);',
+                               boxShadow: 'var(--widget-shadow);',
+                               borderTopLeftRadius: '0.71rem',
+                               borderTopRightRadius: '0.71rem',
+                               padding: '1.42rem'
+                           },
+                       }}
+                       variant="temporary"
+                       onClose={()=>{
+                           setIsShow(false)
+                       }}>
+                {renderAndroidContent()}
+            </MuiDrawer>
+        )
+    }
+    const renderIOSContent=()=>{
+        let mainDomain = getMainDomain();
+        if(mainDomain!=null)mainDomain=mainDomain.toUpperCase();
+        const origin=window.location.origin;
+        return (
+            <div className={styles.container}>
+                <div className={styles.header}>
+                    <span className={styles.title}>
+                        {i18n.t("installBox.shortcut.title")}
+                    </span>
+                </div>
+                <div className={styles.content}>
+                    <span className={styles.sub_title}>{i18n.t("installBox.shortcut.sub_1")}</span>
+                    <div className={styles.ios_op_1}>
+                        <span>{i18n.t("installBox.shortcut.ios_op_1")}</span>
+                        <span>{i18n.t("installBox.shortcut.ios_op_2")}</span>
+                        <span>{i18n.t("installBox.shortcut.ios_op_3")}</span>
+                        <span className={styles.bottom}>{i18n.t("installBox.shortcut.ios_op_4")}</span>
+                    </div>
+                    <span className={styles.sub_title}>{i18n.t("installBox.shortcut.sub_2")}</span>
+                    <div className={styles.ios_op_2}>
+                        <div className={styles.header}>
+                            <span className={styles.btn}>{i18n.t("installBox.shortcut.cancel")}</span>
+                            <span className={styles.title_1}>{i18n.t("installBox.shortcut.title")}</span>
+                            <span className={styles.btn}>{i18n.t("installBox.shortcut.add")}</span>
+                        </div>
+                        <div className={styles.appinfo_con}>
+                            <img className={styles.icon} src={iconUrl}/>
+                            <div className={styles.info_con}>
+                                <span className={styles.host}>{mainDomain}</span>
+                                <span className={styles.origin}>{origin}</span>
+                            </div>
+                        </div>
+                        <div className={styles.tips_con}>
+                            <span>{i18n.t("installBox.shortcut.tips_1")}</span>
+                        </div>
+                    </div>
+                </div>
+                <div className={styles.b_guide_con}>
+                    <img className={styles.b_hand} src={img_hand}/>
+                </div>
+            </div>
+        )
+    }
+    const renderIOS = () => {
+        return (
+            <MuiDrawer open={isShow}
+                       anchor={"bottom"}
+                       sx={{
+                           pointerEvents: 'auto',
+                           zIndex: 'var(--zindex-install)',
+                           "& .MuiDrawer-paper": {
+                               boxSizing: "border-box",
+                               overflow: 'visible !important',
+                               backgroundColor:'var(--standard);',
+                               boxShadow: 'var(--widget-shadow);',
+                               borderTopLeftRadius: '0.71rem',
+                               borderTopRightRadius: '0.71rem',
+                               padding: '1.42rem'
+                           },
+                       }}
+                       variant="temporary"
+                       onClose={()=>{
+                           setIsShow(false)
+                       }}>
+                {renderIOSContent()}
+            </MuiDrawer>
+        )
+    }
+    const renderGuide=()=>{
+        if (isAndroid()){
+            return renderAndroid();
+        }
+        else
+        {
+            return renderIOS();
+        }
+    }
+    return (
+        <>
+            {renderGuide()}
+        </>
+    )
+}
+export default WShortcutGuide;

+ 224 - 0
src/widgets/WInstallBox/WShortcutGuide/styles.module.scss

@@ -0,0 +1,224 @@
+.container{
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 100%;
+  gap: 1rem;
+  position: relative;
+}
+.header{
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: center;
+  & .title{
+    font-size: 1rem;
+    color: var(--header);
+    font-weight: 600;
+  }
+}
+.content{
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 90%;
+  max-width: 22rem;
+  color: var(--header);
+  white-space: normal;
+  line-height: 1.2rem;
+  gap: 1rem;
+  & .sub_title{
+    min-width: 100%;
+  }
+}
+.ios_op_1{
+  display: flex;
+  flex-direction: column;
+  width: 17.8rem;
+  height: 9.57rem;
+  background-image: url("../../../assets/shortcut/img_ios_jc_1.avif");
+  background-size: 100% 100%;
+  color: #211f20;
+  font-size: 0.76rem;
+  gap: 1.1rem;
+  padding: 0.55rem 1.5rem;
+  & .bottom{
+    margin-top: 0.3rem;
+  }
+}
+.ios_op_2{
+  display: flex;
+  flex-direction: column;
+  width: 17.8rem;
+  height: 10.4rem;
+  background-image: url("../../../assets/shortcut/img_ios_jc_2_zh.avif");
+  background-size: 100% 100%;
+  padding: 0.65rem 0.5rem 0.65rem 0.65rem;
+  & .header{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 0.76rem;
+    gap: 0.5rem;
+    & .btn{
+      color: #1678ff;
+    }
+    & .title_1{
+      color: #333;
+      font-weight: 600;
+      white-space: nowrap; /* 禁止换行 */
+      overflow: hidden; /* 超出部分隐藏 */
+      text-overflow: ellipsis; /* 显示省略号 */
+    }
+  }
+  & .appinfo_con{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    gap: 1rem;
+    padding: 0.6rem 0.1rem;
+    margin-top: 2.3rem;
+    //min-height: 2.78rem;
+    & .icon{
+      width: 2.78rem;
+      height: 2.78rem;
+      border-radius: 0.5rem;
+    }
+    & .info_con{
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+      height: 100%;
+      font-size: 0.76rem;
+      & .host{
+        color: #211f20;
+      }
+      & .origin{
+        color: #8f8f8f;
+      }
+    }
+  }
+  & .tips_con{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    padding: 0.5rem 0rem;
+    font-size: 0.6rem;
+    color:#8f8f8f;
+    line-height: 0.67rem;
+  }
+  margin-bottom: 0.5rem;
+}
+.b_guide_con{
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  position: absolute;
+  inset: 0;
+  & .b_hand{
+    position: absolute;
+    width: 3.2rem;
+    height: auto;
+    bottom: 0;
+    transform: translate(0%) rotate(180deg);
+    animation: bottom_guide .9s ease-in-out infinite;
+  }
+}
+
+@keyframes bottom_guide{
+  0% {
+    bottom: -1rem;
+  }
+  50% {
+    bottom: 0.3rem;
+  }
+  100% {
+    bottom: -1rem;
+  }
+}
+@keyframes top_guide{
+  0% {
+    top: -1rem;
+  }
+  50% {
+    top: 0.3rem;
+  }
+  100% {
+    top: -1rem;
+  }
+}
+
+.android_op_1{
+  display: flex;
+  flex-direction: column;
+  width: 17.8rem;
+  height: 11.13rem;
+  background-image: url("../../../assets/shortcut/img_android_jc_1.avif");
+  background-size: 100% 100%;
+  color: #211f20;
+  font-size: 0.76rem;
+  gap: 1.56rem;
+  padding: 0.8rem 0rem 0.8rem 5.5rem;
+}
+.android_op_2{
+  display: flex;
+  flex-direction: column;
+  width: 17.8rem;
+  height: 9.64rem;
+  background-image: url("../../../assets/shortcut/img_android_jc_2_zh.avif");
+  background-size: 100% 100%;
+  padding: 1.5rem 1rem 1rem 1.5rem;
+  align-items: flex-start;
+  & .header{
+    color: #1f1f1f;
+    font-size: 1.1rem;
+    text-align: left;
+    white-space: nowrap; /* 禁止换行 */
+    overflow: hidden; /* 超出部分隐藏 */
+    text-overflow: ellipsis; /* 显示省略号 */
+  }
+  & .app_info_con{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    min-height: 1.65rem;
+    margin-top: 1.5rem;
+    & .icon{
+      width: 1.65rem;
+      height: 1.65rem;
+      border-radius: 0.25rem;
+    }
+    gap: 0.8rem;
+    color: #1f1f1f;
+    font-size: 0.8rem;
+  }
+  & .app_btns{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: flex-end;
+    width: 100%;
+    gap: 2.5rem;
+    color: #1678ff;
+    font-size: 0.7rem;
+    font-weight: 600;
+    margin-top: 1.3rem;
+    padding: 0rem 0.2rem;
+  }
+}
+.t_guide_con{
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  position: absolute;
+  inset: 0;
+  & .t_hand{
+    position: absolute;
+    width: 3.2rem;
+    height: auto;
+    bottom: 0;
+    right: -1rem;
+    animation: top_guide .9s ease-in-out infinite;
+  }
+}

+ 20 - 3
src/widgets/WInstallBox/index.jsx

@@ -11,6 +11,9 @@ import Fade from "@mui/material/Fade";
 import Grow from "@mui/material/Grow";
 import Modal from "@mui/material/Modal";
 import Http from "@api/request";
+import {useSelector} from "react-redux";
+import {getDownloadConf} from "@features/mainSlice";
+import {stringFormat} from "@utils/helpers";
 const i18n=global.i18n;
 const objInfo={
     count:0,
@@ -21,6 +24,7 @@ const WInstallBox = () => {
     const [isShow, setIsShow] = useState(false);
     const installRef = useRef(null);
     const [iconUrl, setIconUrl] = useState("");
+    const downloadConf= useSelector(getDownloadConf);
     const show=()=>{
         setIsShow(true);
     }
@@ -35,6 +39,9 @@ const WInstallBox = () => {
         }
     }
     const onInstall=()=>{
+        setIsShow(false);
+        global.showDownBox();
+        return;
         if (isInAppBrowser()){
             openUrlUseChrome();
         }
@@ -45,6 +52,8 @@ const WInstallBox = () => {
         }
     }
     const onCancel=()=>{
+        setIsShow(false);
+        return;
         let apkUrl=Http.getAPKUrl();
         window.open(apkUrl);
         setIsShow(false);
@@ -90,19 +99,27 @@ const WInstallBox = () => {
             clearTimer();
         }
     },[])
+    const getTips=()=>{
+        let bonus=0;
+        if(downloadConf!=null&&downloadConf.bonus!=null){
+            bonus=Number(downloadConf.bonus)
+        }
+        return stringFormat(i18n.t("installBox.tips_1"),[global.DOLLAR+" "+bonus]);
+    }
     const renderInstall=()=>{
         return (
             <div className={styles.continer}>
                 <div className={styles.install_con}>
                     <img src={iconUrl}/>
-                    <span>{i18n.t("installBox.tips")}</span>
+                    {/*<span>{i18n.t("installBox.tips")}</span>*/}
+                    <span>{getTips()}</span>
                 </div>
                 <div className={styles.install_btn_con}>
                     <button className={styles.install_btn} onClick={onCancel}>
                         {i18n.t("installBox.btn_cancel")}
                     </button>
                     <button className={`${styles.install_btn} ${styles.btn_green}`} onClick={onInstall}>
-                        {i18n.t("installBox.btn_install")}
+                        {i18n.t("installBox.btn_downnow")}
                     </button>
                 </div>
             </div>
@@ -156,4 +173,4 @@ const WInstallBox = () => {
         </>
     )
 }
-export default WInstallBox;
+export default WInstallBox;

+ 3 - 2
src/widgets/WInstallBox/styles.module.scss

@@ -9,6 +9,7 @@
     font-size: 0.99rem;
     line-height: 1.42rem;
     color: var(--text-light);
+    align-items: center;
     img{
       width: 4.26rem;
       height: 4.26rem;
@@ -30,7 +31,7 @@
       padding: 0.5rem;
       color: var(--text-light);
       border-radius: 0.42rem;
-      min-width: 5.11rem;
+      min-width: 7.11rem;
       font-weight: 600;
     }
     & .btn_green{
@@ -46,4 +47,4 @@
   background-color: #fff;
   max-width: 25.875rem;
   pointer-events: auto;
-}
+}