浏览代码

1.在线客服前缀修改。
2.手机验证规则修改。
3.去除个人信息界面cashapp绑定。

fattiger 2 周之前
父节点
当前提交
2ed21d91fc

+ 30 - 28
craco.config.js

@@ -2,7 +2,7 @@ const path = require('path');
 
 module.exports = {
     webpack: {
-        configure: (webpackConfig) => {
+        configure: (webpackConfig, { env }) => {
             // 设置 publicPath
             // webpackConfig.output.publicPath = 'http://192.168.1.4:8081/';
 
@@ -17,34 +17,36 @@ module.exports = {
                 });
             }
 
-            // Split existing initial modules into deterministic cacheable files. They are
-            // still loaded before the entry point, so runtime behavior remains unchanged.
-            const initialChunkMaxSize = 1000000;
-            const currentCacheGroups = webpackConfig.optimization.splitChunks?.cacheGroups || {};
-            webpackConfig.optimization.splitChunks = {
-                ...webpackConfig.optimization.splitChunks,
-                cacheGroups: {
-                    ...currentCacheGroups,
-                    initialVendors: {
-                        test: /[\\/]node_modules[\\/]/,
-                        chunks: "initial",
-                        enforce: true,
-                        maxSize: initialChunkMaxSize,
-                        minSize: 0,
-                        priority: 30,
-                        reuseExistingChunk: true,
+            // CRA development builds use a fixed "static/js/bundle.js" filename, so
+            // splitting initial chunks there makes multiple chunks target the same file.
+            if (env === "production") {
+                const initialChunkMaxSize = 1000000;
+                const currentCacheGroups = webpackConfig.optimization.splitChunks?.cacheGroups || {};
+                webpackConfig.optimization.splitChunks = {
+                    ...webpackConfig.optimization.splitChunks,
+                    cacheGroups: {
+                        ...currentCacheGroups,
+                        initialVendors: {
+                            test: /[\\/]node_modules[\\/]/,
+                            chunks: "initial",
+                            enforce: true,
+                            maxSize: initialChunkMaxSize,
+                            minSize: 0,
+                            priority: 30,
+                            reuseExistingChunk: true,
+                        },
+                        initialApp: {
+                            test: module => module.resource?.startsWith(path.resolve(__dirname, "src")),
+                            chunks: "initial",
+                            enforce: true,
+                            maxSize: initialChunkMaxSize,
+                            minSize: 0,
+                            priority: 20,
+                            reuseExistingChunk: true,
+                        },
                     },
-                    initialApp: {
-                        test: module => module.resource?.startsWith(path.resolve(__dirname, "src")),
-                        chunks: "initial",
-                        enforce: true,
-                        maxSize: initialChunkMaxSize,
-                        minSize: 0,
-                        priority: 20,
-                        reuseExistingChunk: true,
-                    },
-                },
-            };
+                };
+            }
 
             // 返回修改后的配置
             return webpackConfig;

+ 8 - 4
public/js/load.m.js

@@ -509,9 +509,10 @@
       "theme": defaultTheme
     },
 
+	// 互导站
     "blazingreels777": {
       "title": "BlazingReels777",
-      "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
+      "subtitle": "Blazing spins, bigger wins — turn up the heat on every reel.",
       "product": "blazingreels777",
       "product_id": "1",
       "logo": `/${res_path}/logos/blazingreels777.webp`,
@@ -522,9 +523,10 @@
       "theme": defaultTheme
     },
 	
+	// 互导站
 	"goldenreel777": {
 	  "title": "GoldenReel777",
-	  "subtitle": "Spin golden reels, unlock daily rewards, and chase exciting jackpots in every game.",
+	  "subtitle": "Golden spins, brilliant wins — strike fortune on every reel.",
 	  "product": "goldenreel777",
 	  "product_id": "2",
 	  "logo": `/${res_path}/logos/goldenreel777.webp`,
@@ -535,9 +537,10 @@
 	  "theme": defaultTheme
 	},
 
+	// 互导站
 	"jackpotreels777": {
 	  "title": "JackpotReels777",
-	  "subtitle": "Spin jackpot-ready reels, discover daily rewards, and enjoy fast, exciting gameplay.",
+	  "subtitle": "Jackpot reels, winning feels — every spin could be the big one.",
 	  "product": "jackpotreels777",
 	  "product_id": "3",
 	  "logo": `/${res_path}/logos/jackpotreels777.webp`,
@@ -548,9 +551,10 @@
 	  "theme": defaultTheme
 	},
 
+	// 互导站
 	"jackpotspin777": {
 	  "title": "JackpotSpin777",
-	  "subtitle": "Take every spin toward bigger jackpots, daily rewards, and nonstop slot excitement.",
+	  "subtitle": "Jackpot reels, winning feels — every spin could be the big one.",
 	  "product": "jackpotspin777",
 	  "product_id": "4",
 	  "logo": `/${res_path}/logos/jackpotspin777.webp`,

+ 2 - 2
src/api/config.js

@@ -14,12 +14,12 @@ export const WS_URL_TEST = "wss://testapi.usgamewin.com:10000";
 
 export const getApiUrl = () => {
     return API_URL_MAIN;
-    return isDebugEnv() ? API_URL_TEST : API_URL_MAIN;
+    // return isDebugEnv() ? API_URL_TEST : API_URL_MAIN;
 };
 
 export const getWsUrl = () => {
     return API_URL_MAIN;
-    return isDebugEnv() ? WS_URL_TEST : WS_URL_MAIN;
+    // return isDebugEnv() ? WS_URL_TEST : WS_URL_MAIN;
 };
 
 export const BASE_API = getApiUrl();

+ 9 - 1
src/components/UInput/PhoneInput.jsx

@@ -41,6 +41,12 @@ const PhoneInput = ({ innerRef, onChangeCountry, ...props }) => {
     const { isMobile } = useThemeProvider();
     const selectRef = useRef(null);
     const [searchValue, setSearchValue] = useState("");
+    const handlePhoneChange = (event) => {
+        const maxLength = getPhoneCodeMaxLen(country);
+        const digits = event.target.value.replace(/\D/g, '').slice(0, maxLength);
+        event.target.value = digits;
+        onChange && onChange(event);
+    };
     useEffect(() => {
         onChangeCountry && onChangeCountry(country);
         localStorageSet(LOCAL_DEFAULT_COUNTRY, country);
@@ -201,12 +207,14 @@ const PhoneInput = ({ innerRef, onChangeCountry, ...props }) => {
                         <div className={styles.line}></div>
                         <input
                             type="tel"
+                            inputMode="numeric"
+                            pattern="[0-9]*"
                             ref={innerRef}
                             maxLength={getPhoneCodeMaxLen(country)}
                             {...inputProps}
                             className={inputClass}
                             value={value}
-                            onChange={onChange}
+                            onChange={handlePhoneChange}
                         />
                         <SvgIcon className={styles.phone_icon} herf={"icon_Phone"} />
                     </div>

+ 3 - 1
src/db/areaCode.js

@@ -49,7 +49,9 @@ export const PhoneCodeRules = {
     },
     "44": {
         length: 10,
+        inputLength: 11,
+        nationalPrefix: "0",
         reg: /^7\d{9}$/,
         msg: "phoneSms.tips_gb",
     },
-}
+}

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

@@ -1032,7 +1032,7 @@
     "tips_info": "Please enter your correct mobile phone number and verification code.",
     "tips_ua": "AU mobile number must be 10 digits",
     "tips_au": "AU mobile number must be 9 digits starting with 4",
-    "tips_gb": "UK mobile number must be 10 digits starting with 7"
+    "tips_gb": "Enter a UK mobile number as 07xxxxxxxxx, or omit the leading 0 after +44"
   },
   "newUserPrompt": {
     "title": "Welcome",

+ 1 - 2
src/utils/SsqHelp.js

@@ -11,8 +11,7 @@ class SsqChat{
         this.src = "https://plugin-code.salesmartly.com/js/project_607414_626816_1768878382.js";
         this.apiUrl = getApiUrl();
         this.prefix=this.apiUrl.split(".")[0].split("//")[1]+"_";
-        if (this.prefix === "us2api_") this.prefix="us2_";
-        else if (this.prefix === "api_") this.prefix="us1_";
+        this.prefix="uk_";
         this.gameId=null;
         this.channel=null;
         this.labels=[];            // 会话来源标签(建议/投诉),经 setLoginInfo label_names 展示在客服端

+ 17 - 3
src/utils/helpers.js

@@ -348,11 +348,25 @@ export const validateUSPhone = (t) => {
     }
     return false;
 }
+export const normalizeCountryPhone = (country, phone) => {
+    const countryCode = String(country || "").replace(/^\+/, "");
+    const rule = PhoneCodeRules[countryCode];
+    let value = String(phone || "").replace(/\D/g, "");
+
+    if (rule?.nationalPrefix &&
+        value.startsWith(rule.nationalPrefix) &&
+        value.length === rule.length + rule.nationalPrefix.length) {
+        value = value.slice(rule.nationalPrefix.length);
+    }
+
+    return value;
+}
 export const validateCountryPhone = (country, phone) => {
-    const rule = PhoneCodeRules[country];
+    const countryCode = String(country || "").replace(/^\+/, "");
+    const rule = PhoneCodeRules[countryCode];
     const regExp = rule?.reg;
     if (!!regExp) {
-        return regExp.test(phone);
+        return regExp.test(normalizeCountryPhone(countryCode, phone));
     }
 
     // let func = ValidatePhoneFunc[country.toString()];
@@ -366,7 +380,7 @@ export const getCountryPhoneError = (country) => {
 }
 export const getPhoneCodeMaxLen = (country) => {
     let rule = PhoneCodeRules[country];
-    return rule?.length || 10;
+    return rule?.inputLength || rule?.length || 10;
 }
 export const getPhoneCountry = (phone) => {
     for (const code in PhoneCodeRules) {

+ 7 - 14
src/widgets/PhoneSMS/index.jsx

@@ -13,7 +13,7 @@ import {
 import { useEffect } from 'react';
 import { REQ_STATUS } from "@api/config";
 import { reqSendCode } from "@features/api";
-import { getCountryPhoneError, validateCountryPhone } from "@utils/helpers";
+import { getCountryPhoneError, normalizeCountryPhone, validateCountryPhone } from "@utils/helpers";
 import { CircularProgress } from "@mui/material";
 import { toast } from 'react-toastify';
 import MainButton from '@components/Buttons/MainButton';
@@ -32,11 +32,10 @@ const DEFAULT_COUNTRY = String(getPhoneCode()).replace(/^\+/, "") || "44";
 
 const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChange, options = {}, defValues = {}, className = '' }) => {
     const [country, setCountry] = useState(DEFAULT_COUNTRY);
-    const [phoneValid, setPhoneValid] = useState(Boolean(defValues.phone));
     const [phoneMessage] = useState("");
     const [sendCount, setSendCount] = useState(0);
     const dispatch = useDispatch();
-    const { handleSubmit, control, watch } = useForm({
+    const { handleSubmit, control, getValues, watch } = useForm({
         defaultValues: {
             // country 由当前区域配置决定。
             account: '',
@@ -56,7 +55,7 @@ const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChang
     const onSendCode = (e) => {
         if (otpCD > 0) return;
         if (otpStatus === REQ_STATUS.LOADING) return;
-        let phone = control._formValues.phone;
+        const phone = getValues("phone");
         let validate = validatePhone(phone);
         if (!validate) {
             let msg = getCountryPhoneError(country);
@@ -65,7 +64,7 @@ const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChang
             control.setError("phone", true);
             return;
         }
-        let params = { phone: phone, country: country };
+        let params = { phone: normalizeCountryPhone(country, phone), country: country };
         dispatch(reqSendCode(params));
     }
     const getLeftCD = useCallback(() => {
@@ -77,13 +76,7 @@ const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChang
         else return delta;
     }, [otpTimeStamp]);
     const checkPhone = (value) => {
-        const ok = validatePhone(value);
-        if (!ok) {
-            setPhoneValid(false);
-        } else {
-            setPhoneValid(true);
-        }
-        return ok;
+        return validatePhone(value);
     }
     const clearTimer = () => {
         if (objInfo.cdTimer != null) {
@@ -122,6 +115,7 @@ const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChang
 
     const codeValue = watch("code");
     const phoneValue = watch("phone");
+    const phoneValid = validatePhone(phoneValue);
     const checkCode = () => {
         return (!codeValue || codeValue.length < CODE_MIN || codeValue.length > CODE_MAX)
     }
@@ -144,6 +138,7 @@ const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChang
         if (!checkFormOnClaim()) return;
         //data.phone  data.code
         data.country = country;
+        data.phone = normalizeCountryPhone(country, data.phone);
         callback && callback(data);
     }
     return (
@@ -163,12 +158,10 @@ const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChang
                         onChange={
                             e => {
                                 onChange(e.target.value);
-                                setPhoneValid(validatePhone(e.target.value));
                             }
                         }
                         onChangeCountry={(country) => {
                             setCountry(country);
-                            setPhoneValid(validatePhone(control._formValues.phone, country));
                             if (onCountryChange != null) onCountryChange(country);
                         }}
                         placeholder={i18n.t('login.phone_ph')}

+ 16 - 10
src/widgets/Userinfo/WBindInfo/WModify/WChangePhone/index.jsx

@@ -4,7 +4,7 @@ import styles from './styles.module.scss';
 import { Trans } from 'react-i18next';
 import { useDispatch, useSelector } from 'react-redux';
 import { getBindPhone, getChangeBindPhoneStatus, getVerifyCodeStatus } from '@features/mainSlice';
-import { formatMaskPhone, validateCountryPhone } from '@utils/helpers';
+import { formatMaskPhone, normalizeCountryPhone, validateCountryPhone } from '@utils/helpers';
 import { ReactComponent as SuccessIcon } from '@assets/singlesvg/succss.svg';
 import { ReactComponent as ClockIcon } from '@assets/singlesvg/icon_alarm_clock.svg';
 import PhoneInputBox from '../widgets/PhoneInputBox';
@@ -31,6 +31,7 @@ const WChangePhone = ({ onDone }) => {
     const [country, setCountry] = useState(DEFAULT_COUNTRY);
     const [newPhone, setNewPhone] = useState('');
     const [newCode, setNewCode] = useState('');
+    const normalizedNewPhone = normalizeCountryPhone(country, newPhone);
 
     const setNextSteps = () => {
         setStepIdx(prev => prev + 1);
@@ -75,16 +76,16 @@ const WChangePhone = ({ onDone }) => {
     }
 
     const checkNewPhone = (phone, country) => {
-        return country + phone !== phoneNum
+        return country + normalizeCountryPhone(country, phone) !== phoneNum
     }
 
     const handleGetNewCode = async () => {
         if (!checkNewPhone(newPhone, country)) return;
         if (!validateCountryPhone(country, newPhone)) return;
-        if (!canSendCode(newPhone)) return;
+        if (!canSendCode(normalizedNewPhone)) return;
 
         let res = await dispatch(reqSendCode({
-            phone: newPhone,
+            phone: normalizedNewPhone,
             country
         })).unwrap().catch(e => null)
 
@@ -120,9 +121,14 @@ const WChangePhone = ({ onDone }) => {
                 </div>
 
 
-                <button className={styles.btn_confirm} onClick={handleGetNewCode}>
+                <button
+                    className={styles.btn_confirm}
+                    disabled={!validateCountryPhone(country, newPhone) ||
+                        !checkNewPhone(newPhone, country) ||
+                        !canSendCode(normalizedNewPhone)}
+                    onClick={handleGetNewCode}>
                     {
-                        getOptStatus(newPhone) === REQ_STATUS.LOADING ? <SmallLoading inherit /> :
+                        getOptStatus(normalizedNewPhone) === REQ_STATUS.LOADING ? <SmallLoading inherit /> :
                             i18n.t("settings.modify_phone.btn_send")
                     }
                 </button>
@@ -135,7 +141,7 @@ const WChangePhone = ({ onDone }) => {
         if (newCode.length !== APP_OPT_LENGTH) return;
 
         let res = await dispatch(reqChangeBindPhone({
-            newPhone,
+            newPhone: normalizedNewPhone,
             newCode,
             country
         })).unwrap().catch(e => null)
@@ -153,11 +159,11 @@ const WChangePhone = ({ onDone }) => {
                 </span>
 
                 <div className={styles.code_box}>
-                    <span>+{country} {newPhone}</span>
+                    <span>+{country} {normalizedNewPhone}</span>
                     <MobileCodeInput onChange={setNewCode} />
                 </div>
 
-                <SendCodeBtn phone={newPhone} />
+                <SendCodeBtn phone={normalizedNewPhone} country={country} />
 
                 <button className={styles.btn_confirm} onClick={handleSetNewCode}>
                     {
@@ -182,7 +188,7 @@ const WChangePhone = ({ onDone }) => {
                 </span>
 
                 <span className={styles.num} >
-                    +({country}) {newPhone}
+                    +({country}) {normalizedNewPhone}
                 </span>
 
                 <div className={styles.warn}>

+ 4 - 1
src/widgets/Userinfo/WBindInfo/WModify/widgets/PhoneInputBox.jsx

@@ -5,7 +5,9 @@ import { useState } from 'react';
 const PhoneInputBox = ({ country, onChange, onCheck }) => {
     const [active, setActive] = useState(false);
     const handleChanged = (e) => {
-        const phone = e.target.value;
+        const maxLength = getPhoneCodeMaxLen(country);
+        const phone = e.target.value.replace(/\D/g, '').slice(0, maxLength);
+        e.target.value = phone;
         onChange && onChange(phone, country);
 
         let active = validateCountryPhone(country, phone);
@@ -25,6 +27,7 @@ const PhoneInputBox = ({ country, onChange, onCheck }) => {
             <input
                 type='tel'
                 inputMode="numeric"
+                pattern="[0-9]*"
                 maxLength={getPhoneCodeMaxLen(country)}
                 className={`${styles.phone_num} ${active ? styles.active : ""}`}
                 onChange={handleChanged} />

+ 3 - 3
src/widgets/Userinfo/WBindInfo/WModify/widgets/SendCodeBtn.jsx

@@ -3,13 +3,13 @@ import useMobileCode from "@hooks/useMobileCode";
 import styles from './styles.module.scss';
 import { Trans } from "react-i18next";
 
-const SendCodeBtn = ({ phone }) => {
+const SendCodeBtn = ({ phone, country = '' }) => {
     const { sendMobileCode, getLeftTimes } = useMobileCode();
     const left_seconds = getLeftTimes(phone);
     const cooling = left_seconds > 0;
     const resend_lbl = cooling ? 'settings.modify_phone.resend_times' : 'settings.modify_phone.resend'
     const onSendCode = () => {
-        sendMobileCode(phone);
+        sendMobileCode(phone, country);
     }
 
     return (
@@ -23,4 +23,4 @@ const SendCodeBtn = ({ phone }) => {
     )
 }
 
-export default SendCodeBtn;
+export default SendCodeBtn;

+ 2 - 2
src/widgets/Userinfo/WBindInfo/index.jsx

@@ -164,14 +164,14 @@ const WBindInfo = () => {
                 onClick={global.showEditBindPaypal}
             />
 
-            <ItemInfo
+            {/* <ItemInfo
                 Icon={CashappIcon}
                 title="Cash App"
                 value={cashAppTag}
                 badge={i18n.t('settings.for_withdraw')}
                 cdTs={cashAppEditCd}
                 onClick={global.showEditBindCashapp}
-            />
+            /> */}
         </div>
     );
 };

+ 2 - 2
src/widgets/WDeposit/WPayInfo/WDepositInfo.jsx

@@ -3,7 +3,7 @@ import Popup from "@components/Popup";
 import styles from "./styles.module.scss";
 import {Controller, useForm} from "react-hook-form";
 import classNames from "classnames";
-import {validateCountryPhone, validateEmail} from "@utils/helpers";
+import {normalizeCountryPhone, validateCountryPhone, validateEmail} from "@utils/helpers";
 import {REQ_STATUS} from "@api/config";
 import SmallLoading from "@components/SmallLoading";
 import PhoneInput from "@components/UInput/PhoneInput";
@@ -58,7 +58,7 @@ const WDepositInfo = () => {
         if (reqKycStatus===REQ_STATUS.LOADING)return;
         let new_data=data;
         if (data.phone&&data.phone!==""){
-            let phone=country+data.phone;
+            let phone=country+normalizeCountryPhone(country, data.phone);
             new_data=Object.assign({},data,{phone:phone});
         }
         dispatch(reqKycEU(new_data)).then((data)=>{

+ 2 - 2
src/widgets/WEditProfile/index.jsx

@@ -12,7 +12,7 @@ import {ReactComponent as FeMale} from '@assets/singlesvg/gener/female.svg';
 import SmallLoading from "@components/SmallLoading";
 import {reqChangeEmail, reqChangeInfo, reqChangePhone} from "@features/api";
 import {APP_GENDER, APP_THEME} from "@constants/app";
-import {validateCountryPhone, validateEmail} from "@utils/helpers";
+import {normalizeCountryPhone, validateCountryPhone, validateEmail} from "@utils/helpers";
 import LazyImgix from "@components/Imgix/LazyImgix";
 import {useLocation} from "react-router";
 import {ROUTE_PATH} from "@constants/routes";
@@ -270,7 +270,7 @@ const WEditProfile=({close})=>{
         }
     }
     const handleChangeInfo=(data)=>{
-        data.Phone=country+data.Phone;
+        data.Phone=country+normalizeCountryPhone(country, data.Phone);
         data.RegisterLocation=country;
         let change={};
         let change_ph={};