添加私聊功能
|
@ -5,13 +5,10 @@ import {useRouter} from "next/navigation";
|
||||||
import requireAPI from "@/utils/requireAPI";
|
import requireAPI from "@/utils/requireAPI";
|
||||||
export default function BillDetail({ params }) {
|
export default function BillDetail({ params }) {
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
const [isFetching, setIsFetching] = useState(true);
|
const [isFetching, setIsFetching] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
getData();
|
getData();
|
||||||
}, 500);
|
|
||||||
}, []);
|
}, []);
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
let type;
|
let type;
|
||||||
|
@ -32,6 +29,7 @@ export default function BillDetail({ params }) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
setIsFetching(true);
|
||||||
const _data = await requireAPI(
|
const _data = await requireAPI(
|
||||||
"POST",
|
"POST",
|
||||||
"/api/vas/get_ch_list",
|
"/api/vas/get_ch_list",
|
||||||
|
@ -86,7 +84,7 @@ export default function BillDetail({ params }) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{data.length === 0 && (
|
{data.length === 0 && (
|
||||||
<div className="flex flex-col mt-4 w-full items-center">
|
<div className="flex flex-col mt-14 w-full items-center">
|
||||||
<svg viewBox="0 0 1024 1024" width="120" height="120">
|
<svg viewBox="0 0 1024 1024" width="120" height="120">
|
||||||
<path
|
<path
|
||||||
d="M102.4 896a409.6 51.2 0 1 0 819.2 0 409.6 51.2 0 1 0-819.2 0Z"
|
d="M102.4 896a409.6 51.2 0 1 0 819.2 0 409.6 51.2 0 1 0-819.2 0Z"
|
||||||
|
|
|
@ -33,12 +33,23 @@ export const viewport = {
|
||||||
};
|
};
|
||||||
export default function RootLayout({ children }) {
|
export default function RootLayout({ children }) {
|
||||||
return (
|
return (
|
||||||
<html lang="zh-CN" className="bg-deepBg h-full" data-prefers-color-scheme="dark">
|
<html
|
||||||
<Head>
|
lang="zh-CN"
|
||||||
|
className="bg-deepBg h-full"
|
||||||
|
data-prefers-color-scheme="dark"
|
||||||
|
>
|
||||||
|
<head>
|
||||||
<title>{metadata.title}</title>
|
<title>{metadata.title}</title>
|
||||||
<meta name="description" content={metadata.description} keywords={metadata.keywords}/>
|
<link rel="icon" href="/favicon.ico" type="image/x-icon"></link>
|
||||||
</Head>
|
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"></link>
|
||||||
<body className={`${inter.className } h-full`}>
|
<link rel="icon" href="/favicon.png" type="image/png"></link>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content={metadata.description}
|
||||||
|
keywords={metadata.keywords}
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body className={`${inter.className} h-full`}>
|
||||||
<main className={`w-full bg-deepBg h-full`}>
|
<main className={`w-full bg-deepBg h-full`}>
|
||||||
{withAuth(<Provider store={store}>{children}</Provider>)}
|
{withAuth(<Provider store={store}>{children}</Provider>)}
|
||||||
{/* <Provider store={store}>{children}</Provider> */}
|
{/* <Provider store={store}>{children}</Provider> */}
|
||||||
|
|
|
@ -5,10 +5,11 @@ import React, { useState, useRef, useEffect, useCallback } from "react";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faAngleLeft } from "@fortawesome/free-solid-svg-icons";
|
import { faAngleLeft } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { Input, Button, Toast, Avatar, DotLoading } from "antd-mobile";
|
import { Input, Button, Toast, Avatar, DotLoading } from "antd-mobile";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import { get } from "@/utils/storeInfo";
|
import { get } from "@/utils/storeInfo";
|
||||||
import requireAPI from "@/utils/requireAPI";
|
import requireAPI from "@/utils/requireAPI";
|
||||||
import { formatDeadline } from "@/utils/tools";
|
import { formatDeadline } from "@/utils/tools";
|
||||||
|
import { getStreamerDetailInfo } from "@/api/space";
|
||||||
/*
|
/*
|
||||||
params格式:
|
params格式:
|
||||||
{
|
{
|
||||||
|
@ -19,6 +20,7 @@ params格式:
|
||||||
export default function MessageDetail({}) {
|
export default function MessageDetail({}) {
|
||||||
// const [hasMore, setHasMore] = useState(true);
|
// const [hasMore, setHasMore] = useState(true);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
const [oldMessages, setOldMessages] = useState([]);
|
const [oldMessages, setOldMessages] = useState([]);
|
||||||
const [messages, setMessages] = useState([]);
|
const [messages, setMessages] = useState([]);
|
||||||
const [handledmessages, setHandledmessages] = useState([]);
|
const [handledmessages, setHandledmessages] = useState([]);
|
||||||
|
@ -26,15 +28,33 @@ export default function MessageDetail({}) {
|
||||||
const [userInfo, setUserInfo] = useState(null);
|
const [userInfo, setUserInfo] = useState(null);
|
||||||
const [newMessage, setNewMessage] = useState("");
|
const [newMessage, setNewMessage] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [offset, setOffset] = useState(0);
|
const [offset, setOffset] = useState(0);
|
||||||
const [more, setMore] = useState(1);
|
const [more, setMore] = useState(1);
|
||||||
const scrollBox = useRef();
|
const scrollBox = useRef();
|
||||||
const toScrollBottom = useRef(0);
|
const toScrollBottom = useRef(0);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const userData = get("account");
|
const userData = get("account");
|
||||||
|
const mid = searchParams.get("mid")
|
||||||
|
if (mid) {
|
||||||
|
getStreamerDetailInfo(Number(mid)).then(data=>{
|
||||||
|
setMessages([[{
|
||||||
|
predicate: 1,
|
||||||
|
_id: 1,
|
||||||
|
createdAt: new Date()/1000,
|
||||||
|
text: data?.streamer_ext.auto_response_message,
|
||||||
|
user: {
|
||||||
|
_id: 0,
|
||||||
|
name: "客服",
|
||||||
|
avatar: data?.streamer_ext?.avatar?.images[0]?.urls[0],
|
||||||
|
},
|
||||||
|
}]]);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
setUserInfo(userData);
|
setUserInfo(userData);
|
||||||
getSession(userData.mid);
|
getSession(userData.mid);
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const intervalId = setInterval(() => {
|
const intervalId = setInterval(() => {
|
||||||
|
@ -262,7 +282,7 @@ export default function MessageDetail({}) {
|
||||||
user: {
|
user: {
|
||||||
_id: 0,
|
_id: 0,
|
||||||
name: "客服",
|
name: "客服",
|
||||||
avatar: process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"images/icon.png",
|
avatar: process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "images/icon.png",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -369,7 +389,7 @@ export default function MessageDetail({}) {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="my-[57px]">
|
<div className="my-[57px]">
|
||||||
<div className="flex justify-center py-2">
|
{searchParams.get("mid")=="" && <div className="flex justify-center py-2">
|
||||||
<div className="px-3 py-2 rounded-full bg-[#FFFFFF1A]">
|
<div className="px-3 py-2 rounded-full bg-[#FFFFFF1A]">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<DotLoading />
|
<DotLoading />
|
||||||
|
@ -379,7 +399,7 @@ export default function MessageDetail({}) {
|
||||||
<span>无更早消息</span>
|
<span>无更早消息</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>}
|
||||||
<ul className="py-2">
|
<ul className="py-2">
|
||||||
{messages?.map((item, index) => (
|
{messages?.map((item, index) => (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
|
@ -433,6 +453,7 @@ export default function MessageDetail({}) {
|
||||||
{/* <InfiniteScroll loadMore={loadMore} hasMore={more} /> */}
|
{/* <InfiniteScroll loadMore={loadMore} hasMore={more} /> */}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{searchParams.get("mid")=="" && (
|
||||||
<div className="w-full h-16 fixed bottom-0 grid grid-cols-[1fr_68px] bg-black items-center p-2 border-t-2 border-[#ffffff2a]">
|
<div className="w-full h-16 fixed bottom-0 grid grid-cols-[1fr_68px] bg-black items-center p-2 border-t-2 border-[#ffffff2a]">
|
||||||
<div className="rounded bg-[#222036] px-4 py-2 mr-2">
|
<div className="rounded bg-[#222036] px-4 py-2 mr-2">
|
||||||
<Input
|
<Input
|
||||||
|
@ -453,6 +474,7 @@ export default function MessageDetail({}) {
|
||||||
发送
|
发送
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -472,7 +472,7 @@ export default function PersonSpace() {
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="text-base bg-[#FFFFFF1A] py-1 px-6 rounded-full"
|
className="text-base bg-[#FFFFFF1A] py-1 px-6 rounded-full"
|
||||||
// onClick={() => handleFollow(isFollow, Number(mid), setIsFollow)}
|
onClick={() => router.push("/messageDetail?mid="+streamerInfo?.streamer_ext?.mid)}
|
||||||
>
|
>
|
||||||
私聊
|
私聊
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -168,10 +168,11 @@ const ZoneItem = ({ data, showMore, link,search }) => {
|
||||||
className="grid grid-cols-[2.5rem_100%] gap-2 items-center"
|
className="grid grid-cols-[2.5rem_100%] gap-2 items-center"
|
||||||
style={{ maxWidth: "calc(100vw - 2rem)" }}
|
style={{ maxWidth: "calc(100vw - 2rem)" }}
|
||||||
>
|
>
|
||||||
<img
|
<Image
|
||||||
className="flex-none w-10 h-10 rounded-full mr-2"
|
className="flex-none w-10 h-10 rounded-full mr-2"
|
||||||
src={data?.avatar?.images[0]?.urls[0]}
|
src={data?.avatar?.images[0]?.urls[0]}
|
||||||
alt=""
|
alt=""
|
||||||
|
fit="cover"
|
||||||
/>
|
/>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
|
|
@ -16,10 +16,10 @@ export default function WithAuth(WrappedComponent) {
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
const checkLogin = async () => {
|
const checkLogin = async () => {
|
||||||
const hasToken = await get("token");
|
const hasToken = await get("token");
|
||||||
console.log("hasToken", hasToken);
|
// console.log("hasToken", hasToken);
|
||||||
if (hasToken) {
|
if (hasToken) {
|
||||||
const hasToken = get("token");
|
const hasToken = get("token");
|
||||||
console.log("hasToken", hasToken);
|
// console.log("hasToken", hasToken);
|
||||||
if (hasToken) {
|
if (hasToken) {
|
||||||
const currentIsLogin = await checkAuth();
|
const currentIsLogin = await checkAuth();
|
||||||
if (!currentIsLogin) {
|
if (!currentIsLogin) {
|
||||||
|
|
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 299 B |
After Width: | Height: | Size: 216 B |
After Width: | Height: | Size: 730 B |
After Width: | Height: | Size: 328 B |
After Width: | Height: | Size: 196 B |
After Width: | Height: | Size: 528 B |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 422 B |
After Width: | Height: | Size: 290 B |
After Width: | Height: | Size: 503 B |
After Width: | Height: | Size: 324 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 769 B |
After Width: | Height: | Size: 499 B |
After Width: | Height: | Size: 228 B |
After Width: | Height: | Size: 609 B |
After Width: | Height: | Size: 952 B |
After Width: | Height: | Size: 228 B |
After Width: | Height: | Size: 258 B |
After Width: | Height: | Size: 302 B |
After Width: | Height: | Size: 223 B |
After Width: | Height: | Size: 179 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 870 B |
After Width: | Height: | Size: 398 B |
After Width: | Height: | Size: 286 B |
After Width: | Height: | Size: 258 B |
After Width: | Height: | Size: 304 B |
After Width: | Height: | Size: 267 B |
After Width: | Height: | Size: 354 B |
After Width: | Height: | Size: 273 B |
After Width: | Height: | Size: 343 B |
After Width: | Height: | Size: 269 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 732 B |
After Width: | Height: | Size: 702 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 456 B |
After Width: | Height: | Size: 356 B |
After Width: | Height: | Size: 297 B |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 798 B |
After Width: | Height: | Size: 1020 B |
After Width: | Height: | Size: 539 B |
After Width: | Height: | Size: 943 B |
After Width: | Height: | Size: 946 B |
After Width: | Height: | Size: 463 B |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 738 B |
After Width: | Height: | Size: 739 B |
After Width: | Height: | Size: 626 B |
After Width: | Height: | Size: 779 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 432 B |
After Width: | Height: | Size: 840 B |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 883 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 161 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 645 B |
After Width: | Height: | Size: 1.1 KiB |