Kaynağa Gözat

fix: 更新首充优惠

Before 8 ay önce
ebeveyn
işleme
dbed9e11ca

+ 15 - 0
messages/br.json

@@ -1097,6 +1097,21 @@
       }
     ]
   },
+  "replayPage": {
+    "title": "Replay Coin Description",
+    "desc1": "Replay Coins can be earned through events",
+    "desc2": "Replay Coins can only be played in the designated replay game",
+    "desc3": "After completing the replay coin encoding amount, the balance will be automatically transferred to the cash wallet",
+    "desc4": "The transfer of replay coins to the cash wallet will also increase the amount of cash wallet slots"
+  },
+
+  "freePage": {
+    "title": "Description of free coins",
+    "desc1": "Free coins can be earned through events",
+    "desc2": "Free Coins can only be used in designated Free Games",
+    "desc3": "After completing the free coin code, the balance will be automatically transferred to the cash wallet",
+    "desc4": "The transfer of free coins to the cash wallet will increase the amount of cash wallet encoding"
+  },
   "titles": {
     "home": "The home of over 30 million players",
     "login": "Login",

BIN
public/doings/recharge.jpg


+ 6 - 0
src/api/depositsApi.ts

@@ -43,4 +43,10 @@ export interface Product {
      * 角标:0无,1为Hot
      */
     badge: number;
+    rewards: RewardsType[];
+}
+export interface RewardsType {
+    coin_type: 1 | 2 | 3 | 4;
+    reward: number;
+    ratio: number;
 }

+ 74 - 12
src/api/user.ts

@@ -125,45 +125,107 @@ export interface Wallet {
     /**
      * 用户头像
      */
-    avatar_url?: string;
+    avatar_url: string;
     /**
      * 货币类型
      */
-    currency?: string;
+    currency: string;
+    /**
+     * 当前免费钱包打码量
+     */
+    current_free_score_rollover: number;
+    /**
+     * 当前输钱钱包打码量
+     */
+    current_lose_score_rollover: number;
+    /**
+     * 当前奖金打码量
+     */
+    current_point_rollover: number;
+    /**
+     * 当前现金打码量
+     */
+    current_score_rollover: number;
     /**
      * 累计充值金额
      */
-    deposit?: number;
+    deposit: number;
     /**
      * 第一次充值时间
      */
-    first_pay_time?: number;
+    first_pay_time: number;
+    /**
+     * 免费币
+     */
+    free_score: number;
     /**
      * 锁定活动代币
      */
-    lock_point?: number;
+    lock_point: number;
     /**
      * 锁定积分
      */
-    lock_score?: number;
+    lock_score: number;
+    /**
+     * 重玩币
+     */
+    lose_score: number;
     /**
      * 真实姓名
      */
-    nick_name?: string;
+    nick_name: string;
     /**
      * 活动代币
      */
-    point?: number;
+    point: number;
     /**
      * 积分
      */
-    score?: number;
+    score: number;
+    /**
+     * 目标免费钱包打码量
+     */
+    target_free_score_rollover: number;
+    /**
+     * 目标输钱钱包打码量
+     */
+    target_lose_score_rollover: number;
+    /**
+     * 目标奖金打码量
+     */
+    target_point_rollover: number;
+    /**
+     * 目标现金打码量
+     */
+    target_score_rollover: number;
+    /**
+     * 累计免费钱包打码量
+     */
+    total_free_score_rollover: number;
+    /**
+     * 累计输钱钱包打码量
+     */
+    total_lose_score_rollover: number;
+    /**
+     * 累计奖金打码量
+     */
+    total_point_rollover: number;
+    /**
+     * 历史领取红包总次数
+     */
+    total_receive_red_packet: number;
+    /**
+     * 历史红包总金额
+     */
+    total_red_packet: number;
+    /**
+     * 累计现金打码量
+     */
+    total_score_rollover: number;
     /**
      * 用户名
      */
-    user_name?: string;
-    free_score?: number;
-    lose_score?: number;
+    user_name: string;
 }
 // 前台用户获取金额信息
 export const getUserMoneyApi = () => {

+ 64 - 0
src/api/userWallt.ts

@@ -0,0 +1,64 @@
+import { Wallet } from "@/api/user";
+import { server } from "@/utils/server";
+
+export const getMoneyApi = async () => {
+    return server
+        .request<Wallet>({
+            url: "/v1/api/user/user_money",
+            method: "POST",
+            next: { revalidate: 30 },
+        })
+        .then((res) => {
+            if (res.code === 200) return res.data;
+            return {
+                avatar_url: "",
+                currency: "",
+                current_free_score_rollover: 0,
+
+                current_lose_score_rollover: 0,
+
+                current_point_rollover: 0,
+
+                current_score_rollover: 0,
+
+                deposit: 0,
+
+                first_pay_time: 0,
+
+                free_score: 0,
+
+                lock_point: 0,
+
+                lock_score: 0,
+
+                lose_score: 0,
+
+                nick_name: "",
+
+                point: 0,
+
+                score: 0,
+
+                target_free_score_rollover: 0,
+
+                target_lose_score_rollover: 0,
+
+                target_point_rollover: 0,
+
+                target_score_rollover: 0,
+
+                total_free_score_rollover: 0,
+
+                total_lose_score_rollover: 0,
+
+                total_point_rollover: 0,
+
+                total_receive_red_packet: 0,
+                total_red_packet: 0,
+
+                total_score_rollover: 0,
+
+                user_name: "",
+            };
+        });
+};

+ 25 - 4
src/app/[locale]/(TabBar)/deposit/DepositData.tsx

@@ -10,6 +10,7 @@ import { FormInstance } from "antd-mobile/es/components/form";
 import { useTranslations } from "next-intl";
 import { FC, Fragment, useRef, useState } from "react";
 
+import actions from "@/app/[locale]/(TabBar)/deposit/actions";
 import "@/styles/deposit.scss";
 interface Props {
     deposits: DepositsTypes[];
@@ -33,13 +34,15 @@ const DepositData: FC<Props> = (props) => {
     const onFinish = (values: any) => {
         const params = { ...values, channel_id: activeType.id, amount: +values.amount };
         getUserRechargeApi(params)
-            .then((res) => {
+            .then(async (res) => {
                 formInstanceRef.current?.resetFields();
                 Toast.show({ icon: "success", content: t("code.200"), maskClickable: false });
                 setAmount(undefined);
+
                 if (res.data.pay_url) {
                     window.open(res.data.pay_url);
                 }
+                await actions();
             })
             .catch((error) => {
                 Toast.show({ content: t(`code${error.data.code}`), maskClickable: false });
@@ -152,9 +155,27 @@ const DepositData: FC<Props> = (props) => {
                                             <span className="iconfont">R$</span>
                                             <span> {item.amount}</span>
                                         </div>
-                                        <span className="amountTips">
-                                            {t("DepositPage.Oferecer")} 100%
-                                        </span>
+                                        <div>
+                                            {item.rewards
+                                                .sort((p, n) => p.coin_type - n.coin_type)
+                                                .map((reward, index) => {
+                                                    return (
+                                                        <Fragment key={index}>
+                                                            {reward.ratio > 0 ? (
+                                                                <span className="amountTips">
+                                                                    {t("DepositPage.Oferecer")}{" "}
+                                                                    {reward.ratio}%
+                                                                </span>
+                                                            ) : null}
+                                                            {reward.reward > 0 ? (
+                                                                <span className="amountTips">
+                                                                    + {reward.reward}
+                                                                </span>
+                                                            ) : null}
+                                                        </Fragment>
+                                                    );
+                                                })}
+                                        </div>
                                     </li>
                                 ))}
                             </ul>

+ 2 - 13
src/app/[locale]/(TabBar)/profile/page.tsx

@@ -1,4 +1,5 @@
-import { UserInfoRep, UserVipInfo, Wallet } from "@/api/user";
+import { UserInfoRep, UserVipInfo } from "@/api/user";
+import { getMoneyApi } from "@/api/userWallt";
 import { server } from "@/utils/server";
 import { FC } from "react";
 import ItemCom from "./component/ItemCom";
@@ -19,18 +20,6 @@ const getUserInfo = async () => {
         });
 };
 
-const getMoneyApi = async () => {
-    return server
-        .request<Wallet>({
-            url: "/v1/api/user/user_money",
-            method: "POST",
-        })
-        .then((res) => {
-            if (res.code === 200) return res.data;
-            return {};
-        });
-};
-
 /**
  * @description  前台用户VIP信息 接口地址:https://app.apifox.com/link/project/4790544/apis/api-201160713
  */

+ 34 - 77
src/app/[locale]/(navbar)/doings/discount/DepositData.tsx

@@ -11,8 +11,7 @@ import { FC, Fragment, useRef, useState } from "react";
 
 import ButtonOwn from "@/components/ButtonOwn";
 import "@/styles/deposit.scss";
-import { Autoplay, Pagination } from "swiper/modules";
-import { Swiper, SwiperSlide } from "swiper/react";
+import Image from "next/image";
 interface Props {
     deposits: DepositsTypes[];
 }
@@ -20,10 +19,10 @@ const DepositData: FC<Props> = (props) => {
     const { deposits } = props;
     const t = useTranslations();
     const userInfo = useUserInfoStore((state) => state.userInfo);
+
+    const count = 2;
     // 选中类型
     const [activeType, setActiveType] = useState<DepositsTypes>(deposits[0]);
-    // 是否自定义充值
-    const [isCustomInput, setIsCustomInput] = useState(false);
 
     const formInstanceRef = useRef<FormInstance>(null);
     let [amount, setAmount] = useState<number | undefined>(undefined);
@@ -71,61 +70,21 @@ const DepositData: FC<Props> = (props) => {
             );
         return Promise.resolve();
     };
-    const banners = [
-        {
-            id: 61,
-            sort: 0,
-            show_platform: 1,
-            action_type: 1,
-            action_params: "",
-            content: "http://192.168.0.237:9000/bcwin/86fa3351-2aef-4ede-ba70-cae365f03812.jpg",
-        },
-        {
-            id: 62,
-            sort: 0,
-            show_platform: 1,
-            action_type: 1,
-            action_params: "",
-            content: "http://192.168.0.237:9000/bcwin/9809de49-966e-4dea-81c9-baa71347dc6c.jpg",
-        },
-    ];
 
     return (
         <>
-            <div style={{ height: "1.86rem" }} className={"home-banner"}>
-                <Swiper
-                    autoplay={{ delay: 2500 }}
-                    pagination={{ clickable: true }}
-                    spaceBetween={10}
-                    scrollbar={{ draggable: true }}
-                    slidesPerView={1}
-                    loop
-                    modules={[Pagination, Autoplay]}
-                >
-                    {banners.map((banner, index) => (
-                        <SwiperSlide key={index}>
-                            <Box
-                                none
-                                action={banner.action_type as 1}
-                                actionData={banner.action_params}
-                            >
-                                <img
-                                    src={banner.content}
-                                    style={{ height: "1.86rem", width: "100%" }}
-                                    alt={"banner"}
-                                />
-                            </Box>
-                        </SwiperSlide>
-                    ))}
-                </Swiper>
-            </div>
+            <Image src={"/doings/recharge.jpg"} alt={"deposit"} width={1950} height={10} />
             <div className="deposit-box">
-                <p>title</p>
-                <p className={"text-[0.12rem] text-[#e8e8e8]"}>
-                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab accusamus amet
-                    animi beatae blanditiis cumque dicta dolor eius est ex, facilis illo libero
-                    magnam placeat quibusdam similique ullam, vel veniam?
-                </p>
+                <div className={"flex items-center"}>
+                    <div className="img-box"></div>
+                    <div className={"flex-1 text-right"}>
+                        <i
+                            className={"iconfont icon-star_full text-[0.15rem] text-primary-color"}
+                        ></i>
+                        {`{${count}} recargas restantes`}
+                    </div>
+                </div>
+
                 <div className={"flex flex-wrap"}>
                     {deposits.map((item, index) => {
                         return (
@@ -155,6 +114,11 @@ const DepositData: FC<Props> = (props) => {
                         initialValues={userInfo}
                         onFinish={onFinish}
                         onValuesChange={onValuesChange}
+                        footer={
+                            <>
+                                <ButtonOwn active>{t("DepositPage.DepositarAgora")}</ButtonOwn>
+                            </>
+                        }
                     >
                         {isStrictMode ? (
                             <>
@@ -184,21 +148,17 @@ const DepositData: FC<Props> = (props) => {
                                 </Form.Item>
                             </>
                         ) : null}
-                        {isCustomInput && (
-                            <Form.Item
-                                name="amount"
-                                label=""
-                                rules={[
-                                    { required: true, type: "number", validator: amountValidator },
-                                ]}
-                            >
-                                <Input
-                                    placeholder={`${t("DepositPage.Montante")}(BRL): Mín. ${activeType.min_amount}`}
-                                    type={"number"}
-                                    maxLength={activeType.max_amount}
-                                />
-                            </Form.Item>
-                        )}
+                        <Form.Item
+                            name="amount"
+                            label=""
+                            rules={[{ required: true, type: "number", validator: amountValidator }]}
+                        >
+                            <Input
+                                placeholder={`${t("DepositPage.Montante")}(BRL): Mín. ${activeType.min_amount}`}
+                                type={"number"}
+                                maxLength={activeType.max_amount}
+                            />
+                        </Form.Item>
 
                         <div className={"flex flex-col"}>
                             <div className={"flex-1"}>
@@ -225,13 +185,10 @@ const DepositData: FC<Props> = (props) => {
                         </div>
                     </Form>
                 </Box>
-                <ButtonOwn
-                    style={{ marginTop: "0.1389rem" }}
-                    active
-                    callbackFun={() => setIsCustomInput(true)}
-                >
-                    {t("DepositPage.customButtonText")}
-                </ButtonOwn>
+                <p className={"text-[#e59c5f]"}>Descrição daatividade:</p>
+                <p className={"text-[0.12rem] text-[#e59c5f]"}>
+                    Recarregue nas primeiras {`{${count}}`} vezes todos os dias e ganhe desco
+                </p>
             </div>
         </>
     );

+ 11 - 1
src/app/[locale]/(navbar)/doings/discount/layout.tsx

@@ -13,7 +13,17 @@ export default async function Layout({
     return (
         <>
             <HeaderBack showBack={true} title={t("deposit")} />
-            <main className={"main-header bg-[#24262b]"}>{children}</main>
+            <main
+                className={"main-header bg-[#24262b]"}
+                style={{
+                    backgroundImage:
+                        "linear-gradient(90deg,#2a2827 1px, rgba(0, 0, 0, 0.1)" +
+                        " 1px), linear-gradient(#2a2827 1px, rgba(0, 0, 0, 0.1) 1px)",
+                    backgroundSize: "40px 40px",
+                }}
+            >
+                {children}
+            </main>
         </>
     );
 }

+ 21 - 4
src/app/[locale]/(navbar)/withdraw/WithdrawWidget.tsx

@@ -1,9 +1,11 @@
 "use client";
+import { Wallet } from "@/api/user";
 import { ChannelType, getWithDrawApi, WithDrawType } from "@/api/withdraw";
 import { clearWallet } from "@/app/[locale]/(navbar)/withdraw/actions";
 import Box from "@/components/Box";
 import ButtonOwn from "@/components/ButtonOwn";
 import Empty from "@/components/Empty";
+import TipsModal, { ModalProps } from "@/components/TipsModal";
 import { useUserInfoStore } from "@/stores/useUserInfoStore";
 import { useWalletStore } from "@/stores/useWalletStore";
 import { isEmail } from "@/utils";
@@ -17,6 +19,7 @@ import "./page.scss";
 
 interface Props {
     channels: WithDrawType[];
+    wallet: Wallet;
 }
 
 export enum ChannelEnum {
@@ -98,10 +101,12 @@ const MobileField: FC<MobileFieldProps> = (props) => {
 };
 const WithdrawWidget: FC<Props> = (props) => {
     const t = useTranslations();
-    const { channels } = props;
+    const { channels, wallet } = props;
 
     const score = useWalletStore((state) => state.score)!;
 
+    const withdrawRef = useRef<ModalProps>(null);
+
     const formRef = useRef<FormInstance>(null);
 
     const [activeWallet, setActiveWallet] = useState<WithDrawType>(channels[0]);
@@ -182,7 +187,7 @@ const WithdrawWidget: FC<Props> = (props) => {
                 <div className="withdraw-box">
                     <div className="img-box"></div>
 
-                    <div className={"mb-[0.1rem] flex flex-wrap"}>
+                    <div className={"mb-[0.1rem] flex flex-wrap gap-[0.0347rem]"}>
                         {channels.map((item) => {
                             return (
                                 <Fragment key={item.id}>
@@ -278,11 +283,14 @@ const WithdrawWidget: FC<Props> = (props) => {
                         <ul className="ul-box">
                             <li>
                                 {t("WithdrawPage.SaqueDisponivel")}{" "}
-                                <span className="tip">0 BRL</span>
+                                <span className="tip">{wallet.score} BRL</span>
                             </li>
                             <li>
                                 {t("WithdrawPage.Valor")} <span className="tip">0 BRL</span>{" "}
-                                <span className="iconfont icon-iconhelp"></span>
+                                <span
+                                    className="iconfont icon-iconhelp"
+                                    onClick={() => withdrawRef.current?.onOpen()}
+                                ></span>
                             </li>
                             <li>
                                 {t("WithdrawPage.Para")},{" "}
@@ -294,6 +302,15 @@ const WithdrawWidget: FC<Props> = (props) => {
                     </Form>
                 </div>
             </Box>
+
+            <TipsModal title={"提现弹窗"} ref={withdrawRef}>
+                <ul>
+                    <li>1</li>
+                    <li>2</li>
+                    <li>3</li>
+                    <li>4</li>
+                </ul>
+            </TipsModal>
         </>
     );
 };

+ 3 - 1
src/app/[locale]/(navbar)/withdraw/page.tsx

@@ -1,3 +1,4 @@
+import { getMoneyApi } from "@/api/userWallt";
 import { WithDrawType } from "@/api/withdraw";
 import { server } from "@/utils/server";
 import WithdrawWidget from "./WithdrawWidget";
@@ -22,7 +23,8 @@ const getWithdrawApi = async () => {
 
 const Page = async () => {
     const data = await getWithdrawApi();
-    return <WithdrawWidget channels={data} />;
+    const wallet = await getMoneyApi();
+    return <WithdrawWidget channels={data} wallet={wallet} />;
 };
 
 export default Page;

+ 0 - 35
src/app/[locale]/(wallet)/components/WalletHeader.tsx

@@ -1,35 +0,0 @@
-import Box from "@/components/Box";
-import Image from "next/image";
-import WalletProgress from "./WalletProgress";
-
-const WalletHeader = () => {
-    return (
-        <div>
-            <Box
-                className={"bg-gradient-to-b from-[#ffaa30] to-[#ffe6be] text-[16px] text-[black]"}
-            >
-                <div className={"flex items-center"}>
-                    <span>余额</span>
-                    <Image
-                        className={"ml-[0.0694rem] h-[0.13rem] w-[0.13rem]"}
-                        src="/img/a.png"
-                        alt="question"
-                        width={10}
-                        height={10}
-                    />
-                </div>
-                <div>
-                    <span>BRL</span>
-                    <span>0.00</span>
-                </div>
-                <WalletProgress />
-                <div>
-                    <span>剩余打码量:</span>
-                    <span>BRL 5555</span>
-                </div>
-            </Box>
-        </div>
-    );
-};
-
-export default WalletHeader;

+ 78 - 0
src/app/[locale]/(wallet)/free/WalletHeader.tsx

@@ -0,0 +1,78 @@
+"use client";
+import { Wallet } from "@/api/user";
+import Box from "@/components/Box";
+import TipsModal, { ModalProps } from "@/components/TipsModal";
+import { percentage } from "@/utils/methods";
+import { ProgressBar } from "antd-mobile";
+import { useTranslations } from "next-intl";
+import Image from "next/image";
+import { FC, useRef } from "react";
+interface Props {
+    wallet: Wallet;
+}
+const WalletHeader: FC<Props> = (props) => {
+    const { wallet } = props;
+
+    const modalRef = useRef<ModalProps>(null);
+    const t = useTranslations("freePage");
+    return (
+        <div>
+            <Box
+                className={"bg-gradient-to-b from-[#ffaa30] to-[#ffe6be] text-[16px] text-[black]"}
+            >
+                <div className={"flex items-center"}>
+                    <span>余额</span>
+                    <Image
+                        className={"ml-[0.0694rem] h-[0.13rem] w-[0.13rem]"}
+                        src="/img/a.png"
+                        alt="question"
+                        width={10}
+                        height={10}
+                        onClick={() => modalRef.current?.onOpen()}
+                    />
+                </div>
+                <div>
+                    <span>BRL:</span>
+                    <span>{wallet.free_score}</span>
+                </div>
+                <div className={"flex"}>
+                    <ProgressBar
+                        percent={percentage(
+                            wallet.current_free_score_rollover,
+                            wallet.target_free_score_rollover
+                        )}
+                        className={"flex-1"}
+                        style={{
+                            "--fill-color": "#fb8b05",
+                            "--track-width": "0.0694rem",
+                        }}
+                    />
+                    <span className={"w-[0.5556rem] text-center"}>
+                        {percentage(
+                            wallet.current_free_score_rollover,
+                            wallet.target_free_score_rollover
+                        )}
+                        %
+                    </span>
+                </div>
+                <div>
+                    <span>剩余打码量:</span>
+                    <span>
+                        {wallet.target_free_score_rollover - wallet.current_free_score_rollover}
+                    </span>
+                </div>
+            </Box>
+
+            <TipsModal ref={modalRef} title={t("title")}>
+                <ul className={"list-decimal p-[0.1389rem] pt-0 text-[0.12rem]"}>
+                    <li>{t("desc1")}</li>
+                    <li>{t("desc2")}</li>
+                    <li>{t("desc3")}</li>
+                    <li>{t("desc4")}</li>
+                </ul>
+            </TipsModal>
+        </div>
+    );
+};
+
+export default WalletHeader;

+ 7 - 6
src/app/[locale]/(wallet)/free/page.tsx

@@ -1,11 +1,12 @@
-import WalletHeader from "../components/WalletHeader";
-import WalletTabs from "./WalletTabs";
-
-const Page = () => {
+import { getMoneyApi } from "@/api/userWallt";
+import WalletHeader from "./WalletHeader";
+const Page = async () => {
+    const userWallet = await getMoneyApi();
+    console.log(`🚀🚀🚀🚀🚀-> in page.tsx on 5`, userWallet);
     return (
         <>
-            <WalletHeader />
-            <WalletTabs />
+            <WalletHeader wallet={userWallet} />
+            {/*<WalletTabs />*/}
         </>
     );
 };

+ 78 - 0
src/app/[locale]/(wallet)/replay/WalletHeader.tsx

@@ -0,0 +1,78 @@
+"use client";
+import { Wallet } from "@/api/user";
+import Box from "@/components/Box";
+import TipsModal, { ModalProps } from "@/components/TipsModal";
+import { percentage } from "@/utils/methods";
+import { ProgressBar } from "antd-mobile";
+import { useTranslations } from "next-intl";
+import Image from "next/image";
+import { FC, useRef } from "react";
+interface Props {
+    wallet: Wallet;
+}
+const WalletHeader: FC<Props> = (props) => {
+    const { wallet } = props;
+
+    const modalRef = useRef<ModalProps>(null);
+    const t = useTranslations("replayPage");
+    return (
+        <div>
+            <Box
+                className={"bg-gradient-to-b from-[#ffaa30] to-[#ffe6be] text-[16px] text-[black]"}
+            >
+                <div className={"flex items-center"}>
+                    <span>余额</span>
+                    <Image
+                        className={"ml-[0.0694rem] h-[0.13rem] w-[0.13rem]"}
+                        src="/img/a.png"
+                        alt="question"
+                        width={10}
+                        height={10}
+                        onClick={() => modalRef.current?.onOpen()}
+                    />
+                </div>
+                <div>
+                    <span>BRL:</span>
+                    <span>{wallet.lose_score}</span>
+                </div>
+                <div className={"flex"}>
+                    <ProgressBar
+                        percent={percentage(
+                            wallet.current_lose_score_rollover,
+                            wallet.target_lose_score_rollover
+                        )}
+                        className={"flex-1"}
+                        style={{
+                            "--fill-color": "#fb8b05",
+                            "--track-width": "0.0694rem",
+                        }}
+                    />
+                    <span className={"w-[0.5556rem] text-center"}>
+                        {percentage(
+                            wallet.current_lose_score_rollover,
+                            wallet.target_lose_score_rollover
+                        )}
+                        %
+                    </span>
+                </div>
+                <div>
+                    <span>剩余打码量:</span>
+                    <span>
+                        {wallet.target_lose_score_rollover - wallet.current_lose_score_rollover}
+                    </span>
+                </div>
+            </Box>
+
+            <TipsModal ref={modalRef} title={t("title")}>
+                <ul className={"list-decimal p-[0.1389rem] pt-0 text-[0.12rem]"}>
+                    <li>{t("desc1")}</li>
+                    <li>{t("desc2")}</li>
+                    <li>{t("desc3")}</li>
+                    <li>{t("desc4")}</li>
+                </ul>
+            </TipsModal>
+        </div>
+    );
+};
+
+export default WalletHeader;

+ 1 - 1
src/app/[locale]/(wallet)/replay/layout.tsx

@@ -12,7 +12,7 @@ export default async function Layout({
     const t = await getTranslations("ProfilePage");
     return (
         <>
-            <HeaderBack showBack={true} title={t("free")} />
+            <HeaderBack showBack={true} title={t("replay")} />
             <main className={"main-header bg-[rgb(36,38,43)]"}>{children}</main>
         </>
     );

+ 10 - 2
src/app/[locale]/(wallet)/replay/page.tsx

@@ -1,5 +1,13 @@
-const Page = () => {
-    return <div>Page</div>;
+import { getMoneyApi } from "@/api/userWallt";
+import WalletHeader from "./WalletHeader";
+const Page = async () => {
+    const userWallet = await getMoneyApi();
+    return (
+        <>
+            <WalletHeader wallet={userWallet} />
+            {/*<WalletTabs />*/}
+        </>
+    );
 };
 
 export default Page;

+ 9 - 8
src/components/Box/Desktop.tsx

@@ -1,9 +1,8 @@
 "use client";
-import { useSystemStore } from "@/stores/useSystemStore";
 import { Button, Popup } from "antd-mobile";
 import { useTranslations } from "next-intl";
 import Image from "next/image";
-import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react";
+import { forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react";
 
 /**
  * @description 检测pwa是否下载
@@ -30,6 +29,7 @@ const Desktop = forwardRef<DesktopRefProps, Props>(function Desktop(props, ref)
     // });
     const [isHasDesktop, setHasDesktop] = useState(false);
     const downloadHandler = () => {
+        sessionStorage.setItem("pwa_install", "cancel");
         // @ts-ignore
         prompt.current?.prompt();
         // 不判断是否真的包含
@@ -37,16 +37,13 @@ const Desktop = forwardRef<DesktopRefProps, Props>(function Desktop(props, ref)
     };
 
     const initDesktop = (e: Event) => {
-        console.log(`🚀🚀🚀🚀🚀-> in Desktop.tsx on 40`, source);
-        if (source === "components") return;
         if (window.matchMedia("(display-mode: standalone)").matches) {
             setHasDesktop(false);
             return;
         }
         // 有pwa 则不会触发
         prompt.current = e;
-        // 只触发一次
-        if (useSystemStore.getState().isHasDesktop === undefined) {
+        if (source === "page" && sessionStorage.getItem("pwa_install") === null) {
             setHasDesktop(true);
         }
     };
@@ -69,6 +66,10 @@ const Desktop = forwardRef<DesktopRefProps, Props>(function Desktop(props, ref)
             },
         };
     });
+    const cancel = () => {
+        sessionStorage.setItem("pwa_install", "cancel");
+        setHasDesktop(false);
+    };
     return (
         <Popup
             visible={!!isHasDesktop}
@@ -91,7 +92,7 @@ const Desktop = forwardRef<DesktopRefProps, Props>(function Desktop(props, ref)
                     className={"mr-[10px]"}
                     style={{ "--text-color": "#8d8d8d" }}
                     fill="none"
-                    onClick={() => setHasDesktop(false)}
+                    onClick={cancel}
                 >
                     {t("cancel")}
                 </Button>
@@ -111,4 +112,4 @@ const Desktop = forwardRef<DesktopRefProps, Props>(function Desktop(props, ref)
         </Popup>
     );
 });
-export default Desktop;
+export default memo(Desktop);

+ 4 - 3
src/components/Box/index.tsx

@@ -7,7 +7,7 @@ import { isHttpUrl } from "@/utils";
 import { getToken } from "@/utils/Cookies";
 import { Toast } from "antd-mobile";
 import clsx from "clsx";
-import { CSSProperties, FC, PropsWithChildren, useRef } from "react";
+import { CSSProperties, FC, PropsWithChildren, useMemo, useRef } from "react";
 import { twMerge } from "tailwind-merge";
 import DesktopModal, { DesktopRefProps } from "./Desktop";
 import { ModalEnum } from "./types";
@@ -63,10 +63,11 @@ const Box: FC<PropsWithChildren<Props>> = (props) => {
     const packetModalRef = useRef<RedPacketModalProps>(null);
     const pwaModalRef = useRef<DesktopRefProps>(null);
 
+    const pwaModal = useMemo(() => <DesktopModal ref={pwaModalRef} source={"components"} />, []);
+
     /**
      * @description 弹窗类型
      */
-
     const popupHandler = (actionData: keyof typeof ModalEnum) => {
         console.log(`🚀🚀🚀🚀🚀-> in index.tsx on 71`, actionData);
         switch (actionData) {
@@ -144,7 +145,7 @@ const Box: FC<PropsWithChildren<Props>> = (props) => {
             </Tag>
 
             <RedPacketModal ref={packetModalRef} />
-            <DesktopModal ref={pwaModalRef} source={"components"} />
+            {pwaModal}
         </>
     );
 };

+ 3 - 0
src/utils/methods/index.ts

@@ -75,6 +75,9 @@ export let copyText = function (text: string) {
 
 /**
  * @description 两个数值计算百分比
+ * @param {current} 当前值
+ * @param {source} 总值
+ * @return number
  */
 export const percentage = (current: number, source: number) => {
     return (current * 100) / source;