Sfoglia il codice sorgente

feat: 提现相关

year 1 mese fa
parent
commit
9634be24b8

+ 2 - 2
messages/br.json

@@ -225,9 +225,9 @@
         "amountReg": "Valor máximo permitido: {max}",
         "amountMaxReg": "Valor excede o limite permitido",
         "pointTitle": "Proxima retirada de bonus",
-        "pointTips": "Bouns R$ ",
+        "pointTips": "Bouns",
         "pointBet": " FALTA APOSTAR R$ ",
-        "scoreTips": "SALDO R$",
+        "scoreTips": "SALDO",
         "scoreTitle": "SACAR",
         "rulesRange": "Mín {min}, máx {max}",
         "rulesToll": "{toll}% de taxa por saque. Em caso de saldo insuficiente, o montante creditado será deduzido"

+ 3 - 0
src/app/[locale]/(TabBar)/deposit/component/deposit/index.module.scss

@@ -1,6 +1,7 @@
 .depositePage {
     padding-bottom: 0.8rem;
     width: calc((100% - 20px) / 2);
+    overflow: auto;
     :global(.adm-list-default .adm-list-body) {
         border: none !important;
     }
@@ -95,6 +96,7 @@
         }
     }
 }
+
 .productTitle {
     color: #74888f;
     padding: 0.1rem 0;
@@ -102,6 +104,7 @@
 
 .amontForm {
     background-color: #1f2830;
+    border-radius: 0.15rem;
 }
 .products {
     display: grid;

+ 1 - 6
src/app/[locale]/(TabBar)/deposit/component/deposit/index.tsx

@@ -256,12 +256,7 @@ const Deposit = () => {
                     </div>
                 </div>
                 <div className={styles.swiperContainer}>
-                    <Swiper
-                        slidesPerView={3}
-                        spaceBetween={10}
-                        style={{ width: "100%" }}
-                        centeredSlidesBounds
-                    >
+                    <Swiper slidesPerView={3} spaceBetween={10} style={{ width: "100%" }}>
                         {shopType?.pay_channel?.map((item, index) => (
                             <SwiperSlide key={index}>
                                 <p

+ 158 - 0
src/app/[locale]/(TabBar)/deposit/component/withdraw/index.module.scss

@@ -1,3 +1,161 @@
 .withdrawPage {
+    padding-bottom: 0.8rem;
     width: calc((100% - 20px) / 2);
+    overflow: auto;
+    :global(.adm-list-default .adm-list-body) {
+        border: none !important;
+    }
+    :global(.adm-form-item-feedback-error) {
+        font-size: 0.1rem;
+    }
+    :global(.adm-form-item-required-asterisk) {
+        display: none;
+    }
+    :global(.adm-list-item-content) {
+        border: none !important;
+    }
+    :global(.adm-list-item-content-prefix) {
+        width: auto !important;
+        label {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            color: #fff !important;
+        }
+    }
+    :global(.adm-form-item-label) {
+        color: #768d95;
+        font-size: 0.13rem;
+    }
+    :global(.adm-list-item-content-extra) {
+        height: 0.36rem;
+    }
+    .extraPart {
+        font-size: 0.12rem;
+        display: flex;
+        align-items: center;
+    }
+    ::placeholder {
+        color: #37434c !important;
+    }
+}
+.amontForm {
+    background-color: #1f2830;
+    border-radius: 0.15rem;
+}
+.withdrawTitle {
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+    border-bottom: 1px solid #3b4852;
+    .withdrawTitleText {
+        padding: 0.05rem 0;
+        margin-right: 0.1rem;
+        position: relative;
+        &::after {
+            content: "";
+            position: absolute;
+            left: 0;
+            right: 0;
+            bottom: -1px;
+            height: 1px;
+            border-bottom: 1px solid #11de68;
+        }
+    }
+}
+.quick {
+    display: grid;
+    grid-template-columns: repeat(3, 1fr);
+    grid-gap: 0.1rem;
+}
+.buttonItem {
+    background-color: #1f2830;
+    border-radius: 0.1rem;
+    padding: 0.02rem 0;
+    text-align: center;
+    border: 1px solid #1f2830;
+    font-size: 0.1rem;
+    position: relative;
+    overflow: hidden;
+    &.active {
+        border: 1px solid #11de68;
+        .checked {
+            display: block;
+        }
+        &:before {
+            content: "\e69e";
+            position: absolute;
+            right: 0.02rem;
+            bottom: -0.01rem;
+            color: #1f2830;
+            font-size: 0.1rem;
+            z-index: 2;
+            width: 0.1rem;
+            transform: scale(0.7);
+        }
+        &:after {
+            content: "";
+            width: 0.4rem;
+            height: 0.4rem;
+            position: absolute;
+            right: -0.24rem;
+            bottom: -0.24rem;
+            background-color: #11de68;
+            transform: rotate(45deg);
+            z-index: 1;
+        }
+    }
+}
+.todos {
+    height: 100%;
+    background-color: #11de68;
+    border-radius: 0.1rem;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0 0.15rem;
+    color: #37434c;
+}
+.line {
+    height: 1px;
+    background-color: #3b4852;
+    margin: 0.2rem 0;
+}
+
+.channelText {
+    display: flex;
+    align-items: center;
+    margin-bottom: 0.1rem;
+}
+.swiperContainer {
+    border-bottom: 1px solid #3b4852;
+    padding-bottom: 0.1rem;
+}
+.btns {
+    display: flex;
+    flex-direction: column;
+    padding-top: 0.2rem;
+    .btn {
+        margin: 0.1rem 0;
+        height: 0.45rem;
+        border-radius: 0.1rem;
+        outline: none;
+        border: none;
+        font-size: 0.16rem;
+        font-weight: bold;
+        &:nth-child(1) {
+            background-color: #11de68;
+            color: #000;
+        }
+        &:nth-child(2) {
+            background-color: #393d47;
+            color: #fff;
+        }
+    }
+}
+.accountNo {
+    &::before {
+        content: "+55";
+        margin-right: 0.1rem;
+    }
 }

+ 639 - 1
src/app/[locale]/(TabBar)/deposit/component/withdraw/index.tsx

@@ -1,6 +1,644 @@
+import { GameListRep } from "@/api/home";
+import { userInfoApi } from "@/api/login";
+import { ChannelType, WithDrawParams, WithDrawType, getWithDrawApi } from "@/api/withdraw";
+import { clearWallet } from "@/app/[locale]/(navbar)/withdraw/actions";
+import TipsModal, { ModalProps } from "@/components/TipsModal";
+import { ChannelEnum, ChannelEnumMap } from "@/enums";
+import useGame from "@/hooks/useGame";
+import { useRouter } from "@/i18n/routing";
+import { useSystemStore } from "@/stores/useSystemStore";
+import { useWalletStore } from "@/stores/useWalletStore";
+import { isEmail } from "@/utils";
+import { server } from "@/utils/client";
+import { flatPoint, percentage } from "@/utils/methods";
+import { Button, Form, Input, ProgressBar, Toast } from "antd-mobile";
+import BigNumber from "bignumber.js";
+import clsx from "clsx";
+import { useTranslations } from "next-intl";
+import React from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
 import styles from "./index.module.scss";
+
+const getWithdrawApi = async () => {
+    return server
+        .request<WithDrawType[]>({
+            url: "/v1/api/user/user_withdraw_config",
+            method: "post",
+        })
+        .then((res) => {
+            if (res.code === 200) {
+                return res.data;
+            }
+            return [];
+        });
+};
+
 const Withdraw = () => {
-    return <div className={styles.withdrawPage}>2323</div>;
+    const t = useTranslations();
+    const router = useRouter();
+    const { getGameUrl } = useGame();
+    const [configData, setConfigData] = React.useState<WithDrawType[]>([] as WithDrawType[]);
+    const [currentChannel, setCurrentChannel] = React.useState<WithDrawType>({} as WithDrawType);
+    const [currentType, setCurrentType] = React.useState<ChannelType>({} as ChannelType);
+    const [amount, setAmount] = React.useState<string>("");
+    const { wallet } = useWalletStore();
+    const isStrictMode = useSystemStore((state) => state.identity_verify.withdraw === 1);
+
+    const bounsModalRef = React.useRef<ModalProps>(null);
+    const formInstanceRef = React.useRef<any>(null);
+    const scoreRef = React.useRef<ModalProps>(null);
+    const gameModelRef = React.useRef<ModalProps>(null);
+    const game = React.useRef<GameListRep | null>(null);
+
+    React.useEffect(() => {
+        getData();
+    }, []);
+
+    React.useEffect(() => {
+        formInstanceRef.current?.resetFields(["account_no"]);
+    }, [currentType]);
+    React.useEffect(() => {
+        formInstanceRef.current?.resetFields();
+        setAmount("");
+    }, [currentChannel]);
+
+    const quicks = React.useMemo(() => {
+        return [200, 500, 1000, 10000];
+    }, []);
+
+    const faltaData = React.useMemo(() => {
+        const {
+            target_score_rollover,
+            current_score_rollover,
+            score,
+            point,
+            target_point_rollover,
+            current_point_rollover,
+        } = wallet;
+
+        const canWithdraw =
+            flatPoint(target_score_rollover - current_score_rollover) === 0 ||
+            percentage(current_score_rollover, target_score_rollover) >= 100
+                ? flatPoint((score || 0) + point)
+                : 0;
+
+        const total = target_score_rollover + target_point_rollover;
+        const current = current_score_rollover + current_point_rollover;
+
+        const waitScore = target_score_rollover - current_score_rollover;
+        const waitPoint = target_point_rollover - current_point_rollover;
+        return {
+            canWithdraw,
+            percent: percentage(current, total),
+            wait: waitScore + waitPoint,
+        };
+    }, [wallet]);
+
+    const getData = async () => {
+        const res = await getWithdrawApi();
+        if (res?.length > 0) {
+            setConfigData(res);
+            if (res[0]) {
+                const cChannel = res[0];
+                setCurrentChannel(cChannel);
+                const ctype = cChannel?.channels;
+                if (ctype && ctype?.length > 0) {
+                    setCurrentType(ctype[0] || {});
+                }
+            }
+        }
+    };
+    const channelChangeHandler = (item: WithDrawType) => {
+        setCurrentChannel(item);
+        if (item?.channels && item?.channels?.length > 0) {
+            setCurrentType(item.channels[0]);
+        }
+    };
+
+    const valuesChange = (data: any) => {
+        for (let key in data) {
+            let curValue = data[key].trim();
+            switch (key) {
+                case "amount":
+                    {
+                        let max = currentChannel.max_amount;
+                        if (faltaData.canWithdraw < currentChannel.max_amount) {
+                            max = faltaData.canWithdraw;
+                        }
+                        const toValue = inputNumber(curValue, { max });
+                        console.log(toValue, max);
+                        setAmount(toValue);
+                        formInstanceRef.current?.setFieldValue(key, toValue);
+                    }
+                    break;
+                case "account_no":
+                    {
+                        if (currentType.type === ChannelEnum.CPF) {
+                            const toValue = inputNumber(curValue, { length: 11 });
+                            formInstanceRef.current?.setFieldValue(key, toValue);
+                        }
+                        if (currentType.type === ChannelEnum.CNPJ) {
+                            const toValue = inputNumber(curValue, { length: 14 });
+                            formInstanceRef.current?.setFieldValue(key, toValue);
+                        }
+                        if (currentType.type === ChannelEnum.Phone) {
+                            const toValue = inputNumber(curValue, { length: 11 });
+                            formInstanceRef.current?.setFieldValue(key, toValue);
+                        }
+                        if (currentType.type === ChannelEnum.Email) {
+                            const toValue = curValue.replace(/\s/gi, "");
+                            formInstanceRef.current?.setFieldValue(key, toValue);
+                        }
+                    }
+                    break;
+                case "passport":
+                    {
+                        const toValue = inputNumber(curValue, { length: 11 });
+                        formInstanceRef.current?.setFieldValue(key, toValue);
+                    }
+                    break;
+            }
+        }
+    };
+
+    const inputNumber = (
+        value: string,
+        opts?: {
+            max?: number;
+            length?: number;
+        }
+    ) => {
+        const toValue = value.replace(/[^0-9]/, "");
+        let toAmount = "";
+        if (toValue) {
+            toAmount = new BigNumber(toValue).toFixed(0, BigNumber.ROUND_DOWN);
+        }
+        if (opts?.max !== undefined && new BigNumber(toAmount).isGreaterThan(opts.max)) {
+            toAmount = opts.max.toString();
+        }
+        if (opts?.length && toAmount.length > opts.length) {
+            toAmount = toAmount.slice(0, opts.length);
+        }
+
+        return toAmount;
+    };
+
+    const ChannelValidator = (rules: any, value: string) => {
+        if (!value) return Promise.reject(new Error(t("WithdrawPage.channel")));
+        if (currentType.type === ChannelEnum.CPF) {
+            return value.length !== 11
+                ? Promise.reject(new Error(t("WithdrawPage.cpfReg")))
+                : Promise.resolve();
+        }
+        if (currentType.type === ChannelEnum.CNPJ) {
+            return value.length !== 14
+                ? Promise.reject(new Error(t("WithdrawPage.cnpjReg")))
+                : Promise.resolve();
+        }
+        if (currentType.type === ChannelEnum.Email) {
+            return isEmail(value)
+                ? Promise.resolve()
+                : Promise.reject(new Error(t("WithdrawPage.EmailReg")));
+        }
+
+        if (currentType.type === ChannelEnum.Phone) {
+            return value.length < 10
+                ? Promise.reject(new Error(t("WithdrawPage.phoneReg")))
+                : Promise.resolve();
+        }
+        return Promise.resolve();
+    };
+
+    const onFinish = async (value: any) => {
+        const { data } = await userInfoApi();
+        if (
+            faltaData.canWithdraw <= 0 ||
+            new BigNumber(value.amount).isGreaterThan(faltaData.canWithdraw)
+        ) {
+            Toast.show("Quantidade insuficiente disponível para retirada");
+            return;
+        }
+        // 如果有未完成游戏
+        if (data.play_list && data.play_list.length > 0) {
+            game.current = data.play_list[0];
+            gameModelRef.current?.onOpen();
+            return;
+        }
+        // 如果彩金 || 彩金打码量不为0
+        if (
+            flatPoint(wallet.target_point_rollover - wallet.current_point_rollover) > 0 ||
+            (wallet.point || 0) > 0
+        ) {
+            bounsModalRef.current?.onOpen();
+            return;
+        }
+        extractHandler();
+    };
+
+    const extractHandler = async () => {
+        const values = formInstanceRef.current?.getFieldValues();
+        const { passport, name, last_name, amount, account_no } = values;
+        if (!amount) {
+            return;
+        }
+        const params: WithDrawParams = {
+            passport,
+            channel_id: currentType.id,
+            amount,
+            account_no,
+            user_name: `${name} ${last_name}`,
+        };
+
+        const withResult = await getWithDrawApi(params).catch((error) => {
+            Toast.show(t(`code.${error.data.code}`));
+        });
+        if (withResult && withResult.code === 200) {
+            Toast.show(t("code.200"));
+        }
+
+        await clearWallet();
+    };
+    const goGame = () => {
+        const current = game.current;
+        getGameUrl(current!, { id: current?.id + "" });
+    };
+
+    return (
+        <div className={styles.withdrawPage}>
+            <div className={styles.swiperContainer}>
+                <Swiper slidesPerView={3} spaceBetween={10} style={{ width: "100%" }}>
+                    {configData?.map((item, index) => (
+                        <SwiperSlide key={index}>
+                            <p
+                                className={clsx(
+                                    styles.buttonItem,
+                                    {
+                                        [styles.active]: currentChannel?.id === item.id,
+                                    },
+                                    "iconfont"
+                                )}
+                                onClick={() => channelChangeHandler(item)}
+                            >
+                                <div className="text-center">
+                                    <img
+                                        className="inline-block h-[.15rem]"
+                                        src={item.icon}
+                                        alt=""
+                                    />
+                                </div>
+                                <div className="mt-[.02rem] text-[#11de68]">
+                                    R${item.min_amount}~{item.max_amount}
+                                </div>
+                            </p>
+                        </SwiperSlide>
+                    ))}
+                </Swiper>
+            </div>
+            <div className={styles.withdrawTitle}>
+                <div className={styles.withdrawTitleText}>
+                    <span className="mr-[.1rem]">ContaSaldo</span>
+                    <span className="text-[#11de68]">R$ {faltaData.canWithdraw}</span>
+                </div>
+                <i
+                    className="iconfont icon-22222_huaban1 text-[#eac61f]"
+                    onClick={() => {
+                        scoreRef.current?.onOpen();
+                    }}
+                ></i>
+            </div>
+            <div className="pb-[.1rem] text-[#74888f]">Valor do Saque</div>
+            <div className={styles.quick}>
+                {quicks.map((item) => {
+                    return (
+                        <div
+                            className={clsx(
+                                styles.buttonItem,
+                                {
+                                    [styles.active]: Number(amount) === item,
+                                },
+                                "iconfont flex h-[.44rem] flex-col items-center justify-center"
+                            )}
+                            key={item}
+                            onClick={() => {
+                                formInstanceRef.current?.setFieldValue("amount", item);
+                                setAmount(`${item}`);
+                            }}
+                        >
+                            <div className="text-[.16rem] text-[#11de68]">R$ {item}</div>
+                        </div>
+                    );
+                })}
+            </div>
+            <div className="flex items-center py-[.1rem]">
+                <i className="iconfont icon-22222_huaban1 mr-[.1rem] text-[#789098]"></i>
+                <span className="text-[.12rem] text-[#eac61f]">
+                    A retirada minima após depositar R$ 10 é R$ 20
+                </span>
+            </div>
+            <div>
+                <Form ref={formInstanceRef} onFinish={onFinish} onValuesChange={valuesChange}>
+                    <Form.Item
+                        className={styles.amontForm}
+                        label="R$"
+                        layout="horizontal"
+                        extra={
+                            <div
+                                className={styles.todos}
+                                onClick={() => {
+                                    if (faltaData.canWithdraw > 0) {
+                                        formInstanceRef.current?.setFieldValue(
+                                            "amount",
+                                            faltaData.canWithdraw
+                                        );
+                                        setAmount(`${faltaData.canWithdraw}`);
+                                    }
+                                }}
+                            >
+                                Todos
+                            </div>
+                        }
+                        name="amount"
+                    >
+                        <Input onChange={(value) => setAmount(value)} />
+                    </Form.Item>
+
+                    <div className={styles.line}></div>
+                    <div className={styles.channelText}>
+                        <span className="mr-[.1rem] text-[#768d95]">Método de Retirada</span>
+                        {currentChannel.icon && (
+                            <div className="rounded-[.04rem] border-[1px] border-[#16432f] px-[.06rem] py-[.02rem]">
+                                <img className="h-[.2rem]" src={currentChannel.icon} alt="" />
+                            </div>
+                        )}
+                    </div>
+                    <div>
+                        <Swiper slidesPerView={3} spaceBetween={10} style={{ width: "100%" }}>
+                            {currentChannel.channels?.map((item, index) => (
+                                <SwiperSlide key={index}>
+                                    <p
+                                        className={clsx(
+                                            styles.buttonItem,
+                                            {
+                                                [styles.active]: currentType?.id === item.id,
+                                            },
+                                            "iconfont"
+                                        )}
+                                        onClick={() => setCurrentType(item)}
+                                    >
+                                        <div className="py-[.08rem] text-[.12rem]">
+                                            {ChannelEnum[item.type]}
+                                        </div>
+                                    </p>
+                                </SwiperSlide>
+                            ))}
+                        </Swiper>
+                    </div>
+                    {(isStrictMode || currentType.type === ChannelEnum.CPF) && (
+                        <div className="mt-[.1rem] flex items-center">
+                            <Form.Item
+                                label="Nome"
+                                className="mr-[.1rem] w-[1.5rem] border-b-[1px] border-[#3b4852]"
+                                rules={[{ required: true }]}
+                                name="name"
+                            >
+                                <Input placeholder="Insira seu nome"></Input>
+                            </Form.Item>
+                            <Form.Item
+                                rules={[{ required: true }]}
+                                className="flex-1 border-b-[1px] border-[#3b4852]"
+                                label="Sobrenome"
+                                name="last_name"
+                            >
+                                <Input placeholder="Insira seu sobrenome"></Input>
+                            </Form.Item>
+                        </div>
+                    )}
+
+                    {isStrictMode && currentType.type !== ChannelEnum.CPF && (
+                        <Form.Item
+                            label={"CPF"}
+                            className="mt-[.1rem] border-b-[1px] border-[#3b4852]"
+                            name={"passport"}
+                            rules={[{ validator: ChannelValidator }]}
+                        >
+                            <Input
+                                className={clsx("flex-1")}
+                                placeholder={ChannelEnumMap.get(ChannelEnum.CPF)?.placeholder ?? ""}
+                            ></Input>
+                        </Form.Item>
+                    )}
+
+                    <Form.Item
+                        label={ChannelEnumMap.get(currentType.type)?.text}
+                        className="mt-[.1rem] border-b-[1px] border-[#3b4852]"
+                        name={"account_no"}
+                        rules={[{ validator: ChannelValidator }]}
+                    >
+                        <Input
+                            className={clsx("flex-1", {
+                                [styles.accountNo]: currentType.type === ChannelEnum.Phone,
+                            })}
+                            placeholder={ChannelEnumMap.get(currentType.type)?.placeholder ?? ""}
+                        ></Input>
+                    </Form.Item>
+                </Form>
+                <div className={styles.btns}>
+                    <Button
+                        className={styles.btn}
+                        onClick={() => formInstanceRef.current?.submit()}
+                    >
+                        Sacar
+                    </Button>
+                    <Button className={styles.btn}>Histórico</Button>
+                </div>
+            </div>
+            {/*本金*/}
+            <TipsModal
+                title={
+                    <div className={"flex items-center"}>
+                        <i
+                            className={"iconfont icon-liwuhuodong mr-[0.0694rem] text-[0.2778rem]"}
+                        ></i>
+                        SACAR
+                    </div>
+                }
+                ref={scoreRef}
+                getContainer={document.body}
+            >
+                <ul>
+                    <li className={"mb-[0.0694rem]"}>
+                        <span className="mr-[.1rem]">Recedibo</span>
+                        <span>R${faltaData.canWithdraw}</span>
+                    </li>
+                    <li className={"mb-[0.0694rem]"}>
+                        <span className="mr-[.1rem]">{t("WithdrawPage.scoreTips")}</span>
+                        <span>R${wallet.score}</span>
+                    </li>
+                    <li className={"mb-[0.0694rem]"}>
+                        <span className="mr-[.1rem]">{t("WithdrawPage.pointTips")}</span>
+                        <span>R${wallet.point}</span>
+                    </li>
+
+                    <li>
+                        <div className={"flex items-center"}>
+                            <ProgressBar
+                                percent={faltaData.percent}
+                                className={"mr-[0.0694rem] flex-1"}
+                                style={{
+                                    "--fill-color": "#fb8b05",
+                                    "--track-width": "0.0694rem",
+                                }}
+                            />
+
+                            <span>{faltaData.percent}%</span>
+                        </div>
+                        <div>
+                            <span>Falta Apostar</span>
+                            <span>{faltaData.wait}</span>
+                        </div>
+                        <div className="mt-[.2rem] flex items-center justify-center">
+                            {faltaData.canWithdraw <= 0 && (
+                                <Button
+                                    color={"primary"}
+                                    className={"mx-auto"}
+                                    style={{
+                                        "--background-color": "var(--primary-color)",
+                                        "--border-color": "var(--primary-color)",
+                                    }}
+                                    onClick={() => router.push("/")}
+                                >
+                                    para jogos
+                                </Button>
+                            )}
+                            {faltaData.canWithdraw > 0 && (
+                                <Button
+                                    color={"primary"}
+                                    className={"ml-[30px]"}
+                                    style={{
+                                        "--background-color": "var(--primary-color)",
+                                        "--border-color": "var(--primary-color)",
+                                    }}
+                                    onClick={() => {
+                                        // 关闭彩金弹窗
+                                        scoreRef.current?.onClose();
+                                        extractHandler();
+                                    }}
+                                >
+                                    confirmação
+                                </Button>
+                            )}
+                        </div>
+                        {/* <div>
+                            <span>{t("WithdrawPage.pointBet")}</span>
+                            <span>
+                                {flatPoint(
+                                    wallet.target_score_rollover - wallet.current_score_rollover
+                                )}
+                            </span>
+                        </div> */}
+                    </li>
+                </ul>
+            </TipsModal>
+
+            {/*含有彩金提现拦截*/}
+            <TipsModal
+                title={
+                    <div className={"text-left text-[0.12rem] font-medium text-[#666]"}>
+                        Retirar bem sucedido, seu dinheiro de prémio será limpo. Você tem certeza?
+                    </div>
+                }
+                ref={bounsModalRef}
+            >
+                <ul>
+                    <li className={"mb-[0.0694rem]"}>
+                        <span>{t("WithdrawPage.pointTips")}</span>
+                        <span>{wallet.point}</span>
+                    </li>
+                    <li>
+                        <div className={"flex items-center"}>
+                            <ProgressBar
+                                percent={percentage(
+                                    wallet.current_point_rollover,
+                                    wallet.target_point_rollover
+                                )}
+                                className={"mr-[0.0694rem] flex-1"}
+                                style={{
+                                    "--fill-color": "#fb8b05",
+                                    "--track-width": "0.0694rem",
+                                }}
+                            />
+                            <span>
+                                {percentage(
+                                    wallet.current_point_rollover,
+                                    wallet.target_point_rollover
+                                )}
+                                %
+                            </span>
+                        </div>
+
+                        <div>
+                            <span>{t("WithdrawPage.pointBet")}</span>
+                            <span>
+                                {flatPoint(
+                                    wallet.target_point_rollover - wallet.current_point_rollover
+                                )}
+                            </span>
+                        </div>
+
+                        <div className={"mt-[20px] flex justify-around"}>
+                            <Button
+                                color={"default"}
+                                fill={"none"}
+                                style={{
+                                    "--text-color": "var(--primary-color)",
+                                }}
+                                onClick={() => {
+                                    bounsModalRef.current?.onClose();
+                                }}
+                            >
+                                cancelar
+                            </Button>
+                            <Button
+                                color={"primary"}
+                                className={"ml-[30px]"}
+                                style={{
+                                    "--background-color": "var(--primary-color)",
+                                    "--border-color": "var(--primary-color)",
+                                }}
+                                onClick={() => {
+                                    // 关闭彩金弹窗
+                                    bounsModalRef.current?.onClose();
+                                    extractHandler();
+                                }}
+                            >
+                                confirmação
+                            </Button>
+                        </div>
+                    </li>
+                </ul>
+            </TipsModal>
+            {/*   提现拦截 */}
+            <TipsModal title={"Tips"} ref={gameModelRef}>
+                <p className={"text-left text-[0.12rem] font-medium text-[#666]"}>
+                    Atualmente, existem jogos de bônus inacabados que não podem iniciar saques.
+                </p>
+
+                <div className={"mt-[0.0694rem] flex justify-center"}>
+                    <Button
+                        color={"primary"}
+                        className={"mx-auto"}
+                        style={{
+                            "--background-color": "var(--primary-color)",
+                            "--border-color": "var(--primary-color)",
+                        }}
+                        onClick={goGame}
+                    >
+                        para jogos
+                    </Button>
+                </div>
+            </TipsModal>
+        </div>
+    );
 };
 
 export default Withdraw;

+ 2 - 1
src/app/[locale]/(TabBar)/deposit/page.module.scss

@@ -10,11 +10,12 @@
     border-radius: 0.1rem;
     background-color: #1f2830;
     overflow: hidden;
+    margin-bottom: 0.1rem;
     .tabItem {
         flex: 1;
         text-align: center;
         cursor: pointer;
-        padding: 0.1rem 0;
+        padding: 0.08rem 0;
         font-weight: bold;
         font-size: 0.14rem;
         &.active {

+ 18 - 20
src/app/[locale]/(TabBar)/profile/ProfileHeader.tsx

@@ -54,14 +54,11 @@ const VipCard = (props: { userVip: UserVipInfo }) => {
     if (!userVip) return null;
     return (
         <div className={"vip-card"}>
-            <div className={"vip-card__icon"}>{vipIconElement}</div>
+            {/* <div className={"vip-card__icon"}>{vipIconElement}</div> */}
             <div className={"vip-card-process"}>
                 {/*<div className={"process-top"}>{userVip.vip_exp}xp</div>*/}
-                <div className="vip-card-text">
-                    <span className="underline">CLUBE VIP</span>
-                    <i className="iconfont icon-xiangzuo1 block rotate-[180deg]"></i>
-                </div>
-                <div>
+
+                <div className="relative mr-[.1rem] flex-1 px-[.3rem]">
                     <ProgressBar
                         percent={percentage(userVip?.vip_exp, userVip?.vip_score_exp)}
                         style={{
@@ -70,19 +67,20 @@ const VipCard = (props: { userVip: UserVipInfo }) => {
                             "--track-width": ".12rem",
                         }}
                     />
-                </div>
-                <div className={"process-bottom text-[#e581ff]"}>
-                    <span>VIP{userVip?.vip_level}</span>
-                    <div className={"process-bottom-desc"}>
-                        {userVip.vip_exp}/{userVip.vip_score_exp}
-                        {/* {t("expTips", {
-                            exp: flatPoint(userVip.vip_score_exp - userVip.vip_exp),
-                        })} */}
+                    <div className={"process-bottom text-[#e581ff]"}>
+                        <span className="bg-[#0abd71]">VIP{userVip?.vip_level}</span>
+                        <div className={"process-bottom-desc"}>
+                            {userVip.vip_exp}/{userVip.vip_score_exp}
+                        </div>
+                        <span className="bg-[#eac61f]">
+                            VIP
+                            {userVip.vip_next_level}
+                        </span>
                     </div>
-                    <span>
-                        VIP
-                        {userVip.vip_next_level}
-                    </span>
+                </div>
+                <div className="vip-card-text">
+                    <span className="underline">CLUBE VIP</span>
+                    <i className="iconfont icon-xiangzuo1 block rotate-[180deg]"></i>
                 </div>
             </div>
         </div>
@@ -365,9 +363,9 @@ export const ProfileHeader = (props: Props) => {
 
     const handler = () => {
         if (!!wallet.score) {
-            router.push("/withdraw");
+            router.push("/deposit?target=2");
         } else {
-            Toast.show("no money ");
+            Toast.show("no money");
         }
     };
 

+ 7 - 4
src/app/[locale]/(TabBar)/profile/page.scss

@@ -129,14 +129,17 @@
             flex: 1;
             font-size: 0.11rem;
             position: relative;
+            display: flex;
+            align-items: center;
+            padding-bottom: 0.15rem;
             .process-top {
                 color: #fb8b05;
                 margin-bottom: 3px;
             }
             .vip-card-text {
-                position: absolute;
-                right: 0;
-                top: -0.4rem;
+                // position: absolute;
+                // right: 0;
+                // top: -0.4rem;
                 color: #11e169;
                 font-size: 0.14rem;
                 display: flex;
@@ -157,7 +160,7 @@
                     color: #fff;
                 }
                 span {
-                    background: #0abd71;
+                    // background: #0abd71;
                     color: #121418;
                     display: block;
                     padding: 0.02rem 0.06rem;

+ 38 - 0
src/enums/index.tsx

@@ -51,3 +51,41 @@ export const FundsHandleTypeMap = new Map<FundsHandleType, Record<string, string
         },
     ],
 ]);
+
+export enum ChannelEnum {
+    CPF = 1,
+    Email = 2,
+    Phone = 3,
+    CNPJ = 4,
+}
+
+export const ChannelEnumMap = new Map<ChannelEnum, Record<string, string>>([
+    [
+        ChannelEnum.CPF,
+        {
+            placeholder: "Seu CPF(000.000.000-00)",
+            text: "CPF ID",
+        },
+    ],
+    [
+        ChannelEnum.Email,
+        {
+            text: "Email",
+            placeholder: "Email",
+        },
+    ],
+    [
+        ChannelEnum.Phone,
+        {
+            text: "Phone",
+            placeholder: "11 dígitos",
+        },
+    ],
+    [
+        ChannelEnum.CNPJ,
+        {
+            text: "CNPJ",
+            placeholder: "CNPJ(00.000.000.0000-00)",
+        },
+    ],
+]);