Prechádzať zdrojové kódy

fix: 更新站内信提示

Before 7 mesiacov pred
rodič
commit
514d1bee0c

+ 7 - 0
src/api/home.ts

@@ -261,6 +261,13 @@ export const getGlobalNoticeApi = () => {
         data: {},
     });
 };
+
+export const getGlobalUserNoticeApi = () => {
+    return server.post<NoticeRep[], { summery: { unread: number } }>({
+        url: "/v1/api/front/notice_user_list",
+        data: {},
+    });
+};
 // 系统通知信息回执
 // POST /v1/api/front/notice_user_receipt
 // 接口ID:224339957

+ 5 - 4
src/app/[locale]/(TabBar)/[[...share]]/@actionWidget/Service.tsx

@@ -59,7 +59,7 @@ const ServiceWidget: FC<Props> = (props) => {
                 wheelModalRef.current?.onOpen(res);
                 return;
             }
-            if (res && res.not_receive.length > 0) {
+            if (res && res.not_receive && res.not_receive.length > 0) {
                 setVisibleWheel(2);
                 return;
             }
@@ -67,8 +67,9 @@ const ServiceWidget: FC<Props> = (props) => {
     }, []);
 
     const t = useTranslations("HomePage");
-    const { unread } = useGlobalNoticeStore((state) => ({
+    const { unread, userUnred } = useGlobalNoticeStore((state) => ({
         unread: state.unread,
+        userUnred: state.userUnred,
     }));
 
     const getRedPacketInfo = async () => {
@@ -179,7 +180,7 @@ const ServiceWidget: FC<Props> = (props) => {
                 })}
 
                 {/*未读消息*/}
-                {unread ? (
+                {unread || userUnred ? (
                     <Link
                         href={"/notification"}
                         className={
@@ -188,7 +189,7 @@ const ServiceWidget: FC<Props> = (props) => {
                             " to-[#ffcf35]"
                         }
                     >
-                        <Badge content={!!unread ? unread : null} style={{ "--top": "12px" }}>
+                        <Badge content={userUnred + unread} style={{ "--top": "12px" }}>
                             <i
                                 className={"iconfont icon-duanxinguanli text-[0.3rem] text-[#fff]"}
                             ></i>

+ 7 - 2
src/app/[locale]/(TabBar)/profile/component/ModalCom/index.tsx

@@ -8,7 +8,7 @@ import { CenterPopup } from "antd-mobile";
 import dayjs from "dayjs";
 import Cookies from "js-cookie";
 import { useTranslations } from "next-intl";
-import { FC, PropsWithChildren, useState } from "react";
+import { FC, PropsWithChildren, useEffect, useRef, useState } from "react";
 import "./style.scss";
 
 /**
@@ -27,6 +27,7 @@ const ModalCom: FC<PropsWithChildren<ItemComProps>> = () => {
 
     // const { isOpen, onOpen, onClose, onOpenChange } = useDisclosure();
     const [visible, setVisible] = useState(false);
+    const element = useRef<HTMLElement | null>(null);
     const logoutRequest = async () => {
         let res = await getLogoutApi();
         const isClearPromotion = dayjs().isSame(sessionStorage.getItem("isClosePromotion"), "days");
@@ -48,6 +49,10 @@ const ModalCom: FC<PropsWithChildren<ItemComProps>> = () => {
         router.push(path);
     };
 
+    useEffect(() => {
+        element.current = document.getElementById("app");
+    }, []);
+
     return (
         <>
             {/* {
@@ -64,7 +69,7 @@ const ModalCom: FC<PropsWithChildren<ItemComProps>> = () => {
 
             <CenterPopup
                 visible={visible}
-                getContainer={() => document.getElementById("app")!}
+                getContainer={element.current}
                 onMaskClick={() => {
                     setVisible(false);
                 }}

+ 58 - 0
src/app/[locale]/(navbar)/notification/NotificationClient.tsx

@@ -0,0 +1,58 @@
+"use client";
+import { GlobalNoticeRep, updateGlobalNoticeApi, updateUserNoticeApi } from "@/api/home";
+import Tabs from "@/components/Tabs";
+import { useTranslations } from "next-intl";
+import { FC, useState } from "react";
+import actions from "./actions";
+import { default as Notices } from "./components/Notices";
+
+interface Props {
+    systemNotices: GlobalNoticeRep[];
+    userNotices: GlobalNoticeRep[];
+}
+const setReadData = (data: GlobalNoticeRep[], key: number) => {
+    const newNotices = data.map((item) => {
+        if (item.id === key && !item.is_read) {
+            return { ...item, is_read: true };
+        } else {
+            return item;
+        }
+    });
+    return newNotices;
+};
+const NotificationClient: FC<Props> = (props) => {
+    const [systemNotices, setSystemNotices] = useState(props.systemNotices);
+    const [userNotices, setUserNotices] = useState(props.userNotices);
+    const t = useTranslations("ProfilePage");
+    const handler = async (active: string, key: string) => {
+        if (key === "system") {
+            const isRead = systemNotices.find((item) => item.id === +active)?.is_read;
+            if (isRead) return;
+            updateGlobalNoticeApi(+active).then((r) => {});
+            setSystemNotices(setReadData(systemNotices, +active));
+        } else {
+            const isRead = userNotices.find((item) => item.id === +active)?.is_read;
+            if (isRead) return;
+            setUserNotices(setReadData(userNotices, +active));
+            updateUserNoticeApi(+active).then((r) => {});
+        }
+
+        await actions();
+    };
+    const defaultTabs = [
+        {
+            id: 1,
+            name: t("systemMessage"),
+            content: systemNotices.reduce((count, notice) => count + (notice.is_read ? 0 : 1), 0),
+            render: <Notices data={systemNotices} type={"system"} handler={handler} />,
+        },
+        {
+            id: 2,
+            name: t("personalMessage"),
+            content: userNotices.reduce((count, notice) => count + (notice.is_read ? 0 : 1), 0),
+            render: <Notices data={userNotices} type={"user"} handler={handler} />,
+        },
+    ];
+    return <Tabs items={defaultTabs} />;
+};
+export default NotificationClient;

+ 8 - 0
src/app/[locale]/(navbar)/notification/actions.ts

@@ -0,0 +1,8 @@
+"use server";
+import { revalidatePath } from "next/cache";
+
+const actions = () => {
+    return revalidatePath("/notification", "page");
+};
+
+export default actions;

+ 18 - 27
src/app/[locale]/(navbar)/notification/components/Notices.tsx

@@ -1,55 +1,46 @@
 "use client";
-import { GlobalNoticeRep, updateGlobalNoticeApi, updateUserNoticeApi } from "@/api/home";
+import { GlobalNoticeRep } from "@/api/home";
 import Box from "@/components/Box";
 import Empty from "@/components/Empty";
 import { timeFormat } from "@/utils/methods";
 import { Badge, Collapse } from "antd-mobile";
 import { useLocale } from "next-intl";
-import { useState } from "react";
 import style from "./style.module.scss";
 interface Props {
     data: GlobalNoticeRep[];
     type: "system" | "user";
+    handler: (active: string, key: Props["type"]) => void;
 }
 const SystemMessage = (props: Props) => {
-    const { data, type } = props;
+    const { data, type, handler } = props;
     const locale = useLocale();
-    const [noticesData, setNoticesData] = useState<GlobalNoticeRep[]>(data);
 
-    const collapseChange = (active: string | null) => {
+    const collapseChange = async (active: string | null) => {
         if (!active) return;
-        const isRead = noticesData.find((item) => item.id === +active)?.is_read;
-        if (isRead) return;
-        const newNotices = noticesData.map((item) => {
-            if (item.id === +active && !item.is_read) {
-                return { ...item, is_read: true };
-            } else {
-                return item;
-            }
-        });
-        if (type === "system") {
-            updateGlobalNoticeApi(+active).then((r) => {});
-        } else {
-            updateUserNoticeApi(+active);
-        }
-        setNoticesData(newNotices);
+        handler && handler(active, type);
     };
-    if (!noticesData.length) return <Empty />;
+    if (!data.length) return <Empty />;
     return (
         <div className={style.messageCollapse}>
             <Collapse accordion onChange={collapseChange}>
-                {noticesData.map((notice, index) => (
+                {data.map((notice, index) => (
                     <Collapse.Panel
                         key={`${notice.id}`}
+                        arrowIcon={
+                            <div>
+                                <Badge
+                                    className={`mr-[0.1rem] h-[0.06rem] w-[0.06rem]`}
+                                    style={{ "--color": "#ff311b" }}
+                                    content={!notice.is_read ? Badge.dot : ""}
+                                ></Badge>
+
+                                <span className={"iconfont icon-zhankai"} />
+                            </div>
+                        }
                         title={
                             <section>
                                 <header className={"flex items-center"}>
                                     <h6 className={""}>{notice.content?.title}</h6>
-                                    <Badge
-                                        className={`ml-[0.1rem] h-[0.06rem] w-[0.06rem]`}
-                                        style={{ "--color": "#ff311b" }}
-                                        content={!notice.is_read ? Badge.dot : ""}
-                                    ></Badge>
                                 </header>
                                 <p className={"text-[12px] text-[#64676d]"}>
                                     {notice.send_time

+ 2 - 19
src/app/[locale]/(navbar)/notification/page.tsx

@@ -1,8 +1,6 @@
 import { GlobalNoticeRep } from "@/api/home";
-import Tabs from "@/components/Tabs";
+import NotificationClient from "@/app/[locale]/(navbar)/notification/NotificationClient";
 import { server } from "@/utils/server";
-import { getTranslations } from "next-intl/server";
-import Notices from "./components/Notices";
 
 const getSystemNotifications = async () => {
     return server.request<GlobalNoticeRep[]>({
@@ -21,24 +19,9 @@ const getUserNotices = () => {
 const Notification = async () => {
     const systemNotices = await getSystemNotifications();
     const userNotices = await getUserNotices();
-    const t = await getTranslations("ProfilePage");
-    const defaultTabs = [
-        {
-            id: 1,
-            name: t("systemMessage"),
-            content: 0,
-            render: <Notices data={systemNotices.data} type={"system"} />,
-        },
-        {
-            id: 2,
-            name: t("personalMessage"),
-            content: 0,
-            render: <Notices data={userNotices.data} type={"user"} />,
-        },
-    ];
     return (
         <div className={"overflow-visible"}>
-            <Tabs items={defaultTabs} />
+            <NotificationClient systemNotices={systemNotices.data} userNotices={userNotices.data} />
         </div>
     );
 };

+ 6 - 1
src/components/Box/RedPacketModal.tsx

@@ -405,6 +405,7 @@ const RedPacketModal = forwardRef<RedPacketModalProps, Props>(function RedPacket
     const [redAmount, setRedAmount] = useState<any>(1);
     const activeIndex = useRef<number>(0);
     const token = getToken();
+    const element = useRef<HTMLElement | null>(null);
     useImperativeHandle(ref, () => {
         return {
             onClose: () => setVisible(false),
@@ -475,8 +476,12 @@ const RedPacketModal = forwardRef<RedPacketModalProps, Props>(function RedPacket
             console.log("redPacketInfo===>error:", error);
         }
     };
+
+    useEffect(() => {
+        element.current = document.getElementById("app");
+    }, []);
     return (
-        <Mask visible={visible} destroyOnClose={true} getContainer={document.getElementById("app")}>
+        <Mask visible={visible} destroyOnClose={true} getContainer={element.current}>
             <FallAnimation onClose={() => setVisible(false)} />
 
             {status === Status.is_start ? (

+ 22 - 3
src/components/Footer/index.tsx

@@ -1,5 +1,5 @@
 "use client";
-import { getGlobalNoticeApi } from "@/api/home";
+import { getGlobalNoticeApi, getGlobalUserNoticeApi } from "@/api/home";
 import { Link, usePathname, useRouter } from "@/i18n/routing";
 import { getToken } from "@/utils/Cookies";
 import { Badge } from "antd-mobile";
@@ -67,9 +67,11 @@ const Footer: FC = () => {
         router.push(path);
     };
 
-    const { unread, setNotices } = useGlobalNoticeStore((state) => ({
+    const { unread, userUnred, setNotices, setUserUnread } = useGlobalNoticeStore((state) => ({
         unread: state.unread,
         setNotices: state.setNotices,
+        setUserUnread: state.setUserUnread,
+        userUnred: state.userUnred,
     }));
 
     const setWallet = useWalletStore((state) => state.setWallet);
@@ -83,6 +85,16 @@ const Footer: FC = () => {
         },
     });
 
+    const { run: userRun } = useRequest(getGlobalUserNoticeApi, {
+        pollingInterval: 10000,
+        manual: true,
+        pollingErrorRetryCount: 3,
+        pollingWhenHidden: false,
+        onSuccess: (data) => {
+            setUserUnread(data.summery.unread || 0);
+        },
+    });
+
     const { run: walletRun } = useRequest(getUserMoneyApi, {
         pollingInterval: 5000,
         pollingWhenHidden: true,
@@ -100,6 +112,7 @@ const Footer: FC = () => {
         if (getToken()) {
             run();
             walletRun();
+            userRun();
         }
     }, []);
 
@@ -122,7 +135,13 @@ const Footer: FC = () => {
                                             <i className="icon-rs"></i>
                                         </>
                                     ) : (
-                                        <Badge content={index === 4 && unread ? Badge.dot : null}>
+                                        <Badge
+                                            content={
+                                                (index === 4 && unread) || userUnred
+                                                    ? Badge.dot
+                                                    : null
+                                            }
+                                        >
                                             <span
                                                 className={clsx("iconfont", item.iconSpanName)}
                                             ></span>

+ 1 - 8
src/components/Tabs/index.tsx

@@ -10,11 +10,6 @@ interface Item {
 interface Props {
     items: Item[];
 }
-const defaultTabs = [
-    { id: 1, name: "deposits", content: 0 },
-    { id: 2, name: "saques", content: 0 },
-    { id: 3, name: "bonus", content: 0 },
-];
 
 const Transactions: FC<PropsWithChildren<Props>> = (props) => {
     const { items } = props;
@@ -38,10 +33,8 @@ const Transactions: FC<PropsWithChildren<Props>> = (props) => {
                                 style={{
                                     "--right": "-10px",
                                     "--top": "8px",
-                                    // @ts-ignore
-                                    "--adm-color-text-light-solid": "#000",
                                 }}
-                                color={"#f0dc00"}
+                                color={"#ff311b"}
                             >
                                 {tab.name}
                             </Badge>

+ 5 - 0
src/stores/useGlobalNoticeStore.ts

@@ -5,6 +5,7 @@ import { create } from "zustand";
 interface State {
     sourceMap: Map<number, NoticeRep>;
     unread: number; // 未读数量
+    userUnred: number; // 未读数量
     notices: NoticeRep[]; // 总数据
 }
 
@@ -13,11 +14,13 @@ interface Action {
     hasValue: (key: number) => boolean;
     setNotices: (notices: NoticeRep[], unread: number) => void;
     setReadNotices: (id: number) => Promise<Result<any>>;
+    setUserUnread: (value: number) => void;
 }
 
 const initialState: State = {
     sourceMap: new Map(),
     unread: 0,
+    userUnred: 0,
     notices: [],
 };
 
@@ -33,6 +36,8 @@ export const useGlobalNoticeStore = create<State & Action>()((set, get) => {
 
         hasValue: (key) => get().sourceMap.has(key),
         setNotices: (notices, unread: number) => set((state) => ({ ...state, notices, unread })),
+
+        setUserUnread: (value: number) => set((state) => ({ ...state, userUnred: value })),
         setReadNotices: (id: number) => {
             return updateGlobalNoticeApi(id);
         },