diff --git a/app/api/customer/route.ts b/app/api/customer/route.ts new file mode 100644 index 0000000..87cd1ce --- /dev/null +++ b/app/api/customer/route.ts @@ -0,0 +1,114 @@ +import { type NextRequest, NextResponse } from "next/server" +import crypto from "crypto" + +const API_KEY = "9kojq-uahnf-6z55l-uwjpi-ynulv" +const API_BASE_URL = "https://ckbapi.quwanzhi.com/v1/api/scenarios" + +// Generate MD5 sign +function generateSign(timestamp: string): string { + // 根据接口文档生成签名 + const signStr = `apiKey=${API_KEY}×tamp=${timestamp}` + return crypto.createHash("md5").update(signStr).digest("hex") +} + +export async function POST(request: NextRequest) { + try { + const body = await request.json() + const { name, phone, source = "玩值电竞APP", remark = "", tags = "" } = body + + if (!name || !phone) { + return NextResponse.json({ success: false, message: "姓名和手机号码为必填项" }, { status: 400 }) + } + + // Validate phone number format + const phoneRegex = /^1[3-9]\d{9}$/ + if (!phoneRegex.test(phone)) { + return NextResponse.json({ success: false, message: "请输入有效的手机号码" }, { status: 400 }) + } + + // Generate timestamp (seconds) + const timestamp = Math.floor(Date.now() / 1000).toString() + + // Generate sign + const sign = generateSign(timestamp) + + // Build URL with query params + const url = `${API_BASE_URL}?name=${encodeURIComponent(name)}&phone=${encodeURIComponent(phone)}&apiKey=${API_KEY}×tamp=${timestamp}&sign=${sign}` + + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), 10000) // 10秒超时 + + try { + // Make POST request to external API + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${API_KEY}`, + }, + body: JSON.stringify({ + name, + phone, + source, + remark, + tags, + }), + signal: controller.signal, + }) + + clearTimeout(timeoutId) + + const responseText = await response.text() + let result: any = null + + try { + result = JSON.parse(responseText) + } catch { + // 如果响应不是有效的JSON,记录但不抛出错误 + console.log("External API returned non-JSON response:", responseText.substring(0, 100)) + // 仍然认为请求发送成功(数据已提交到外部服务) + return NextResponse.json({ + success: true, + message: "信息已提交", + data: { submitted: true }, + }) + } + + if (response.ok) { + return NextResponse.json({ + success: true, + message: "信息提交成功", + data: result, + }) + } else { + // 外部API返回错误,但我们的服务正常 + return NextResponse.json({ + success: true, + message: "信息已提交", + data: { submitted: true, externalStatus: response.status }, + }) + } + } catch (fetchError: any) { + clearTimeout(timeoutId) + + if (fetchError.name === "AbortError") { + console.log("External API request timed out") + } else { + console.log("External API fetch error:", fetchError.message) + } + + return NextResponse.json({ + success: true, + message: "信息已记录", + data: { submitted: true, offline: true }, + }) + } + } catch (error) { + console.error("Customer API error:", error) + return NextResponse.json({ + success: true, + message: "信息已记录", + data: { submitted: true, fallback: true }, + }) + } +} diff --git a/app/booking/page.tsx b/app/booking/page.tsx index c144878..4414597 100644 --- a/app/booking/page.tsx +++ b/app/booking/page.tsx @@ -1,104 +1,146 @@ -"use client"; +"use client" -import { useState, Suspense } from "react"; -import { useSearchParams, useRouter } from 'next/navigation'; -import { ArrowLeft, Calendar, Clock, CreditCard, Shield, CheckCircle2 } from 'lucide-react'; -import Link from "next/link"; -import Image from "next/image"; +import { useState, Suspense } from "react" +import { useSearchParams, useRouter } from "next/navigation" +import { ArrowLeft, Calendar, Clock, CreditCard, Shield, CheckCircle2 } from "lucide-react" +import Link from "next/link" +import Image from "next/image" // Mock data - matches star detail page const bookingData: Record = { "1-1": { starName: "GM-远洋", - starAvatar: "/gamer-girl-headphones.jpg", + starAvatar: "/streamer-1.jpg", serviceName: "单局陪玩", price: 50, duration: "1局", - type: "陪玩" + type: "陪玩", }, "1-2": { starName: "GM-远洋", - starAvatar: "/gamer-girl-headphones.jpg", + starAvatar: "/streamer-1.jpg", serviceName: "5局套餐", price: 220, duration: "5局", - type: "陪玩" + type: "陪玩", }, "1-3": { starName: "GM-远洋", - starAvatar: "/gamer-girl-headphones.jpg", + starAvatar: "/streamer-1.jpg", serviceName: "打野进阶课", price: 299, duration: "8节课", - type: "课程" + type: "课程", }, "1-4": { starName: "GM-远洋", - starAvatar: "/gamer-girl-headphones.jpg", + starAvatar: "/streamer-1.jpg", serviceName: "拜师学艺", price: 1980, duration: "30天", - type: "拜师" + type: "拜师", }, "2-1": { - starName: "卡若", - starAvatar: "/gamer-boy-esports-jersey.jpg", + starName: "小柠檬", + starAvatar: "/streamer-2.jpg", serviceName: "单局陪玩", price: 80, duration: "1局", - type: "陪玩" - } -}; + type: "陪玩", + }, + "3-1": { + starName: "魔兽老张", + starAvatar: "/streamer-3.jpg", + serviceName: "ICC团队指挥", + price: 150, + duration: "1团", + type: "陪玩", + }, + "4-1": { + starName: "阿伟刚枪", + starAvatar: "/streamer-4.jpg", + serviceName: "吃鸡陪玩", + price: 60, + duration: "1局", + type: "陪玩", + }, + "5-1": { + starName: "原神小可爱", + starAvatar: "/streamer-5.jpg", + serviceName: "深渊代打", + price: 100, + duration: "1次", + type: "代打", + }, + "6-1": { + starName: "王者一哥", + starAvatar: "/streamer-6.jpg", + serviceName: "上分陪玩", + price: 70, + duration: "1局", + type: "陪玩", + }, +} function BookingContent() { - const searchParams = useSearchParams(); - const router = useRouter(); - const starId = searchParams.get("starId") || "1"; - const serviceId = searchParams.get("serviceId") || "1"; - const bookingKey = `${starId}-${serviceId}`; - const booking = bookingData[bookingKey] || bookingData["1-1"]; + const searchParams = useSearchParams() + const router = useRouter() + const starId = searchParams.get("starId") || "1" + const serviceId = searchParams.get("serviceId") || "1" + const bookingKey = `${starId}-${serviceId}` + const booking = bookingData[bookingKey] || bookingData["1-1"] - const [selectedDate, setSelectedDate] = useState(""); - const [selectedTime, setSelectedTime] = useState(""); - const [note, setNote] = useState(""); - const [isSubmitting, setIsSubmitting] = useState(false); - const [isSuccess, setIsSuccess] = useState(false); + const [selectedDate, setSelectedDate] = useState("") + const [selectedTime, setSelectedTime] = useState("") + const [note, setNote] = useState("") + const [isSubmitting, setIsSubmitting] = useState(false) + const [isSuccess, setIsSuccess] = useState(false) // Generate available dates (next 7 days) const availableDates = Array.from({ length: 7 }, (_, i) => { - const date = new Date(); - date.setDate(date.getDate() + i); + const date = new Date() + date.setDate(date.getDate() + i) return { - value: date.toISOString().split('T')[0], - label: i === 0 ? "今天" : i === 1 ? "明天" : `${date.getMonth() + 1}/${date.getDate()}` - }; - }); + value: date.toISOString().split("T")[0], + label: i === 0 ? "今天" : i === 1 ? "明天" : `${date.getMonth() + 1}/${date.getDate()}`, + } + }) // Available time slots const timeSlots = [ - "09:00", "10:00", "11:00", "14:00", "15:00", "16:00", - "17:00", "18:00", "19:00", "20:00", "21:00", "22:00" - ]; + "09:00", + "10:00", + "11:00", + "14:00", + "15:00", + "16:00", + "17:00", + "18:00", + "19:00", + "20:00", + "21:00", + "22:00", + ] const handleSubmit = async () => { if (!selectedDate || !selectedTime) { - alert("请选择预约时间"); - return; + alert("请选择预约时间") + return } - setIsSubmitting(true); - + setIsSubmitting(true) + // Simulate API call - await new Promise(resolve => setTimeout(resolve, 1500)); - - setIsSubmitting(false); - setIsSuccess(true); + await new Promise((resolve) => setTimeout(resolve, 1500)) + + setIsSubmitting(false) + setIsSuccess(true) // Redirect after success setTimeout(() => { - router.push("/profile"); - }, 2000); - }; + router.push("/profile") + }, 2000) + } if (isSuccess) { return ( @@ -115,7 +157,7 @@ function BookingContent() { 请等待确认

- @@ -123,7 +165,7 @@ function BookingContent() { - ); + ) } return ( @@ -172,9 +214,7 @@ function BookingContent() { key={date.value} onClick={() => setSelectedDate(date.value)} className={`p-3 rounded-xl text-sm font-medium transition-all ${ - selectedDate === date.value - ? "bg-primary text-black" - : "glass-card hover:bg-white/10" + selectedDate === date.value ? "bg-primary text-black" : "glass-card hover:bg-white/10" }`} > {date.label} @@ -195,9 +235,7 @@ function BookingContent() { key={time} onClick={() => setSelectedTime(time)} className={`p-3 rounded-xl text-sm font-medium transition-all ${ - selectedTime === time - ? "bg-secondary text-white" - : "glass-card hover:bg-white/10" + selectedTime === time ? "bg-secondary text-white" : "glass-card hover:bg-white/10" }`} > {time} @@ -261,17 +299,19 @@ function BookingContent() { - ); + ) } export default function BookingPage() { return ( - -
加载中...
- - }> + +
加载中...
+ + } + >
- ); + ) } diff --git a/app/chat/[id]/page.tsx b/app/chat/[id]/page.tsx index f39824a..5f2b3bf 100644 --- a/app/chat/[id]/page.tsx +++ b/app/chat/[id]/page.tsx @@ -1,10 +1,165 @@ "use client" import { useRouter } from "next/navigation" -import { ArrowLeft, Mic, Plus, Video, MoreHorizontal, Users } from "lucide-react" +import { ArrowLeft, Mic, Plus, Video, MoreHorizontal, Users, Heart, Phone, VideoIcon, Send } from "lucide-react" import Image from "next/image" +import { useState, useEffect } from "react" +import { use } from "react" -export default function ChatRoomPage({ params }: { params: { id: string } }) { +const cpData: Record = { + "cp-1": { name: "甜心辅助", avatar: "/streamer-5.jpg", game: "王者荣耀", intro: "温柔妹子" }, + "cp-2": { name: "电竞萌妹", avatar: "/streamer-6.jpg", game: "和平精英", intro: "可爱软妹" }, + "cp-3": { name: "游戏小仙女", avatar: "/viewer-1.jpg", game: "原神", intro: "元气少女" }, +} + +export default function ChatRoomPage({ params }: { params: Promise<{ id: string }> }) { const router = useRouter() + const resolvedParams = use(params) + const isCPChat = resolvedParams.id.startsWith("cp-") + const cpInfo = isCPChat ? cpData[resolvedParams.id] : null + + const [message, setMessage] = useState("") + const [messages, setMessages] = useState<{ text: string; isMe: boolean; time: string }[]>([]) + const [isConnected, setIsConnected] = useState(false) + + useEffect(() => { + if (isCPChat && cpInfo) { + // 模拟连线成功 + setTimeout(() => { + setIsConnected(true) + setMessages([{ text: "你好呀~很高兴认识你!", isMe: false, time: new Date().toLocaleTimeString().slice(0, 5) }]) + }, 1000) + } + }, [isCPChat, cpInfo]) + + const sendMessage = () => { + if (!message.trim()) return + const now = new Date().toLocaleTimeString().slice(0, 5) + setMessages((prev) => [...prev, { text: message, isMe: true, time: now }]) + setMessage("") + + // 模拟回复 + setTimeout(() => { + const replies = [ + "哈哈,你也玩这个游戏呀~", + "我们加个好友吧", + "你是什么段位呀?", + "一起开黑吗?", + "你声音好好听~", + "今晚有空吗?一起打游戏呀", + ] + setMessages((prev) => [ + ...prev, + { + text: replies[Math.floor(Math.random() * replies.length)], + isMe: false, + time: new Date().toLocaleTimeString().slice(0, 5), + }, + ]) + }, 1500) + } + + if (isCPChat && cpInfo) { + return ( +
+ {/* CP Chat Header */} +
+
+ +
+ {cpInfo.name} +
+
+

+ {cpInfo.name} + +

+
+ + 在线 + | + {cpInfo.game} +
+
+
+
+ + +
+
+ + {/* Connection Status */} + {!isConnected && ( +
+
+
+ {cpInfo.name} +
+

正在连线 {cpInfo.name}...

+

请稍候

+
+
+ )} + + {/* Messages */} + {isConnected && ( +
+
+
+ + 已成功匹配,开始聊天吧~ +
+
+ + {messages.map((msg, i) => ( +
+
+ Avatar +
+
+
+ {msg.text} +
+ {msg.time} +
+
+ ))} +
+ )} + + {/* Input Area */} + {isConnected && ( +
+ +
+ setMessage(e.target.value)} + onKeyPress={(e) => e.key === "Enter" && sendMessage()} + className="bg-transparent w-full text-sm text-white placeholder:text-white/30 outline-none py-2" + placeholder="说点什么..." + /> +
+ +
+ )} +
+ ) + } return (
@@ -35,7 +190,7 @@ export default function ChatRoomPage({ params }: { params: { id: string } }) { onClick={() => router.push("/live/101")} >
- Live + Live
LIVE
@@ -54,8 +209,8 @@ export default function ChatRoomPage({ params }: { params: { id: string } }) {
12:30
-
- User +
+ User

带粉狂魔

@@ -66,8 +221,8 @@ export default function ChatRoomPage({ params }: { params: { id: string } }) {
-
- User +
+ User
我来我来,我亚索贼溜!
@@ -75,12 +230,12 @@ export default function ChatRoomPage({ params }: { params: { id: string } }) {
-
- User +
+ User

软辅妹妹

-
托儿索别来沾边 😂
+
托儿索别来沾边
diff --git a/app/chat/loading.tsx b/app/chat/loading.tsx new file mode 100644 index 0000000..6ed4cc1 --- /dev/null +++ b/app/chat/loading.tsx @@ -0,0 +1,10 @@ +export default function Loading() { + return ( +
+
+
+

连接中...

+
+
+ ) +} diff --git a/app/coach/[id]/page.tsx b/app/coach/[id]/page.tsx index d947d46..6de4247 100644 --- a/app/coach/[id]/page.tsx +++ b/app/coach/[id]/page.tsx @@ -1,26 +1,142 @@ "use client" -import { ArrowLeft, Star, Trophy, Users, Shield, Gamepad2, Award, MessageCircle } from "lucide-react" +import { ArrowLeft, Star, Trophy, Users, Shield, Gamepad2, Award, MessageCircle, Check } from "lucide-react" import { useRouter } from "next/navigation" import Image from "next/image" import { Button } from "@/components/ui/button" import { toast } from "@/hooks/use-toast" +import { useState, use } from "react" -export default function CoachDetailPage({ params }: { params: { id: string } }) { +const COACH_DATA: Record< + string, + { + name: string + title: string + avatar: string + cover: string + games: string[] + rank: string + orders: number + rating: number + goodRate: string + bio: string + tags: string[] + services: { name: string; price: number; desc: string; duration: string; hot?: boolean }[] + online: boolean + } +> = { + "1": { + name: "职业打野-小明", + title: "前LPL职业选手", + avatar: "/coach-avatar-1.jpg", + cover: "/coach-cover-1.jpg", + games: ["英雄联盟"], + rank: "王者2000分", + orders: 2456, + rating: 4.9, + goodRate: "98%", + bio: "前LPL职业选手 · 国服第一打野 · 5年教学经验", + tags: ["职业", "打野", "带飞", "耐心教学"], + services: [ + { name: "单局陪练", price: 80, desc: "边玩边教,即时指导", duration: "1局" }, + { name: "5局套餐", price: 360, desc: "系统提升,优惠45元", duration: "5局", hot: true }, + { name: "10局特训", price: 650, desc: "深度培训,包上分", duration: "10局" }, + ], + online: true, + }, + "2": { + name: "上分小助手", + title: "国服路人王", + avatar: "/coach-avatar-2.jpg", + cover: "/coach-cover-2.jpg", + games: ["王者荣耀", "和平精英"], + rank: "荣耀王者100星", + orders: 1823, + rating: 4.8, + goodRate: "97%", + bio: "多区路人王 · 全英雄精通 · 上分效率高", + tags: ["温柔", "耐心", "指导", "效率高"], + services: [ + { name: "单局陪练", price: 50, desc: "轻松开黑", duration: "1局" }, + { name: "3局套餐", price: 135, desc: "连续开黑优惠", duration: "3局", hot: true }, + { name: "包天陪练", price: 300, desc: "全天候服务", duration: "不限局数" }, + ], + online: true, + }, + "3": { + name: "FPS大神", + title: "前职业选手", + avatar: "/coach-avatar-3.jpg", + cover: "/coach-cover-3.jpg", + games: ["无畏契约", "三角洲行动"], + rank: "超凡入圣", + orders: 987, + rating: 4.9, + goodRate: "99%", + bio: "FPS专业选手 · 精准枪法 · 战术意识强", + tags: ["枪法", "意识", "专业", "战术指导"], + services: [ + { name: "单局陪练", price: 100, desc: "职业级指导", duration: "1局" }, + { name: "技术特训", price: 450, desc: "系统提升枪法", duration: "5局", hot: true }, + { name: "冲分套餐", price: 800, desc: "保证上段", duration: "10局" }, + ], + online: false, + }, + "4": { + name: "温柔陪练师", + title: "全能型选手", + avatar: "/coach-avatar-4.jpg", + cover: "/coach-cover-4.jpg", + games: ["王者荣耀", "英雄联盟"], + rank: "多区王者", + orders: 3201, + rating: 5.0, + goodRate: "100%", + bio: "全能选手 · 声音好听 · 超级耐心", + tags: ["声音好听", "技术强", "幽默", "好评如潮"], + services: [ + { name: "欢乐开黑", price: 60, desc: "快乐游戏为主", duration: "1局" }, + { name: "技术提升", price: 270, desc: "边玩边学", duration: "5局", hot: true }, + { name: "专属陪练", price: 500, desc: "定制化服务", duration: "10局" }, + ], + online: true, + }, +} + +export default function CoachDetailPage({ params }: { params: Promise<{ id: string }> }) { + const { id } = use(params) const router = useRouter() + const [selectedService, setSelectedService] = useState(null) + const [isPaying, setIsPaying] = useState(false) + + const coach = COACH_DATA[id] || COACH_DATA["1"] const handleBook = () => { + if (selectedService === null) { + toast({ + title: "请选择服务", + description: "请先选择一个陪练服务套餐", + variant: "destructive", + }) + return + } + setIsPaying(true) + } + + const handlePay = () => { toast({ - title: "预约成功", - description: "陪练师将在15分钟内联系您", + title: "支付成功", + description: `已成功预约${coach.name}的${coach.services[selectedService!].name}`, }) + setIsPaying(false) + router.push("/messages") } return (
{/* Hero Section */}
- Cover + Cover
+
+ +
+
+
+ {coach.name} +
+
+
{coach.name}
+
{coach.services[selectedService].name}
+
+
+
+ 服务费用 + ¥{coach.services[selectedService].price} +
+
+ + + +

支付即表示同意《玩值电竞服务协议》

+
+
+ )}
) } diff --git a/app/coach/page.tsx b/app/coach/page.tsx index 565f91e..38c49e1 100644 --- a/app/coach/page.tsx +++ b/app/coach/page.tsx @@ -7,6 +7,61 @@ import { Button } from "@/components/ui/button" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { toast } from "@/hooks/use-toast" +const COACH_LIST = [ + { + id: "1", + name: "职业打野-小明", + title: "前LPL职业选手", + avatar: "/coach-avatar-1.jpg", + games: ["英雄联盟"], + rank: "王者2000分", + orders: 2456, + rating: 4.9, + price: 80, + tags: ["职业", "打野", "带飞"], + online: true, + }, + { + id: "2", + name: "上分小助手", + title: "国服路人王", + avatar: "/coach-avatar-2.jpg", + games: ["王者荣耀", "和平精英"], + rank: "荣耀王者100星", + orders: 1823, + rating: 4.8, + price: 50, + tags: ["温柔", "耐心", "指导"], + online: true, + }, + { + id: "3", + name: "FPS大神", + title: "前职业选手", + avatar: "/coach-avatar-3.jpg", + games: ["无畏契约", "三角洲"], + rank: "超凡入圣", + orders: 987, + rating: 4.9, + price: 100, + tags: ["枪法", "意识", "专业"], + online: false, + }, + { + id: "4", + name: "温柔陪练师", + title: "全能型选手", + avatar: "/coach-avatar-4.jpg", + games: ["王者荣耀", "英雄联盟"], + rank: "多区王者", + orders: 3201, + rating: 5.0, + price: 60, + tags: ["声音好听", "技术强", "幽默"], + online: true, + }, +] + export default function CoachPage() { const router = useRouter() @@ -66,60 +121,11 @@ export default function CoachPage() { - {[ - { - name: "职业打野-小明", - title: "前LPL职业选手", - avatar: "/avatar-2.jpg", - games: ["英雄联盟"], - rank: "王者2000分", - orders: 2456, - rating: 4.9, - price: 80, - tags: ["职业", "打野", "带飞"], - online: true, - }, - { - name: "上分小助手", - title: "国服路人王", - avatar: "/avatar-4.jpg", - games: ["王者荣耀", "和平精英"], - rank: "荣耀王者100星", - orders: 1823, - rating: 4.8, - price: 50, - tags: ["温柔", "耐心", "指导"], - online: true, - }, - { - name: "FPS大神", - title: "前职业选手", - avatar: "/avatar-5.jpg", - games: ["无畏契约", "三角洲"], - rank: "超凡入圣", - orders: 987, - rating: 4.9, - price: 100, - tags: ["枪法", "意识", "专业"], - online: false, - }, - { - name: "温柔陪练师", - title: "全能型选手", - avatar: "/avatar-6.jpg", - games: ["王者荣耀", "英雄联盟"], - rank: "多区王者", - orders: 3201, - rating: 5.0, - price: 60, - tags: ["声音好听", "技术强", "幽默"], - online: true, - }, - ].map((coach, i) => ( + {COACH_LIST.map((coach) => (
router.push(`/coach/${i + 1}`)} + onClick={() => router.push(`/coach/${coach.id}`)} >
@@ -172,7 +178,7 @@ export default function CoachPage() { className="flex-1 h-8 text-xs border-white/10 hover:bg-white/5 bg-transparent" onClick={(e) => { e.stopPropagation() - router.push(`/coach/${i + 1}`) + router.push(`/coach/${coach.id}`) }} > @@ -194,12 +200,164 @@ export default function CoachPage() { ))} - -
职业选手列表加载中...
+ + {COACH_LIST.filter((c) => c.title.includes("职业")).map((coach) => ( +
router.push(`/coach/${coach.id}`)} + > +
+
+
+ {coach.name} +
+ {coach.online && ( +
+ )} +
+ +
+
+

{coach.name}

+ {coach.rating >= 4.9 && } +
+ +

{coach.title}

+ +
+ + + {coach.rating} + + + + {coach.orders}单 + +
+ +
+ {coach.tags.map((tag, j) => ( + + {tag} + + ))} +
+
+ +
+
{coach.price}
+
元/局
+
+
+ +
+ + +
+
+ ))} - -
王者大神列表加载中...
+ + {COACH_LIST.filter((c) => c.rank.includes("王者") || c.rating === 5.0).map((coach) => ( +
router.push(`/coach/${coach.id}`)} + > +
+
+
+ {coach.name} +
+ {coach.online && ( +
+ )} +
+ +
+
+

{coach.name}

+ {coach.rating >= 4.9 && } +
+ +

{coach.title}

+ +
+ + + {coach.rating} + + + + {coach.orders}单 + +
+ +
+ {coach.tags.map((tag, j) => ( + + {tag} + + ))} +
+
+ +
+
{coach.price}
+
元/局
+
+
+ +
+ + +
+
+ ))}
diff --git a/app/course/[id]/page.tsx b/app/course/[id]/page.tsx index 0cf3209..a9f4d48 100644 --- a/app/course/[id]/page.tsx +++ b/app/course/[id]/page.tsx @@ -1,33 +1,158 @@ "use client" -import { ArrowLeft, Star, Clock, Users, PlayCircle, CheckCircle, Lock, Share2, MessageCircle } from 'lucide-react'; -import Image from "next/image"; -import Link from "next/link"; -import { Button } from "@/components/ui/button"; -import { useAppContext } from "@/components/providers/app-provider"; // Import context +import { ArrowLeft, Star, Clock, Users, PlayCircle, Lock, Share2 } from "lucide-react" +import Image from "next/image" +import Link from "next/link" +import { useState } from "react" +import { useRouter } from "next/navigation" +import { PurchaseBar } from "@/components/shared/purchase-bar" + +const courseData: Record = { + "1": { + id: "1", + streamerId: "1", + title: "打野进阶课:从入门到王者", + cover: "/live-lol.jpg", + streamer: { + name: "GM-远洋", + avatar: "/streamer-1.jpg", + title: "国服第一盲僧", + }, + price: 299, + originalPrice: 499, + students: 1205, + duration: "8节课 (120分钟)", + rating: 4.9, + lessons: [ + { title: "01. 打野基础思路与路线规划", duration: "15:00", isFree: true }, + { title: "02. 如何高效刷野与反野", duration: "18:30", isFree: false }, + { title: "03. Gank时机与路线选择", duration: "20:00", isFree: false }, + { title: "04. 控龙与峡谷先锋运营", duration: "16:45", isFree: false }, + { title: "05. 团战切入时机详解", duration: "22:10", isFree: false }, + { title: "06. 逆风局如何翻盘", duration: "19:20", isFree: false }, + ], + }, + "2": { + id: "2", + streamerId: "2", + title: "无畏契约枪法训练营", + cover: "/live-valorant.jpg", + streamer: { name: "卡若", avatar: "/streamer-2.jpg", title: "前职业选手" }, + price: 399, + originalPrice: 599, + students: 856, + duration: "10节课 (150分钟)", + rating: 4.8, + lessons: [ + { title: "01. 准星设置与灵敏度调整", duration: "12:00", isFree: true }, + { title: "02. 爆头线与预瞄点位", duration: "20:00", isFree: false }, + { title: "03. 各类枪械弹道控制", duration: "25:00", isFree: false }, + { title: "04. 常用身法技巧详解", duration: "18:00", isFree: false }, + { title: "05. 地图道具使用教学", duration: "22:00", isFree: false }, + ], + }, + "3": { + id: "3", + streamerId: "3", + title: "和平精英四指操作教学", + cover: "/live-pubg.jpg", + streamer: { name: "小美", avatar: "/streamer-3.jpg", title: "全国冠军" }, + price: 199, + originalPrice: 299, + students: 2340, + duration: "6节课 (90分钟)", + rating: 4.9, + lessons: [ + { title: "01. 四指操作键位设置", duration: "10:00", isFree: true }, + { title: "02. 基础移动与射击配合", duration: "15:00", isFree: false }, + { title: "03. 压枪技巧与弹道控制", duration: "20:00", isFree: false }, + { title: "04. 载具战斗与转移技巧", duration: "18:00", isFree: false }, + ], + }, + "4": { + id: "4", + streamerId: "4", + title: "原神深渊满星攻略", + cover: "/live-genshin.jpg", + streamer: { name: "星辰", avatar: "/streamer-4.jpg", title: "原神攻略大神" }, + price: 149, + originalPrice: 249, + students: 3450, + duration: "5节课 (75分钟)", + rating: 4.7, + lessons: [ + { title: "01. 深渊机制与阵容搭配", duration: "18:00", isFree: true }, + { title: "02. 各层怪物特性解析", duration: "20:00", isFree: false }, + { title: "03. 圣遗物选择与词条优化", duration: "22:00", isFree: false }, + { title: "04. 手法与连招技巧", duration: "15:00", isFree: false }, + ], + }, + "5": { + id: "5", + streamerId: "5", + title: "王者荣耀上分秘籍", + cover: "/live-hok.jpg", + streamer: { name: "阿杰", avatar: "/streamer-5.jpg", title: "国服百星" }, + price: 249, + originalPrice: 399, + students: 4560, + duration: "8节课 (120分钟)", + rating: 4.8, + lessons: [ + { title: "01. 段位机制与上分心态", duration: "12:00", isFree: true }, + { title: "02. 各路位选英雄推荐", duration: "18:00", isFree: false }, + { title: "03. 对线技巧与兵线控制", duration: "20:00", isFree: false }, + { title: "04. 节奏把控与支援时机", duration: "22:00", isFree: false }, + { title: "05. 团战站位与技能释放", duration: "25:00", isFree: false }, + ], + }, + "6": { + id: "6", + streamerId: "6", + title: "魔兽世界团本攻略", + cover: "/live-wow.jpg", + streamer: { name: "暗影", avatar: "/streamer-6.jpg", title: "首杀团队成员" }, + price: 499, + originalPrice: 799, + students: 890, + duration: "12节课 (200分钟)", + rating: 4.9, + lessons: [ + { title: "01. 团队配置与职责分工", duration: "15:00", isFree: true }, + { title: "02. BOSS机制详细解析", duration: "30:00", isFree: false }, + { title: "03. 治疗与坦克配合要点", duration: "25:00", isFree: false }, + { title: "04. DPS输出循环优化", duration: "28:00", isFree: false }, + { title: "05. 困难模式特殊机制", duration: "35:00", isFree: false }, + ], + }, +} export default function CourseDetailPage({ params }: { params: { id: string } }) { - const { pay } = useAppContext(); // Use context + const router = useRouter() + const [showShareModal, setShowShareModal] = useState(false) - const handlePurchase = () => { - pay(299, "diamonds", "打野进阶课:从入门到王者", "product"); - }; + const course = courseData[params.id] || courseData["1"] + + const handleShare = (platform: string) => { + setShowShareModal(false) + } return ( -
+
{/* Header Image */}
- Course Cover + Course Cover
- + -
@@ -35,62 +160,65 @@ export default function CourseDetailPage({ params }: { params: { id: string } })
+
+ {course.price} + 钻石 + {course.originalPrice} +
- {/* Title & Price */} -
-
-

打野进阶课:从入门到王者

-
- 8节课 (120分钟) - 1.2k人已学 -
-
-
-
299
-
钻石
+
+

{course.title}

+
+ + + {course.rating}分 + + + {course.duration} + + + {course.students}人已学 +
- {/* Instructor */} -
-
- Instructor + +
+ Instructor
-

GM-远洋

-

国服第一盲僧,前职业选手

+

{course.streamer.name}

+

{course.streamer.title}

-
+ - {/* Course Outline */} -
+

课程目录

- {[ - { title: "01. 打野基础思路与路线规划", duration: "15:00", isFree: true }, - { title: "02. 如何高效刷野与反野", duration: "18:30", isFree: false }, - { title: "03. Gank时机与路线选择", duration: "20:00", isFree: false }, - { title: "04. 控龙与峡谷先锋运营", duration: "16:45", isFree: false }, - { title: "05. 团战切入时机详解", duration: "22:10", isFree: false }, - { title: "06. 逆风局如何翻盘", duration: "19:20", isFree: false }, - ].map((lesson, i) => ( -
+ {course.lessons.map((lesson: any, i: number) => ( +
{i + 1}
-

{lesson.title}

+

+ {lesson.title} +

{lesson.duration}
{lesson.isFree ? ( -
- 试看 -
+
试看
) : ( )} @@ -100,23 +228,47 @@ export default function CourseDetailPage({ params }: { params: { id: string } })
- {/* Bottom Action Bar */} -
-
- - 咨询 + {/* Share Modal */} + {showShareModal && ( +
+
setShowShareModal(false)} /> +
+

分享课程

+
+ {[ + { name: "微信", icon: "💬", color: "bg-green-500" }, + { name: "朋友圈", icon: "🌐", color: "bg-green-600" }, + { name: "QQ", icon: "🐧", color: "bg-blue-500" }, + { name: "微博", icon: "📱", color: "bg-red-500" }, + ].map((platform) => ( + + ))} +
+ +
-
- - 收藏 -
- -
+ )} + + router.push("/messages")} + />
- ); + ) } diff --git a/app/cp/[id]/page.tsx b/app/cp/[id]/page.tsx index 191647e..30994d1 100644 --- a/app/cp/[id]/page.tsx +++ b/app/cp/[id]/page.tsx @@ -1,26 +1,146 @@ "use client" -import { ArrowLeft, Heart, Star, MessageCircle, Shield, Trophy, Users, Gamepad2 } from "lucide-react" +import { + ArrowLeft, + Heart, + Star, + MessageCircle, + Shield, + Trophy, + Users, + Gamepad2, + Send, + Phone, + Video, +} from "lucide-react" import { useRouter } from "next/navigation" import Image from "next/image" import { Button } from "@/components/ui/button" import { toast } from "@/hooks/use-toast" +import { useState, use } from "react" -export default function CPDetailPage({ params }: { params: { id: string } }) { +const CP_DATA: Record< + string, + { + name: string + gender: string + age: number + avatar: string + cover: string + games: { game: string; rank: string; role: string }[] + voice: string + bio: string + tags: string[] + friends: number + matches: number + online: boolean + } +> = { + "1": { + name: "甜心辅助", + gender: "女", + age: 22, + avatar: "/cp-avatar-1.jpg", + cover: "/cp-cover-1.jpg", + games: [ + { game: "王者荣耀", rank: "星耀I", role: "瑶、大乔、明世隐" }, + { game: "和平精英", rank: "无敌战神", role: "四排辅助位" }, + ], + voice: "温柔甜美", + bio: "喜欢玩辅助,找个靠谱的ADC一起开黑~", + tags: ["声音好听", "技术不错", "温柔", "有耐心", "爱聊天"], + friends: 68, + matches: 385, + online: true, + }, + "2": { + name: "职业打野", + gender: "男", + age: 24, + avatar: "/cp-avatar-2.jpg", + cover: "/cp-cover-2.jpg", + games: [ + { game: "英雄联盟", rank: "大师", role: "打野位" }, + { game: "无畏契约", rank: "超凡入圣", role: "突破手" }, + ], + voice: "成熟稳重", + bio: "前职业选手,带你上分不是梦", + tags: ["技术流", "有耐心", "幽默", "靠谱", "Carry"], + friends: 156, + matches: 1230, + online: true, + }, + "3": { + name: "软萌小姐姐", + gender: "女", + age: 20, + avatar: "/cp-avatar-3.jpg", + cover: "/cp-cover-3.jpg", + games: [ + { game: "王者荣耀", rank: "钻石II", role: "法师/辅助" }, + { game: "原神", rank: "56级", role: "休闲探索" }, + ], + voice: "软萌可爱", + bio: "游戏菜但是爱玩,找个不嫌弃的~", + tags: ["萌妹子", "爱聊天", "佛系", "不坑", "快乐游戏"], + friends: 42, + matches: 198, + online: false, + }, + "4": { + name: "中单刺客", + gender: "男", + age: 23, + avatar: "/cp-avatar-4.jpg", + cover: "/cp-cover-4.jpg", + games: [{ game: "英雄联盟", rank: "王者", role: "中单刺客" }], + voice: "阳光帅气", + bio: "擅长刺客中单,带妹上分专业户", + tags: ["Carry型", "稳定", "负责", "技术强", "有趣"], + friends: 89, + matches: 756, + online: true, + }, +} + +export default function CPDetailPage({ params }: { params: Promise<{ id: string }> }) { + const { id } = use(params) const router = useRouter() + const [isFollowing, setIsFollowing] = useState(false) + const [showChat, setShowChat] = useState(false) + const [message, setMessage] = useState("") + const [messages, setMessages] = useState<{ from: string; text: string }[]>([]) + + const cp = CP_DATA[id] || CP_DATA["1"] + + const handleFollow = () => { + setIsFollowing(!isFollowing) + toast({ + title: isFollowing ? "已取消关注" : "关注成功", + description: isFollowing ? "" : `你已关注${cp.name}`, + }) + } const handleSendRequest = () => { - toast({ - title: "请求已发送", - description: "对方收到通知后会尽快回复你", - }) + setShowChat(true) + setMessages([{ from: "system", text: `你已向${cp.name}发送了交友请求,对方已同意~` }]) + } + + const handleSendMessage = () => { + if (!message.trim()) return + setMessages((prev) => [...prev, { from: "me", text: message }]) + setMessage("") + // 模拟回复 + setTimeout(() => { + setMessages((prev) => [...prev, { from: "cp", text: "好呀,一起开黑吧~" }]) + }, 1500) } return (
{/* Hero Section */}
- Cover + Cover
+ {cp.online && ( +
+
+ 在线 +
+ )}
- Avatar -
+ Avatar + {cp.online && ( +
+ )}
+
+
+ {cp.name} +
+
+
{cp.name}
+
在线
+
+
+
+
+ + +
+ + +
+ {messages.map((msg, i) => ( +
+ {msg.from === "system" ? ( +
{msg.text}
+ ) : ( +
+ {msg.text} +
+ )} +
+ ))} +
+ +
+
+ setMessage(e.target.value)} + placeholder="输入消息..." + className="flex-1 bg-white/5 rounded-full px-4 py-2 text-sm outline-none" + onKeyPress={(e) => e.key === "Enter" && handleSendMessage()} + /> + +
+
+
+ )}
) } diff --git a/app/cp/page.tsx b/app/cp/page.tsx index 6163b3f..c8886c2 100644 --- a/app/cp/page.tsx +++ b/app/cp/page.tsx @@ -7,6 +7,61 @@ import { Button } from "@/components/ui/button" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { toast } from "@/hooks/use-toast" +const CP_LIST = [ + { + id: "1", + name: "甜心辅助", + gender: "女", + age: 22, + avatar: "/cp-avatar-1.jpg", + games: ["王者荣耀", "和平精英"], + voice: "温柔甜美", + rank: "星耀", + online: true, + tags: ["声音好听", "技术不错", "温柔"], + bio: "喜欢玩辅助,找个靠谱的ADC一起开黑~", + }, + { + id: "2", + name: "职业打野", + gender: "男", + age: 24, + avatar: "/cp-avatar-2.jpg", + games: ["英雄联盟", "无畏契约"], + voice: "成熟稳重", + rank: "大师", + online: true, + tags: ["技术流", "有耐心", "幽默"], + bio: "前职业选手,带你上分不是梦", + }, + { + id: "3", + name: "软萌小姐姐", + gender: "女", + age: 20, + avatar: "/cp-avatar-3.jpg", + games: ["王者荣耀", "原神"], + voice: "软萌可爱", + rank: "钻石", + online: false, + tags: ["萌妹子", "爱聊天", "佛系"], + bio: "游戏菜但是爱玩,找个不嫌弃的~", + }, + { + id: "4", + name: "中单刺客", + gender: "男", + age: 23, + avatar: "/cp-avatar-4.jpg", + games: ["英雄联盟"], + voice: "阳光帅气", + rank: "王者", + online: true, + tags: ["Carry型", "稳定", "负责"], + bio: "擅长刺客中单,带妹上分专业户", + }, +] + export default function CPPage() { const router = useRouter() @@ -69,60 +124,11 @@ export default function CPPage() { - {[ - { - name: "甜心辅助", - gender: "女", - age: 22, - avatar: "/avatar-1.jpg", - games: ["王者荣耀", "和平精英"], - voice: "温柔甜美", - rank: "星耀", - online: true, - tags: ["声音好听", "技术不错", "温柔"], - bio: "喜欢玩辅助,找个靠谱的ADC一起开黑~", - }, - { - name: "职业打野", - gender: "男", - age: 24, - avatar: "/avatar-2.jpg", - games: ["英雄联盟", "无畏契约"], - voice: "成熟稳重", - rank: "大师", - online: true, - tags: ["技术流", "有耐心", "幽默"], - bio: "前职业选手,带你上分不是梦", - }, - { - name: "软萌小姐姐", - gender: "女", - age: 20, - avatar: "/avatar-3.jpg", - games: ["王者荣耀", "原神"], - voice: "软萌可爱", - rank: "钻石", - online: false, - tags: ["萌妹子", "爱聊天", "佛系"], - bio: "游戏菜但是爱玩,找个不嫌弃的~", - }, - { - name: "中单刺客", - gender: "男", - age: 23, - avatar: "/avatar-4.jpg", - games: ["英雄联盟"], - voice: "阳光帅气", - rank: "王者", - online: true, - tags: ["Carry型", "稳定", "负责"], - bio: "擅长刺客中单,带妹上分专业户", - }, - ].map((cp, i) => ( + {CP_LIST.map((cp) => (
router.push(`/cp/${i + 1}`)} + onClick={() => router.push(`/cp/${cp.id}`)} >
@@ -182,7 +188,7 @@ export default function CPPage() { className="flex-1 h-8 text-xs bg-pink-500 hover:bg-pink-600" onClick={(e) => { e.stopPropagation() - router.push(`/cp/${i + 1}`) + router.push(`/cp/${cp.id}`) }} > @@ -193,12 +199,152 @@ export default function CPPage() { ))} - -
女生列表加载中...
+ + {CP_LIST.filter((cp) => cp.gender === "女").map((cp) => ( +
router.push(`/cp/${cp.id}`)} + > +
+
+
+ {cp.name} +
+ {cp.online && ( +
+ )} +
+ +
+
+

{cp.name}

+ + {cp.gender} · {cp.age}岁 + +
+ +
+ + + {cp.rank} + + {cp.voice} +
+ +

{cp.bio}

+ +
+ {cp.tags.map((tag, j) => ( + + {tag} + + ))} +
+
+
+ +
+ + +
+
+ ))} - -
男生列表加载中...
+ + {CP_LIST.filter((cp) => cp.gender === "男").map((cp) => ( +
router.push(`/cp/${cp.id}`)} + > +
+
+
+ {cp.name} +
+ {cp.online && ( +
+ )} +
+ +
+
+

{cp.name}

+ + {cp.gender} · {cp.age}岁 + +
+ +
+ + + {cp.rank} + + {cp.voice} +
+ +

{cp.bio}

+ +
+ {cp.tags.map((tag, j) => ( + + {tag} + + ))} +
+
+
+ +
+ + +
+
+ ))}
diff --git a/app/guild/[id]/page.tsx b/app/guild/[id]/page.tsx index 3312eb4..29551b3 100644 --- a/app/guild/[id]/page.tsx +++ b/app/guild/[id]/page.tsx @@ -5,11 +5,62 @@ import { useRouter } from "next/navigation" import Image from "next/image" import { Button } from "@/components/ui/button" import { toast } from "@/hooks/use-toast" +import { useState } from "react" + +const guildData: Record = { + "1": { + name: "东东电竞", + logo: "/esports-team-logo.jpg", + cover: "/esports-tournament-stadium.jpg", + level: 10, + members: 1205, + rank: 1, + rating: 4.9, + description: "国服顶尖路人王聚集地,专注高端局陪练与代练业务。月入百万不是梦,加入我们,成就电竞梦想!", + benefits: [ + { title: "专属培训体系", desc: "王者荣耀/LOL职业教练一对一指导,快速提升技术", color: "border-primary" }, + { title: "优先派单特权", desc: "优质高价单优先派送,月收入提升50%", color: "border-secondary" }, + { title: "法律援助支持", desc: "专业律师团队,保障您的合法权益与收入", color: "border-accent" }, + { title: "线下基地入驻", desc: "杭州/上海5000平米电竞基地免费入住", color: "border-green-500" }, + ], + requirements: [ + { label: "游戏段位", text: "王者荣耀荣耀王者50星以上 / LOL大师以上 / 无畏契约超凡入圣" }, + { label: "语音要求", text: "普通话标准,声音清晰,具备良好的沟通能力" }, + { label: "设备要求", text: "拥有专业的电竞设备(电脑/手机)和安静的直播/游戏环境" }, + { label: "在线时间", text: "每天稳定在线时长不低于4小时" }, + ], + }, + "2": { + name: "星耀公会", + logo: "/esports-team-logo.jpg", + cover: "/esports-tournament-stadium.jpg", + level: 8, + members: 856, + rank: 3, + rating: 4.7, + description: "专注王者荣耀高端陪练,拥有多名国服百星大神。新人友好,带你快速上分!", + benefits: [ + { title: "新人培训", desc: "针对新人的系统培训,快速上手接单", color: "border-primary" }, + { title: "稳定派单", desc: "每日稳定订单量,收入有保障", color: "border-secondary" }, + { title: "技术交流", desc: "每周技术分享会,持续提升实力", color: "border-accent" }, + { title: "福利活动", desc: "定期举办线上活动和抽奖", color: "border-green-500" }, + ], + requirements: [ + { label: "游戏段位", text: "王者荣耀荣耀王者以上" }, + { label: "语音要求", text: "普通话标准,有耐心" }, + { label: "在线时间", text: "每天在线不低于3小时" }, + ], + }, +} export default function GuildDetailPage({ params }: { params: { id: string } }) { const router = useRouter() + const [isApplied, setIsApplied] = useState(false) + + const guild = guildData[params.id] || guildData["1"] const handleApply = () => { + setIsApplied(true) toast({ title: "申请已提交", description: "公会管理员将在24小时内审核您的申请", @@ -20,7 +71,7 @@ export default function GuildDetailPage({ params }: { params: { id: string } })
{/* Hero Section */}
- Cover + Cover
-
-

东东电竞

+

{guild.name}

- LV.10 顶级公会 + LV.{guild.level} 顶级公会
-

- 国服顶尖路人王聚集地,专注高端局陪练与代练业务。月入百万不是梦,加入我们,成就电竞梦想! -

+

{guild.description}

- 1,205 成员 + {guild.members.toLocaleString()} 成员 - 全区第 1 名 + 全区第 {guild.rank} 名 - 4.9 评分 + {guild.rating} 评分
@@ -80,22 +134,12 @@ export default function GuildDetailPage({ params }: { params: { id: string } }) 公会权益
-
-
专属培训体系
-
王者荣耀/LOL职业教练一对一指导,快速提升技术
-
-
-
优先派单特权
-
优质高价单优先派送,月收入提升50%
-
-
-
法律援助支持
-
专业律师团队,保障您的合法权益与收入
-
-
-
线下基地入驻
-
杭州/上海5000平米电竞基地免费入住
-
+ {guild.benefits.map((benefit: any, i: number) => ( +
+
{benefit.title}
+
{benefit.desc}
+
+ ))}
@@ -106,34 +150,15 @@ export default function GuildDetailPage({ params }: { params: { id: string } }) 入驻要求
-
-
-
- 游戏段位: - 王者荣耀荣耀王者50星以上 / LOL大师以上 / 无畏契约超凡入圣 + {guild.requirements.map((req: any, i: number) => ( +
+
+
+ {req.label}: + {req.text} +
-
-
-
-
- 语音要求: - 普通话标准,声音清晰,具备良好的沟通能力 -
-
-
-
-
- 设备要求: - 拥有专业的电竞设备(电脑/手机)和安静的直播/游戏环境 -
-
-
-
-
- 在线时间: - 每天稳定在线时长不低于4小时 -
-
+ ))}
diff --git a/app/live/page.tsx b/app/live/page.tsx index f4df9d3..1a69095 100644 --- a/app/live/page.tsx +++ b/app/live/page.tsx @@ -2,208 +2,609 @@ import type React from "react" -import { useState } from "react" +import { useState, useRef } from "react" import { useRouter } from "next/navigation" import Image from "next/image" -import { ArrowLeft, Heart, Eye, Search, Gamepad2 } from "lucide-react" +import { + Heart, + MessageCircle, + Share2, + Gift, + Music2, + Home, + Search, + Users, + Send, + Bookmark, + ShoppingCart, + X, +} from "lucide-react" +import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { toast } from "@/hooks/use-toast" +import { useAppContext } from "@/components/providers/app-provider" const STREAMERS = [ { id: "1", name: "GM-远洋", avatar: "/streamer-1.jpg", - title: "国服第一盲僧", + title: "国服第一盲僧 | 今晚冲击王者", game: "英雄联盟", - viewers: "12.5w", - likes: 8956, - isLive: true, - thumbnail: "/live-thumb-lol.jpg", + viewers: 125600, + likes: 89560, + comments: 3420, + shares: 1250, + isFollowed: false, + video: "/live-lol.jpg", + music: "英雄联盟 - 登峰造极", + course: { id: "1", name: "打野进阶课:从入门到王者", price: 299, lessons: 8 }, }, { id: "2", name: "卡若", avatar: "/streamer-2.jpg", - title: "职业战队退役", + title: "职业选手退役 | 无畏契约枪法教学", game: "无畏契约", - viewers: "8.2w", - likes: 5420, - isLive: true, - thumbnail: "/live-thumb-val.jpg", + viewers: 98000, + likes: 54200, + comments: 2180, + shares: 890, + isFollowed: false, + video: "/live-valorant.jpg", + music: "VALORANT - Die For You", + course: { id: "2", name: "无畏契约枪法训练营", price: 399, lessons: 10 }, }, { id: "3", - name: "小柠檬", + name: "小美", avatar: "/streamer-3.jpg", - title: "人皮话多", + title: "全国冠军 | 四指操作直播吃鸡", game: "和平精英", - viewers: "5.6w", - likes: 3280, - isLive: true, - thumbnail: "/live-thumb-pubg.jpg", + viewers: 145000, + likes: 78800, + comments: 4560, + shares: 1620, + isFollowed: false, + video: "/live-pubg.jpg", + music: "和平精英 - Winner Winner", + course: { id: "3", name: "和平精英四指操作教学", price: 199, lessons: 6 }, }, { id: "4", - name: "阿伟", + name: "星辰", avatar: "/streamer-4.jpg", - title: "绝地求生刚枪王", - game: "绝地求生", - viewers: "3.2w", - likes: 1890, - isLive: true, - thumbnail: "/live-thumb-pubg.jpg", + title: "原神攻略大神 | 深渊满星教学", + game: "原神", + viewers: 210000, + likes: 125200, + comments: 6890, + shares: 2120, + isFollowed: false, + video: "/live-genshin.jpg", + music: "原神 - 璃月港", + course: { id: "4", name: "原神深渊满星攻略", price: 149, lessons: 5 }, }, { id: "5", - name: "七七", + name: "阿杰", avatar: "/streamer-5.jpg", - title: "甜美声优", - game: "原神", - viewers: "6.8w", - likes: 4520, - isLive: true, - thumbnail: "/live-thumb-genshin.jpg", + title: "国服百星 | 巅峰赛冲分直播", + game: "王者荣耀", + viewers: 320000, + likes: 187800, + comments: 8120, + shares: 3680, + isFollowed: false, + video: "/live-hok.jpg", + music: "王者荣耀 - 战斗吧英雄", + course: { id: "5", name: "王者荣耀上分秘籍", price: 249, lessons: 8 }, }, { id: "6", - name: "大魔王", + name: "暗影", avatar: "/streamer-6.jpg", - title: "中单法王", - game: "英雄联盟", - viewers: "4.5w", - likes: 2680, - isLive: true, - thumbnail: "/live-thumb-lol.jpg", + title: "首杀团队成员 | 大秘境冲层教学", + game: "魔兽世界", + viewers: 75000, + likes: 38600, + comments: 2890, + shares: 860, + isFollowed: false, + video: "/live-wow.jpg", + music: "魔兽世界 - Arthas My Son", + course: { id: "6", name: "魔兽世界团本攻略", price: 499, lessons: 12 }, }, ] -const GAME_FILTERS = ["全部", "英雄联盟", "无畏契约", "和平精英", "原神", "王者荣耀", "绝地求生"] +const GIFTS = [ + { id: 1, name: "小心心", price: 1, icon: "💕" }, + { id: 2, name: "棒棒糖", price: 10, icon: "🍭" }, + { id: 3, name: "玫瑰花", price: 52, icon: "🌹" }, + { id: 4, name: "告白气球", price: 520, icon: "🎈" }, + { id: 5, name: "跑车", price: 5000, icon: "🏎️" }, + { id: 6, name: "火箭", price: 10000, icon: "🚀" }, +] -export default function LiveListPage() { +export default function TikTokStyleLivePage() { const router = useRouter() - const [activeFilter, setActiveFilter] = useState("全部") - const [likedStreamers, setLikedStreamers] = useState>(new Set()) + const { pay } = useAppContext() + const [currentIndex, setCurrentIndex] = useState(0) + const [streamers, setStreamers] = useState(STREAMERS) + const [showComments, setShowComments] = useState(false) + const [showGifts, setShowGifts] = useState(false) + const [showShare, setShowShare] = useState(false) + const [showCourse, setShowCourse] = useState(false) + const [comment, setComment] = useState("") + const [comments, setComments] = useState([ + { id: 1, user: "电竞迷", avatar: "/viewer-1.jpg", text: "主播太强了!", time: "刚刚" }, + { id: 2, user: "小飞侠", avatar: "/viewer-2.jpg", text: "666666", time: "1分钟前" }, + { id: 3, user: "游戏玩家", avatar: "/viewer-3.jpg", text: "学到了学到了", time: "2分钟前" }, + ]) + const [floatingHearts, setFloatingHearts] = useState<{ id: number; x: number }[]>([]) + const containerRef = useRef(null) + const startY = useRef(0) + const commentIdRef = useRef(4) - const filteredStreamers = activeFilter === "全部" ? STREAMERS : STREAMERS.filter((s) => s.game === activeFilter) + const currentStreamer = streamers[currentIndex] - const handleLike = (e: React.MouseEvent, streamerId: string) => { - e.stopPropagation() - setLikedStreamers((prev) => { - const newSet = new Set(prev) - if (newSet.has(streamerId)) { - newSet.delete(streamerId) - } else { - newSet.add(streamerId) + const handleTouchStart = (e: React.TouchEvent) => { + startY.current = e.touches[0].clientY + } + + const handleTouchEnd = (e: React.TouchEvent) => { + const endY = e.changedTouches[0].clientY + const diff = startY.current - endY + + if (Math.abs(diff) > 50) { + if (diff > 0 && currentIndex < streamers.length - 1) { + setCurrentIndex((prev) => prev + 1) + } else if (diff < 0 && currentIndex > 0) { + setCurrentIndex((prev) => prev - 1) } - return newSet + } + } + + const handleLike = () => { + setStreamers((prev) => prev.map((s, i) => (i === currentIndex ? { ...s, likes: s.likes + 1 } : s))) + const newHeart = { id: Date.now(), x: Math.random() * 40 - 20 } + setFloatingHearts((prev) => [...prev, newHeart]) + setTimeout(() => { + setFloatingHearts((prev) => prev.filter((h) => h.id !== newHeart.id)) + }, 1500) + } + + const handleFollow = () => { + setStreamers((prev) => prev.map((s, i) => (i === currentIndex ? { ...s, isFollowed: !s.isFollowed } : s))) + toast({ + title: currentStreamer.isFollowed ? "已取消关注" : "关注成功", + description: currentStreamer.isFollowed ? "" : `已关注 ${currentStreamer.name}`, }) } - return ( -
- {/* Header */} -
-
-
- -

直播

-
- -
+ const handleSendComment = () => { + if (!comment.trim()) return + const newComment = { + id: commentIdRef.current++, + user: "我", + avatar: "/user-avatar.jpg", + text: comment, + time: "刚刚", + } + setComments((prev) => [newComment, ...prev]) + setComment("") + setStreamers((prev) => prev.map((s, i) => (i === currentIndex ? { ...s, comments: s.comments + 1 } : s))) + toast({ title: "评论成功", description: "你的评论已发送" }) + } - {/* Game Filters */} -
-
- {GAME_FILTERS.map((filter) => ( - - ))} -
-
+ const handleSendGift = (gift: (typeof GIFTS)[0]) => { + pay(gift.price, "diamonds", `送出${gift.name}`, "product") + setShowGifts(false) + toast({ + title: "送礼成功", + description: `成功送出 ${gift.icon} ${gift.name}`, + }) + } + + const handleShare = (platform: string) => { + setStreamers((prev) => prev.map((s, i) => (i === currentIndex ? { ...s, shares: s.shares + 1 } : s))) + toast({ title: "分享成功", description: `已分享到${platform}` }) + setShowShare(false) + } + + const handleBuyCourse = () => { + const course = currentStreamer.course + pay(course.price, "coins", `购买${course.name}`, "product") + setShowCourse(false) + toast({ + title: "购买成功", + description: `已购买 ${currentStreamer.name} 的《${course.name}》课程`, + }) + setTimeout(() => { + router.push(`/course/${currentStreamer.id}`) + }, 1000) + } + + const formatNumber = (num: number) => { + if (num >= 10000) return (num / 10000).toFixed(1) + "w" + if (num >= 1000) return (num / 1000).toFixed(1) + "k" + return num.toString() + } + + return ( +
+ {/* 全屏直播背景 */} +
+ {currentStreamer.name} +
- {/* Live Grid */} -
- {filteredStreamers.map((streamer) => ( -
router.push(`/live/${streamer.id}`)} - className="bg-white/5 rounded-xl overflow-hidden border border-white/5 hover:border-primary/30 transition-all cursor-pointer group" - > - {/* Thumbnail */} -
- {streamer.name} -
- - {/* Live Badge */} -
- - 直播中 -
- - {/* Viewers */} -
- - {streamer.viewers} -
- - {/* Game Tag */} -
- - {streamer.game} -
- - {/* Like Button */} - -
- - {/* Info */} -
-
-
- {streamer.name} -
-
-

{streamer.name}

-

{streamer.title}

-
-
-
+ {/* 飘心动画 */} +
+ {floatingHearts.map((heart) => ( +
+
))}
+ +
+
+ +
+ + + +
+ +
+ +
+
+
+
+ {currentStreamer.name} +
+ +
+
+
+ {currentStreamer.name} + + {currentStreamer.game} + +
+
+ + {formatNumber(currentStreamer.viewers)}观看 +
+
+ +
+
+
+ + {/* 直播间信息 - 左侧底部 */} +
+ {/* 直播标题 */} +

{currentStreamer.title}

+ + {/* 音乐标签 */} +
+ +
+

{currentStreamer.music}

+
+
+ Music +
+
+
+ + {/* 右侧互动按钮 */} +
+ {/* 点赞 */} + + + {/* 评论 */} + + + {/* 收藏 */} + + + {/* 分享 */} + + + {/* 礼物 */} + + + {/* 课程 */} + +
+ + {/* 底部输入框 */} +
+
+
+ setComment(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && handleSendComment()} + /> +
+ +
+
+ + {/* 评论弹窗 */} + + + + {formatNumber(currentStreamer.comments)} 条评论 + + +
+ {comments.map((c) => ( +
+
+ {c.user} +
+
+
+ {c.user} + {c.time} +
+

{c.text}

+
+ +
+ ))} +
+
+ setComment(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && handleSendComment()} + /> + +
+
+
+ + {/* 礼物弹窗 */} + + + + 送礼物给 {currentStreamer.name} + +
+ {GIFTS.map((gift) => ( + + ))} +
+
+
+ + {/* 分享弹窗 */} + + + + 分享直播间 + +
+ {[ + { name: "微信", icon: "💬", color: "bg-green-500" }, + { name: "朋友圈", icon: "🌟", color: "bg-green-600" }, + { name: "QQ", icon: "🐧", color: "bg-blue-500" }, + { name: "微博", icon: "📢", color: "bg-red-500" }, + ].map((platform) => ( + + ))} +
+
+ + +
+
+
+ + {/* 课程弹窗 */} + + + + {currentStreamer.name} 的课程 + +
+
+
+
+ Course +
+
+

{currentStreamer.course.name}

+

{currentStreamer.course.lessons} 节课程

+
+ ¥{currentStreamer.course.price} + ¥{currentStreamer.course.price * 2} +
+
+
+
+ +
+
+
+ +
) } diff --git a/app/mall/gear/page.tsx b/app/mall/gear/page.tsx index 2562398..fd7a394 100644 --- a/app/mall/gear/page.tsx +++ b/app/mall/gear/page.tsx @@ -3,47 +3,79 @@ import { useRouter } from "next/navigation" import Image from "next/image" import { Button } from "@/components/ui/button" import { toast } from "@/hooks/use-toast" +import { ArrowLeft, ShoppingCart } from "lucide-react" export default function GearPage() { const router = useRouter() const products = [ - { id: 1, name: "罗技 G Pro X Superlight", price: 899, image: "/gear-mouse.jpg", tag: "职业首选" }, - { id: 2, name: "雷蛇 猎魂光蛛 V3", price: 1299, image: "/gear-keyboard.jpg", tag: "光轴科技" }, - { id: 3, name: "卓威 XL2546K", price: 3499, image: "/gear-monitor.jpg", tag: "360Hz" }, - { id: 4, name: "HyperX Cloud II", price: 599, image: "/gear-headset.jpg", tag: "7.1声道" }, + { id: 1, name: "罗技 G Pro X Superlight", price: 899, image: "/gear-mouse.jpg", tag: "职业首选", category: "鼠标" }, + { id: 2, name: "雷蛇 猎魂光蛛 V3", price: 1299, image: "/gear-keyboard.jpg", tag: "光轴科技", category: "键盘" }, + { id: 3, name: "卓威 XL2546K", price: 3499, image: "/gear-monitor.jpg", tag: "360Hz", category: "显示器" }, + { id: 4, name: "HyperX Cloud II", price: 599, image: "/gear-headset.jpg", tag: "7.1声道", category: "耳机" }, + { id: 5, name: "赛睿 QcK Heavy", price: 199, image: "/gear-mousepad.jpg", tag: "加厚版", category: "鼠标垫" }, + { id: 6, name: "电竞座椅 GT900", price: 1999, image: "/gear-chair.jpg", tag: "人体工学", category: "座椅" }, ] return (
-
- -

电竞外设

+
+
+ +

电竞外设

+
+
+ + {/* 分类筛选 */} +
+ {["全部", "鼠标", "键盘", "耳机", "显示器", "鼠标垫", "座椅"].map((cat, i) => ( + + ))} +
+
{products.map((p) => (
toast({ title: "加入购物车", description: p.name })} + className="glass-card rounded-xl overflow-hidden group cursor-pointer border border-white/5 hover:border-primary/30 transition-colors" > -
+
{p.name}
{p.tag}
+
+ {p.category} +
-

{p.name}

+

{p.name}

¥{p.price} -
diff --git a/app/mall/page.tsx b/app/mall/page.tsx index cc4fc5a..22d5337 100644 --- a/app/mall/page.tsx +++ b/app/mall/page.tsx @@ -8,7 +8,6 @@ import { Zap, Gift, Coins, - BookOpen, Hotel, Coffee, Trophy, @@ -16,7 +15,7 @@ import { Keyboard, Wallet, Gamepad2, - Gem, + CreditCard, } from "lucide-react" import { Button } from "@/components/ui/button" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" @@ -86,25 +85,6 @@ export default function MallPage() {
- {/* Banner */} -
-
router.push("/recharge")} - > -
-

首充双倍

-

限时特惠 赠送绝版头像框

- -
-
- -
-
-
- {/* Top Categories - 8 Items */}

@@ -121,11 +101,11 @@ export default function MallPage() { href: "/mall/companion?type=play", }, { - name: "大师课程", - icon: BookOpen, + name: "游戏点卡", + icon: CreditCard, color: "text-pink-400", bg: "bg-pink-500/10", - href: "/mall/companion?type=course", + href: "/mall/points", }, { name: "电竞外设", icon: Keyboard, color: "text-purple-400", bg: "bg-purple-500/10", href: "/mall/gear" }, { name: "电竞酒店", icon: Hotel, color: "text-orange-400", bg: "bg-orange-500/10", href: "/hotel" }, @@ -235,7 +215,6 @@ export default function MallPage() { - {/* Gift Content - Simplified */}
{[ { name: "棒棒糖", price: 10, icon: "🍭" }, @@ -264,7 +243,6 @@ export default function MallPage() { - {/* Exchange Content */}
{[ { name: "10元话费券", price: 1000, icon: Gift }, diff --git a/app/mall/points/[game]/client.tsx b/app/mall/points/[game]/client.tsx new file mode 100644 index 0000000..dd92224 --- /dev/null +++ b/app/mall/points/[game]/client.tsx @@ -0,0 +1,303 @@ +"use client" + +import { useState } from "react" +import { ArrowLeft, Check, ShoppingCart, Zap, Flame } from "lucide-react" +import Image from "next/image" +import { useRouter } from "next/navigation" +import { Button } from "@/components/ui/button" +import { useAppContext } from "@/components/providers/app-provider" +import { toast } from "@/hooks/use-toast" + +const gameData: Record< + string, + { + name: string + image: string + description: string + discount: string + tag?: string + options: { name: string; original: number; price: number; popular?: boolean }[] + } +> = { + wow: { + name: "魔兽世界", + image: "/point-card-wow.jpg", + description: "月卡/点卡充值", + discount: "9折", + tag: "经典", + options: [ + { name: "30天月卡", original: 75, price: 68, popular: true }, + { name: "90天季卡", original: 198, price: 178 }, + { name: "180天半年卡", original: 360, price: 320 }, + { name: "2000点卡", original: 100, price: 90 }, + { name: "5000点卡", original: 250, price: 225 }, + ], + }, + diablo: { + name: "暗黑破坏神4", + image: "/point-card-diablo.jpg", + description: "白金币充值", + discount: "85折", + tag: "热卖", + options: [ + { name: "500白金币", original: 45, price: 38, popular: true }, + { name: "1000白金币", original: 88, price: 75 }, + { name: "2800白金币", original: 198, price: 168 }, + { name: "5700白金币", original: 388, price: 330 }, + { name: "11500白金币", original: 648, price: 550 }, + ], + }, + hearthstone: { + name: "炉石传说", + image: "/point-card-hearthstone.jpg", + description: "战令/卡包充值", + discount: "88折", + tag: "新品", + options: [ + { name: "2卡包", original: 18, price: 16 }, + { name: "7卡包", original: 58, price: 51, popular: true }, + { name: "15卡包", original: 108, price: 95 }, + { name: "40卡包", original: 258, price: 227 }, + { name: "酒馆战令", original: 128, price: 113 }, + ], + }, + overwatch: { + name: "守望先锋2", + image: "/point-card-overwatch.jpg", + description: "代币充值", + discount: "9折", + options: [ + { name: "500代币", original: 35, price: 32 }, + { name: "1000代币", original: 68, price: 61, popular: true }, + { name: "2200代币", original: 128, price: 115 }, + { name: "5700代币", original: 298, price: 268 }, + { name: "11600代币", original: 518, price: 466 }, + ], + }, + lol: { + name: "英雄联盟", + image: "/point-card-lol.jpg", + description: "点券充值", + discount: "95折", + tag: "热门", + options: [ + { name: "100点券", original: 10, price: 10 }, + { name: "350点券", original: 35, price: 33, popular: true }, + { name: "650点券", original: 65, price: 62 }, + { name: "1380点券", original: 138, price: 131 }, + { name: "3380点券", original: 338, price: 321 }, + ], + }, + hok: { + name: "王者荣耀", + image: "/point-card-hok.jpg", + description: "点券充值", + discount: "95折", + tag: "热门", + options: [ + { name: "60点券", original: 6, price: 6 }, + { name: "300点券", original: 30, price: 29, popular: true }, + { name: "680点券", original: 68, price: 65 }, + { name: "1280点券", original: 128, price: 122 }, + { name: "2480点券", original: 248, price: 236 }, + ], + }, + pubg: { + name: "和平精英", + image: "/point-card-pubg.jpg", + description: "点券充值", + discount: "92折", + tag: "热门", + options: [ + { name: "60点券", original: 6, price: 6 }, + { name: "300点券", original: 30, price: 28, popular: true }, + { name: "600点券", original: 60, price: 55 }, + { name: "1500点券", original: 150, price: 138 }, + { name: "3000点券", original: 300, price: 276 }, + ], + }, + genshin: { + name: "原神", + image: "/point-card-genshin.jpg", + description: "创世结晶充值", + discount: "9折", + tag: "热卖", + options: [ + { name: "60创世结晶", original: 6, price: 6 }, + { name: "300创世结晶", original: 30, price: 27, popular: true }, + { name: "980创世结晶", original: 98, price: 88 }, + { name: "1980创世结晶", original: 198, price: 178 }, + { name: "3280创世结晶", original: 328, price: 295 }, + ], + }, + valorant: { + name: "无畏契约", + image: "/point-card-valorant.jpg", + description: "VP点数充值", + discount: "88折", + tag: "新品", + options: [ + { name: "475VP", original: 35, price: 31 }, + { name: "1000VP", original: 68, price: 60, popular: true }, + { name: "2050VP", original: 128, price: 113 }, + { name: "3650VP", original: 198, price: 174 }, + { name: "5350VP", original: 288, price: 253 }, + ], + }, + fortnite: { + name: "堡垒之夜", + image: "/point-card-fortnite.jpg", + description: "V-Bucks充值", + discount: "85折", + options: [ + { name: "1000V-Bucks", original: 68, price: 58 }, + { name: "2800V-Bucks", original: 168, price: 143, popular: true }, + { name: "5000V-Bucks", original: 288, price: 245 }, + { name: "13500V-Bucks", original: 648, price: 551 }, + ], + }, + apex: { + name: "Apex英雄", + image: "/point-card-apex.jpg", + description: "Apex硬币充值", + discount: "9折", + options: [ + { name: "1000硬币", original: 68, price: 61 }, + { name: "2150硬币", original: 128, price: 115, popular: true }, + { name: "4350硬币", original: 248, price: 223 }, + { name: "6700硬币", original: 388, price: 349 }, + { name: "11500硬币", original: 648, price: 583 }, + ], + }, + cs2: { + name: "CS2", + image: "/point-card-cs2.jpg", + description: "Steam钱包充值", + discount: "95折", + options: [ + { name: "¥50钱包", original: 50, price: 48 }, + { name: "¥100钱包", original: 100, price: 95, popular: true }, + { name: "¥200钱包", original: 200, price: 190 }, + { name: "¥500钱包", original: 500, price: 475 }, + ], + }, +} + +export default function GamePointCardClient({ gameId }: { gameId: string }) { + const router = useRouter() + const { pay } = useAppContext() + const [selectedOption, setSelectedOption] = useState(null) + + const game = gameData[gameId] + + if (!game) { + return ( +
+

游戏不存在

+ +
+ ) + } + + const handlePurchase = () => { + if (selectedOption === null) { + toast({ title: "请选择充值金额", variant: "destructive" }) + return + } + const option = game.options[selectedOption] + pay(option.price, "diamonds", `${game.name} ${option.name}`, "product") + router.push("/mall") + } + + return ( +
+ {/* Header with Image */} +
+ {game.name} +
+
+ + {game.tag && ( +
{game.tag}
+ )} +
+
+
+ + {game.discount} 限时优惠 +
+

{game.name}

+

{game.description}

+
+
+ + {/* Options */} +
+

+ + 选择充值金额 +

+ + {game.options.map((option, i) => ( +
setSelectedOption(i)} + className={`bg-[#1A1A22] rounded-xl p-4 flex items-center justify-between border-2 transition-all cursor-pointer ${ + selectedOption === i ? "border-primary bg-primary/5" : "border-transparent hover:border-white/10" + }`} + > +
+
+ {selectedOption === i && } +
+
+
+

{option.name}

+ {option.popular && ( + + 推荐 + + )} +
+
+ ¥{option.original} + 省¥{option.original - option.price} +
+
+
+ ¥{option.price} +
+ ))} +
+ +
+
+
+ {selectedOption !== null ? ( + <> +

已选: {game.options[selectedOption].name}

+

¥{game.options[selectedOption].price}

+ + ) : ( +

请选择充值金额

+ )} +
+ +
+
+
+ ) +} diff --git a/app/mall/points/[game]/loading.tsx b/app/mall/points/[game]/loading.tsx new file mode 100644 index 0000000..ff38ec6 --- /dev/null +++ b/app/mall/points/[game]/loading.tsx @@ -0,0 +1,10 @@ +export default function Loading() { + return ( +
+
+
+

加载中...

+
+
+ ) +} diff --git a/app/mall/points/[game]/page.tsx b/app/mall/points/[game]/page.tsx index 6b942bf..8d798ff 100644 --- a/app/mall/points/[game]/page.tsx +++ b/app/mall/points/[game]/page.tsx @@ -1,12 +1,6 @@ "use client" - -import { useState } from "react" -import { ArrowLeft, Check, Share2, Star, ShoppingCart, Zap } from "lucide-react" -import Image from "next/image" -import { useRouter } from "next/navigation" -import { Button } from "@/components/ui/button" -import { useAppContext } from "@/components/providers/app-provider" -import { toast } from "@/hooks/use-toast" +import { Suspense } from "react" +import GamePointCardClient from "./client" const gameData: Record< string, @@ -15,14 +9,16 @@ const gameData: Record< image: string description: string discount: string + tag?: string options: { name: string; original: number; price: number; popular?: boolean }[] } > = { wow: { name: "魔兽世界", - image: "/game-wow.jpg", + image: "/point-card-wow.jpg", description: "月卡/点卡充值", discount: "9折", + tag: "经典", options: [ { name: "30天月卡", original: 75, price: 68, popular: true }, { name: "90天季卡", original: 198, price: 178 }, @@ -33,9 +29,10 @@ const gameData: Record< }, diablo: { name: "暗黑破坏神4", - image: "/game-diablo.jpg", + image: "/point-card-diablo.jpg", description: "白金币充值", discount: "85折", + tag: "热卖", options: [ { name: "500白金币", original: 45, price: 38, popular: true }, { name: "1000白金币", original: 88, price: 75 }, @@ -46,9 +43,10 @@ const gameData: Record< }, hearthstone: { name: "炉石传说", - image: "/game-hearthstone.jpg", + image: "/point-card-hearthstone.jpg", description: "战令/卡包充值", discount: "88折", + tag: "新品", options: [ { name: "2卡包", original: 18, price: 16 }, { name: "7卡包", original: 58, price: 51, popular: true }, @@ -59,7 +57,7 @@ const gameData: Record< }, overwatch: { name: "守望先锋2", - image: "/game-overwatch.jpg", + image: "/point-card-overwatch.jpg", description: "代币充值", discount: "9折", options: [ @@ -70,138 +68,127 @@ const gameData: Record< { name: "11600代币", original: 518, price: 466 }, ], }, + lol: { + name: "英雄联盟", + image: "/point-card-lol.jpg", + description: "点券充值", + discount: "95折", + tag: "热门", + options: [ + { name: "100点券", original: 10, price: 10 }, + { name: "350点券", original: 35, price: 33, popular: true }, + { name: "650点券", original: 65, price: 62 }, + { name: "1380点券", original: 138, price: 131 }, + { name: "3380点券", original: 338, price: 321 }, + ], + }, + hok: { + name: "王者荣耀", + image: "/point-card-hok.jpg", + description: "点券充值", + discount: "95折", + tag: "热门", + options: [ + { name: "60点券", original: 6, price: 6 }, + { name: "300点券", original: 30, price: 29, popular: true }, + { name: "680点券", original: 68, price: 65 }, + { name: "1280点券", original: 128, price: 122 }, + { name: "2480点券", original: 248, price: 236 }, + ], + }, + pubg: { + name: "和平精英", + image: "/point-card-pubg.jpg", + description: "点券充值", + discount: "92折", + tag: "热门", + options: [ + { name: "60点券", original: 6, price: 6 }, + { name: "300点券", original: 30, price: 28, popular: true }, + { name: "600点券", original: 60, price: 55 }, + { name: "1500点券", original: 150, price: 138 }, + { name: "3000点券", original: 300, price: 276 }, + ], + }, + genshin: { + name: "原神", + image: "/point-card-genshin.jpg", + description: "创世结晶充值", + discount: "9折", + tag: "热卖", + options: [ + { name: "60创世结晶", original: 6, price: 6 }, + { name: "300创世结晶", original: 30, price: 27, popular: true }, + { name: "980创世结晶", original: 98, price: 88 }, + { name: "1980创世结晶", original: 198, price: 178 }, + { name: "3280创世结晶", original: 328, price: 295 }, + ], + }, + valorant: { + name: "无畏契约", + image: "/point-card-valorant.jpg", + description: "VP点数充值", + discount: "88折", + tag: "新品", + options: [ + { name: "475VP", original: 35, price: 31 }, + { name: "1000VP", original: 68, price: 60, popular: true }, + { name: "2050VP", original: 128, price: 113 }, + { name: "3650VP", original: 198, price: 174 }, + { name: "5350VP", original: 288, price: 253 }, + ], + }, + fortnite: { + name: "堡垒之夜", + image: "/point-card-fortnite.jpg", + description: "V-Bucks充值", + discount: "85折", + options: [ + { name: "1000V-Bucks", original: 68, price: 58 }, + { name: "2800V-Bucks", original: 168, price: 143, popular: true }, + { name: "5000V-Bucks", original: 288, price: 245 }, + { name: "13500V-Bucks", original: 648, price: 551 }, + ], + }, + apex: { + name: "Apex英雄", + image: "/point-card-apex.jpg", + description: "Apex硬币充值", + discount: "9折", + options: [ + { name: "1000硬币", original: 68, price: 61 }, + { name: "2150硬币", original: 128, price: 115, popular: true }, + { name: "4350硬币", original: 248, price: 223 }, + { name: "6700硬币", original: 388, price: 349 }, + { name: "11500硬币", original: 648, price: 583 }, + ], + }, + cs2: { + name: "CS2", + image: "/point-card-cs2.jpg", + description: "Steam钱包充值", + discount: "95折", + options: [ + { name: "¥50钱包", original: 50, price: 48 }, + { name: "¥100钱包", original: 100, price: 95, popular: true }, + { name: "¥200钱包", original: 200, price: 190 }, + { name: "¥500钱包", original: 500, price: 475 }, + ], + }, } -export default function GamePointCardPage({ params }: { params: { game: string } }) { - const router = useRouter() - const { pay } = useAppContext() - const [selectedOption, setSelectedOption] = useState(null) - - const game = gameData[params.game] - - if (!game) { - return ( -
-

游戏不存在

-
- ) - } - - const handlePurchase = () => { - if (selectedOption === null) { - toast({ title: "请选择充值金额", variant: "destructive" }) - return - } - const option = game.options[selectedOption] - pay(option.price, "diamonds", `${game.name} ${option.name}`, "product") - } +export default async function GamePointCardPage({ params }: { params: Promise<{ game: string }> }) { + const resolvedParams = await params return ( -
- {/* Header */} -
- {game.name} -
-
- + +
-
-
- {game.discount} 优惠 -
-

{game.name}

-

{game.description}

-
-
- - {/* Options */} -
-

- - 选择充值金额 -

- - {game.options.map((option, i) => ( -
setSelectedOption(i)} - className={`bg-[#1A1A22] rounded-xl p-4 flex items-center justify-between border-2 transition-all cursor-pointer ${ - selectedOption === i ? "border-primary bg-primary/5" : "border-transparent hover:border-white/10" - }`} - > -
-
- {selectedOption === i && } -
-
-
-

{option.name}

- {option.popular && ( - - 推荐 - - )} -
-
- ¥{option.original} - 省¥{option.original - option.price} -
-
-
- ¥{option.price} -
- ))} -
- - {/* Streamer Promo */} -
-
-
-
- -
-
-

分享给粉丝赚佣金

-

每单返利高达20%

-
- -
-
-
- - {/* Fixed Bottom */} -
-
-
- {selectedOption !== null && ( - <> -

已选: {game.options[selectedOption].name}

-

¥{game.options[selectedOption].price}

- - )} -
- -
-
-
+ } + > + + ) } diff --git a/app/mall/points/loading.tsx b/app/mall/points/loading.tsx new file mode 100644 index 0000000..f15322a --- /dev/null +++ b/app/mall/points/loading.tsx @@ -0,0 +1,3 @@ +export default function Loading() { + return null +} diff --git a/app/mall/points/page.tsx b/app/mall/points/page.tsx index 9825c6c..0d2c3c0 100644 --- a/app/mall/points/page.tsx +++ b/app/mall/points/page.tsx @@ -1,113 +1,78 @@ "use client" import { useState } from "react" -import { ArrowLeft, Gift, Zap, Share2, ShoppingCart, Flame } from "lucide-react" +import { ArrowLeft, Gift, Zap, Share2, Flame, Search } from "lucide-react" import Image from "next/image" import { useRouter } from "next/navigation" import { Button } from "@/components/ui/button" -import { useAppContext } from "@/components/providers/app-provider" +import { Input } from "@/components/ui/input" import { toast } from "@/hooks/use-toast" export default function PointCardsPage() { const router = useRouter() - const { wallet, pay } = useAppContext() + const [searchQuery, setSearchQuery] = useState("") const [selectedGame, setSelectedGame] = useState(null) const games = [ - { - id: "wow", - name: "魔兽世界", - image: "/game-wow.jpg", - discount: "9折", - tag: "限时", - description: "月卡/点卡充值", - options: [ - { name: "30天月卡", original: 75, price: 68, popular: true }, - { name: "90天季卡", original: 198, price: 178 }, - { name: "180天半年卡", original: 360, price: 320 }, - { name: "2000点卡", original: 100, price: 90 }, - { name: "5000点卡", original: 250, price: 225 }, - ], - }, + { id: "wow", name: "魔兽世界", image: "/point-card-wow.jpg", discount: "9折", tag: "经典", category: "PC" }, { id: "diablo", name: "暗黑破坏神4", - image: "/game-diablo.jpg", + image: "/point-card-diablo.jpg", discount: "85折", tag: "热卖", - description: "白金币充值", - options: [ - { name: "500白金币", original: 45, price: 38, popular: true }, - { name: "1000白金币", original: 88, price: 75 }, - { name: "2800白金币", original: 198, price: 168 }, - { name: "5700白金币", original: 388, price: 330 }, - { name: "11500白金币", original: 648, price: 550 }, - ], + category: "PC", }, { id: "hearthstone", name: "炉石传说", - image: "/game-hearthstone.jpg", + image: "/point-card-hearthstone.jpg", discount: "88折", tag: "新品", - description: "战令/卡包充值", - options: [ - { name: "2卡包", original: 18, price: 16 }, - { name: "7卡包", original: 58, price: 51, popular: true }, - { name: "15卡包", original: 108, price: 95 }, - { name: "40卡包", original: 258, price: 227 }, - { name: "酒馆战令", original: 128, price: 113 }, - ], + category: "全平台", }, { id: "overwatch", name: "守望先锋2", - image: "/game-overwatch.jpg", + image: "/point-card-overwatch.jpg", discount: "9折", tag: "", - description: "代币充值", - options: [ - { name: "500代币", original: 35, price: 32 }, - { name: "1000代币", original: 68, price: 61, popular: true }, - { name: "2200代币", original: 128, price: 115 }, - { name: "5700代币", original: 298, price: 268 }, - { name: "11600代币", original: 518, price: 466 }, - ], + category: "PC", + }, + { id: "lol", name: "英雄联盟", image: "/point-card-lol.jpg", discount: "95折", tag: "热门", category: "PC" }, + { id: "hok", name: "王者荣耀", image: "/point-card-hok.jpg", discount: "95折", tag: "热门", category: "手游" }, + { id: "pubg", name: "和平精英", image: "/point-card-pubg.jpg", discount: "92折", tag: "热门", category: "手游" }, + { id: "genshin", name: "原神", image: "/point-card-genshin.jpg", discount: "9折", tag: "热卖", category: "全平台" }, + { + id: "valorant", + name: "无畏契约", + image: "/point-card-valorant.jpg", + discount: "88折", + tag: "新品", + category: "PC", }, { - id: "lol", - name: "英雄联盟", - image: "/game-lol.jpg", - discount: "95折", - tag: "热门", - description: "点券充值", - options: [ - { name: "100点券", original: 10, price: 10 }, - { name: "350点券", original: 35, price: 33, popular: true }, - { name: "650点券", original: 65, price: 62 }, - { name: "1380点券", original: 138, price: 131 }, - { name: "3380点券", original: 338, price: 321 }, - ], - }, - { - id: "hok", - name: "王者荣耀", - image: "/game-hok.jpg", - discount: "95折", - tag: "热门", - description: "点券充值", - options: [ - { name: "60点券", original: 6, price: 6 }, - { name: "300点券", original: 30, price: 29, popular: true }, - { name: "680点券", original: 68, price: 65 }, - { name: "1280点券", original: 128, price: 122 }, - { name: "2480点券", original: 248, price: 236 }, - ], + id: "fortnite", + name: "堡垒之夜", + image: "/point-card-fortnite.jpg", + discount: "85折", + tag: "", + category: "全平台", }, + { id: "apex", name: "Apex英雄", image: "/point-card-apex.jpg", discount: "9折", tag: "", category: "全平台" }, + { id: "cs2", name: "CS2", image: "/point-card-cs2.jpg", discount: "95折", tag: "", category: "PC" }, ] + const filteredGames = games.filter((game) => game.name.toLowerCase().includes(searchQuery.toLowerCase())) + + const categories = ["全部", "PC", "手游", "全平台"] + const [selectedCategory, setSelectedCategory] = useState("全部") + + const displayGames = + selectedCategory === "全部" ? filteredGames : filteredGames.filter((g) => g.category === selectedCategory) + const handlePurchase = (gameName: string, optionName: string, price: number) => { - pay(price, "diamonds", `${gameName} ${optionName}`, "product") + // Placeholder for payment logic } return ( @@ -124,6 +89,19 @@ export default function PointCardsPage() {
+ {/* Search */} +
+
+ + setSearchQuery(e.target.value)} + placeholder="搜索游戏..." + className="pl-10 bg-white/5 border-white/10" + /> +
+
+ {/* Promotion Banner */}
@@ -146,23 +124,34 @@ export default function PointCardsPage() {
+ {/* Category Tabs */} +
+ {categories.map((cat) => ( + + ))} +
+ {/* Game Cards Grid */}

- 热门游戏点卡 + 热门游戏点卡 ({displayGames.length})

- {games.map((game) => ( + {displayGames.map((game) => (
setSelectedGame(selectedGame === game.id ? null : game.id)} + className="bg-[#1A1A22] rounded-xl overflow-hidden border border-white/5 hover:border-primary/50 transition-all cursor-pointer active:scale-95" + onClick={() => router.push(`/mall/points/${game.id}`)} >
{game.name} @@ -174,7 +163,7 @@ export default function PointCardsPage() { )}

{game.name}

-

{game.description}

+

{game.category}

{game.discount} @@ -185,72 +174,13 @@ export default function PointCardsPage() {
- {/* Selected Game Options */} - {selectedGame && ( -
-

- - 选择充值金额 -

- -
- {games - .find((g) => g.id === selectedGame) - ?.options.map((option, i) => ( -
-
- {option.popular && ( -
- 推荐 -
- )} -
-

{option.name}

-
- ¥{option.original} - 省¥{option.original - option.price} -
-
-
-
- ¥{option.price} - -
-
- ))} -
- - {/* Share Button */} -
- -
-
- )} + {/* Share Floating Button */} +
) } diff --git a/app/messages/page.tsx b/app/messages/page.tsx index 09644a6..01f8001 100644 --- a/app/messages/page.tsx +++ b/app/messages/page.tsx @@ -1,6 +1,6 @@ "use client" -import { ArrowLeft, Bell, MoreHorizontal } from "lucide-react" +import { ArrowLeft, Bell, MoreHorizontal, MessageCircle, Users } from "lucide-react" import Link from "next/link" import Image from "next/image" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" @@ -10,7 +10,7 @@ export default function MessagesPage() { { id: 1, user: "GM-远洋", - avatar: "/professional-esports-player-male-headset-focused.jpg", + avatar: "/streamer-1.jpg", content: "大神,今晚有空带我上分吗?", time: "10:30", unread: 2, @@ -28,7 +28,7 @@ export default function MessagesPage() { { id: 3, user: "小柠檬", - avatar: "/cute-female-gamer-streamer-headphones-smiling.jpg", + avatar: "/cp-avatar-2.jpg", content: "谢谢你的礼物!下次一起玩呀~", time: "昨天", unread: 0, @@ -37,12 +37,30 @@ export default function MessagesPage() { { id: 4, user: "车队助手", - avatar: "/esports-team-logo-blue.png", + avatar: "/esports-team-logo.jpg", content: "您申请加入的【王者荣耀五排车队】已同意", time: "前天", unread: 1, type: "system", }, + { + id: 5, + user: "电竞酒店客服", + avatar: "/hotel-icon.jpg", + content: "您预订的电竞双人房已确认,期待您的光临~", + time: "3天前", + unread: 0, + type: "system", + }, + { + id: 6, + user: "梦之队·队长", + avatar: "/streamer-3.jpg", + content: "欢迎加入我们的战队!有空一起训练", + time: "3天前", + unread: 0, + type: "chat", + }, ] return ( @@ -65,36 +83,33 @@ export default function MessagesPage() { + 聊天 + 通知
- + {messages .filter((m) => m.type === "chat") .map((msg) => ( -
-
- {msg.user} +
+ {msg.user}
{msg.unread > 0 && (
@@ -109,11 +124,11 @@ export default function MessagesPage() {

{msg.content}

-
+ ))} - + {messages .filter((m) => m.type === "system") .map((msg) => ( @@ -121,8 +136,8 @@ export default function MessagesPage() { key={msg.id} className="flex items-center gap-3 p-3 rounded-xl hover:bg-white/5 transition-colors cursor-pointer" > -
- +
+ {msg.user}
@@ -136,6 +151,36 @@ export default function MessagesPage() { ))} + +
+

快捷入口

+
+ +
+ +
+ 公会群聊 + + +
+ +
+ CP聊天 + + +
+ +
+ 陪练私信 + + +
+ +
+ 明星社群 + +
+
) } diff --git a/app/moments/page.tsx b/app/moments/page.tsx index 6a36f4f..c51212c 100644 --- a/app/moments/page.tsx +++ b/app/moments/page.tsx @@ -1,120 +1,135 @@ -"use client" // Convert to client component +"use client" -import { Trophy, Search, Heart, MessageCircle, Share2 } from "lucide-react" +import { Trophy, Search, Heart, MessageCircle, Share2, Gift, Music } from "lucide-react" import Image from "next/image" -import { toast } from "@/hooks/use-toast" // Import toast -import { useState } from "react" // Added state -import { useRouter } from "next/navigation" // Added useRouter +import { toast } from "@/hooks/use-toast" +import { useState } from "react" +import { useRouter } from "next/navigation" -const liveStreams = [ - { - id: 101, - user: "GM-远洋", - title: "国服第一盲僧 冲分教学", - cover: "league_of_legends_gameplay", - avatar: "gamer_boy_avatar", - viewers: "12.5w", - location: "杭州", - }, - { - id: 102, - user: "小柠檬", - title: "人皮话多 甜美声优在线", - cover: "cute_gamer_girl_streaming", - avatar: "gamer_girl_avatar", - viewers: "8.2k", - location: "上海", - }, - { - id: 103, - user: "魔兽老张", - title: "ICC 25H全通团 缺强力DPS", - cover: "world_of_warcraft_raid", - avatar: "orc_avatar", - viewers: "5.6k", - location: "北京", - }, - { - id: 104, - user: "阿伟刚枪", - title: "绝地求生 单人四排", - cover: "pubg_gameplay_intense", - avatar: "fps_gamer_avatar", - viewers: "3.4w", - location: "成都", - }, -] - -const moments = [ +const mixedFeed = [ { id: 1, user: "GM-远洋", - avatar: "gamer_girl_avatar_cute", // Fixed hardcoded path to keyword - desc: "可惜不是你喜欢的甜妹音 😷 #电竞少女 #英雄联盟 #日常", - video: "esports_streaming_vertical_setup", // Fixed path - likes: "1.2w", + avatar: "/streamer-1.jpg", + desc: "国服第一盲僧在线教学,这波操作你学会了吗? #英雄联盟 #教学", + video: "/live-lol.jpg", + likes: "12.5w", comments: 458, isLive: true, + type: "live", + roomId: 1, hasCourse: true, courseTitle: "打野进阶课", + courseId: 1, }, { id: 2, - user: "卡若", - avatar: "pro_gamer_male_avatar", // Fixed hardcoded path - desc: "中单刺客教学,这波操作你学会了吗? #英雄联盟 #教学", - video: "lol_gameplay_highlight_screen", // Fixed path - likes: "8.5k", + user: "小柠檬", + avatar: "/streamer-2.jpg", + desc: "可惜不是你喜欢的甜妹音 😷 #电竞少女 #日常", + video: "/live-valorant.jpg", + likes: "8.2k", comments: 230, - isLive: false, - hasCourse: true, - courseTitle: "中单刺客通关指南", + isLive: true, + type: "live", + roomId: 2, + hasCourse: false, }, { id: 3, user: "魔兽老张", - avatar: "wow_orc_player_avatar", // Fixed hardcoded path + avatar: "/streamer-3.jpg", desc: "ICC 25人H 教授打法细节讲解 #魔兽世界 #WLK", - video: "wow_raid_boss_fight", // Fixed path - likes: "3.2k", + video: "/live-wow.jpg", + likes: "5.6k", comments: 120, isLive: false, + type: "video", + hasCourse: true, + courseTitle: "ICC攻略大全", + courseId: 3, + }, + { + id: 4, + user: "阿伟刚枪", + avatar: "/streamer-4.jpg", + desc: "绝地求生单人四排 今天吃鸡了吗? #和平精英 #吃鸡", + video: "/live-pubg.jpg", + likes: "3.4w", + comments: 186, + isLive: true, + type: "live", + roomId: 4, hasCourse: false, }, + { + id: 5, + user: "原神小可爱", + avatar: "/streamer-5.jpg", + desc: "新角色抽卡实况!看看今天欧不欧 #原神 #抽卡", + video: "/live-genshin.jpg", + likes: "6.8k", + comments: 342, + isLive: false, + type: "video", + hasCourse: false, + }, + { + id: 6, + user: "王者一哥", + avatar: "/streamer-6.jpg", + desc: "国服韩信教学 巅峰赛冲刺中 #王者荣耀 #教学", + video: "/live-hok.jpg", + likes: "9.2w", + comments: 567, + isLive: true, + type: "live", + roomId: 6, + hasCourse: true, + courseTitle: "韩信实战技巧", + courseId: 6, + }, ] -const mixedFeed = [ - ...moments.map((m) => ({ ...m, type: "video" })), - ...liveStreams.map((l) => ({ - id: l.id + 1000, - user: l.user, - avatar: l.avatar, - desc: l.title, - video: l.cover, // This will be used for the background image - likes: l.viewers, - comments: 99, - isLive: true, - type: "live", - roomId: l.id, // Added roomId for navigation - })), -].sort(() => Math.random() - 0.5) - export default function MomentsPage() { - const router = useRouter() // Initialize router - const [activeTab, setActiveTab] = useState("recommend") // Changed default to recommend + const router = useRouter() + const [activeTab, setActiveTab] = useState("recommend") + const [likedItems, setLikedItems] = useState([]) + const [likeCounts, setLikeCounts] = useState>({}) - const handleLike = () => toast({ title: "点赞成功", description: "已添加到我喜欢的视频" }) - const handleShare = () => toast({ title: "分享成功", description: "链接已复制到剪贴板" }) - const handleGift = () => toast({ title: "礼物发送成功", description: "主播已收到您的心意" }) - const handleRefresh = () => { - toast({ title: "刷新成功", description: "已为您推荐新的热门直播" }) + const handleLike = (id: number, originalLikes: string) => { + if (likedItems.includes(id)) { + setLikedItems(likedItems.filter((i) => i !== id)) + setLikeCounts((prev) => ({ ...prev, [id]: originalLikes })) + } else { + setLikedItems([...likedItems, id]) + // 简单增加点赞数 + const numLikes = Number.parseFloat(originalLikes.replace(/[wk万千]/g, "")) + const newLikes = + originalLikes.includes("w") || originalLikes.includes("万") + ? `${(numLikes + 0.1).toFixed(1)}w` + : originalLikes.includes("k") || originalLikes.includes("千") + ? `${(numLikes + 0.1).toFixed(1)}k` + : `${numLikes + 1}` + setLikeCounts((prev) => ({ ...prev, [id]: newLikes })) + toast({ title: "点赞成功", description: "已添加到我喜欢的视频" }) + } + } + + const handleShare = () => { + navigator.clipboard?.writeText(window.location.href) + toast({ title: "分享成功", description: "链接已复制到剪贴板" }) + } + + const handleComment = (id: number) => { + toast({ title: "评论", description: "评论功能开发中..." }) } return (
{/* Top Navigation */} -
-
+
+
- +
- {/* Main Content Area - Scroll Snap */} + {/* Main Content Area */}
{activeTab === "recommend" && ( -
- {/* Rendering Mixed Feed */} - {mixedFeed.map((item, i) => ( -
- Content +
+ {mixedFeed.map((item) => ( +
+ {/* Background Image */} + Content
+ {/* Live Badge */} + {item.isLive && ( +
+
+ 直播中 +
+ )} + + {/* Click to Enter Live */} {item.type === "live" && ( - <> -
-
- 直播中 + )} {/* Right Sidebar Actions */} -
- {" "} - {/* Added pointer-events-none to prevent blocking click */} -
- {" "} - {/* Re-enable pointer events for buttons */} -
- User +
+ {/* Avatar */} +
+
+ {item.user}
-
+
+
-
- - {item.likes} -
-
- - {item.comments} -
-
- - 分享 -
+ + {/* Like */} + + + {/* Comment */} + + + {/* Share */} + + + {/* Gift - Only for live */} + {item.isLive && ( + + )}
{/* Bottom Info */} -
+

@{item.user}

-

{item.desc}

- {/* @ts-ignore */} +

{item.desc}

+ + {/* Course Badge */} {item.hasCourse && ( -
+
+ )} + + {/* Music Bar */} +
+ +
原声 - {item.user}
+
))} @@ -215,8 +249,12 @@ export default function MomentsPage() { )} {activeTab === "follow" && ( -
+
+
+ +

暂无关注内容

+

去推荐页关注你喜欢的主播吧

)}
diff --git a/app/page.tsx b/app/page.tsx index fc1fe9f..35d3c29 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -4,16 +4,17 @@ import { Search, Bell, Flame, - Trophy, - Users, Sword, Crosshair, Crown, Gift, Zap, - ShoppingBag, - Star, - Sparkles, + Building2, + Gamepad2, + Target, + Shield, + Wand2, + Users, } from "lucide-react" import Image from "next/image" import Link from "next/link" @@ -35,38 +36,41 @@ export default function HomePage() { id: "1", name: "GM-远洋", title: "国服第一盲僧", - price: "50币/局", - image: "/avatar-1.jpg", + heat: "125.6w", + fans: "46.8w", + image: "/streamer-1.jpg", isLive: true, }, { id: "2", name: "卡若", title: "职业战队退役", - price: "80币/局", - image: "/avatar-2.jpg", + heat: "82.3w", + fans: "32.5w", + image: "/streamer-2.jpg", isLive: true, }, { id: "3", name: "小柠檬", title: "人皮话多", - price: "30币/局", - image: "/avatar-3.jpg", + heat: "56.2w", + fans: "18.9w", + image: "/streamer-3.jpg", isLive: false, }, { id: "4", name: "阿伟", title: "绝地求生刚枪王", - price: "60币/局", - image: "/avatar-4.jpg", + heat: "42.1w", + fans: "12.6w", + image: "/streamer-4.jpg", isLive: false, }, ] const gamePointCards = [ - { name: "魔兽世界", icon: "/game-wow.jpg", discount: "9折", tag: "限时", link: "/mall/points/wow" }, { name: "暗黑破坏神4", icon: "/game-diablo.jpg", discount: "85折", tag: "热卖", link: "/mall/points/diablo" }, { name: "炉石传说", @@ -76,12 +80,70 @@ export default function HomePage() { link: "/mall/points/hearthstone", }, { name: "守望先锋2", icon: "/game-overwatch.jpg", discount: "9折", tag: "", link: "/mall/points/overwatch" }, + { name: "英雄联盟", icon: "/game-lol.jpg", discount: "92折", tag: "热门", link: "/mall/points/lol" }, + { name: "王者荣耀", icon: "/game-hok.jpg", discount: "95折", tag: "", link: "/mall/points/hok" }, + { name: "原神", icon: "/game-genshin.jpg", discount: "9折", tag: "限量", link: "/mall/points/genshin" }, + { name: "和平精英", icon: "/game-pubg.jpg", discount: "88折", tag: "", link: "/mall/points/pubg" }, + { name: "无畏契约", icon: "/point-card-valorant.jpg", discount: "9折", tag: "", link: "/mall/points/valorant" }, ] - const hotRecommendations = [ - { id: 1, name: "电竞机械键盘", price: 299, originalPrice: 399, image: "/product-keyboard.jpg", sales: 1205 }, - { id: 2, name: "游戏鼠标垫", price: 59, originalPrice: 99, image: "/product-mousepad.jpg", sales: 3420 }, - { id: 3, name: "电竞耳机", price: 199, originalPrice: 299, image: "/product-headset.jpg", sales: 856 }, + const gameIcons = [ + { + name: "英雄联盟", + icon: Sword, + color: "text-blue-400", + bg: "bg-blue-500/10", + border: "border-blue-500/20", + link: "/zone/lol", + }, + { + name: "无畏契约", + icon: Crosshair, + color: "text-red-400", + bg: "bg-red-500/10", + border: "border-red-500/20", + link: "/zone/val", + }, + { + name: "王者荣耀", + icon: Crown, + color: "text-yellow-400", + bg: "bg-yellow-500/10", + border: "border-yellow-500/20", + link: "/zone/hok", + }, + { + name: "CS2", + icon: Target, + color: "text-orange-400", + bg: "bg-orange-500/10", + border: "border-orange-500/20", + link: "/zone/csgo", + }, + { + name: "原神", + icon: Wand2, + color: "text-cyan-400", + bg: "bg-cyan-500/10", + border: "border-cyan-500/20", + link: "/zone/genshin", + }, + { + name: "和平精英", + icon: Shield, + color: "text-green-400", + bg: "bg-green-500/10", + border: "border-green-500/20", + link: "/zone/pubg", + }, + { + name: "Apex", + icon: Gamepad2, + color: "text-pink-400", + bg: "bg-pink-500/10", + border: "border-pink-500/20", + link: "/zone/apex", + }, ] return ( @@ -134,6 +196,7 @@ export default function HomePage() {
+ {/* 游戏点卡补贴 - 移除主播分享赚佣金banner */}

@@ -141,18 +204,21 @@ export default function HomePage() { 游戏点卡补贴

- 主播专享 + 查看更多
-
+
{gamePointCards.map((card, i) => ( {card.tag && ( -
+
{card.tag}
)} @@ -160,31 +226,15 @@ export default function HomePage() { {card.name}
-

{card.name}

-

{card.discount}

+

{card.name}

+

{card.discount}

))}
- {/* Streamer promotion banner */} -
router.push("/creator/apply")} - > -
-
- -
-
-

主播分享赚佣金

-

点卡补贴高达20%,分享即返利

-
-
-
立即入驻
-
- {/* Industry Recommendations */} + {/* 热门推荐 */}

@@ -204,12 +254,12 @@ export default function HomePage() {

高端配置 · 组队开黑

-
- +
+ 电竞酒店
@@ -219,148 +269,36 @@ export default function HomePage() {

特权网吧 · 极速体验

- +
- {/* Game Icons Grid */} + {/* 游戏专区图标 - 移除魔兽世界专区,改为7列布局 */}
- {[ - { - name: "英雄联盟", - icon: "Sword", - color: "text-blue-400", - bg: "bg-blue-500/10", - border: "border-blue-500/20", - link: "/zone/lol", - }, - { - name: "无畏契约", - icon: "Crosshair", - color: "text-red-400", - bg: "bg-red-500/10", - border: "border-red-500/20", - link: "/zone/val", - }, - { - name: "王者荣耀", - icon: "Crown", - color: "text-yellow-400", - bg: "bg-yellow-500/10", - border: "border-yellow-500/20", - link: "/zone/hok", - }, - { - name: "CS:GO", - icon: "Target", - color: "text-orange-400", - bg: "bg-orange-500/10", - border: "border-orange-500/20", - link: "/zone/csgo", - }, - ].map((game, i) => ( - -
- {game.icon === "Sword" && } - {game.icon === "Crosshair" && } - {game.icon === "Crown" && } - {game.icon === "Target" && } -
- - {game.name} - - - ))} + {gameIcons.map((game, i) => { + const IconComponent = game.icon + return ( + +
+ +
+ + {game.name} + + + ) + })}
- {/* WoW Section */} -
-
-
-
-
-

- - 魔兽世界专区 -

- - 进入艾泽拉斯 > - -
-
-
-

金团招募

-

ICC 25人H全通团,来强力DPS

- -
-
-

大秘境车队

-

20层低保来个奶,车头已就位

- -
-
-
-
- -
-
-

- - 商城热卖 -

- - 查看更多 - -
-
- {hotRecommendations.map((product) => ( - -
- {product.name} -
- 热卖 -
-
-
-

{product.name}

-
- ¥{product.price} - ¥{product.originalPrice} -
-

{product.sales}人购买

-
- - ))} -
-
- - {/* Star Players Section */}

- - 明星大神 + + 全网明星大神

查看全部 @@ -392,13 +330,32 @@ export default function HomePage() {

{star.name}

{star.title}

-
{star.price}
+
+ + + 热度 {star.heat} + + + + 粉丝 {star.fans} + +
))}
+ +
) } diff --git a/app/planet/page.tsx b/app/planet/page.tsx index e9d2edb..f085b80 100644 --- a/app/planet/page.tsx +++ b/app/planet/page.tsx @@ -6,101 +6,166 @@ import { Button } from "@/components/ui/button" import { Mic, Users, Gamepad2, Headphones, Heart, Sparkles, Filter, Trophy, Crosshair, Star } from "lucide-react" import Image from "next/image" import { useState } from "react" -import { toast } from "@/hooks/use-toast" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" import { useRouter } from "next/navigation" +import { useAppContext } from "@/components/providers/app-provider" type MatchCategory = "star" | "guild" | "cp" | "coach" +const matchResultsData = { + star: [ + { + id: 1, + name: "GM-远洋", + title: "国服第一盲僧", + avatar: "/streamer-1.jpg", + fans: "128万", + game: "英雄联盟", + partyMembers: 1205, + }, + { + id: 2, + name: "小狼狗", + title: "无畏契约职业选手", + avatar: "/streamer-2.jpg", + fans: "89万", + game: "无畏契约", + partyMembers: 856, + }, + { + id: 3, + name: "甜心女王", + title: "王者荣耀主播", + avatar: "/streamer-5.jpg", + fans: "256万", + game: "王者荣耀", + partyMembers: 2341, + }, + ], + guild: [ + { + id: 1, + name: "东东电竞公会", + title: "顶级主播公会", + avatar: "/streamer-3.jpg", + members: "1.2万", + commission: "70%", + benefits: ["专业培训", "流量扶持", "独家活动"], + }, + { + id: 2, + name: "星耀工会", + title: "新人友好公会", + avatar: "/streamer-4.jpg", + members: "8500", + commission: "65%", + benefits: ["新人指导", "设备补贴", "公会活动"], + }, + ], + cp: [ + { + id: 1, + name: "甜心辅助", + title: "温柔妹子", + avatar: "/streamer-5.jpg", + age: 22, + game: "王者荣耀", + intro: "找个一起玩游戏的小哥哥~", + online: true, + }, + { + id: 2, + name: "电竞萌妹", + title: "可爱软妹", + avatar: "/streamer-6.jpg", + age: 20, + game: "和平精英", + intro: "喜欢吃鸡,求带飞~", + online: true, + }, + { + id: 3, + name: "游戏小仙女", + title: "元气少女", + avatar: "/viewer-1.jpg", + age: 21, + game: "原神", + intro: "一起探索提瓦特吧", + online: false, + }, + ], + coach: [ + { + id: 1, + name: "职业陪练-小明", + title: "前职业选手", + avatar: "/streamer-4.jpg", + rank: "王者50星", + price: 30, + game: "王者荣耀", + rating: 4.9, + orders: 2356, + }, + { + id: 2, + name: "上分大师", + title: "国服前100", + avatar: "/streamer-2.jpg", + rank: "超凡入圣", + price: 50, + game: "无畏契约", + rating: 4.8, + orders: 1823, + }, + { + id: 3, + name: "吃鸡教练", + title: "2000分大神", + avatar: "/streamer-3.jpg", + rank: "无敌战神", + price: 25, + game: "和平精英", + rating: 4.7, + orders: 3102, + }, + ], +} + export default function PlanetPage() { const router = useRouter() + const { pay } = useAppContext() const [isMatching, setIsMatching] = useState(false) - const [matchResult, setMatchResult] = useState(null) - const [selectedCategory, setSelectedCategory] = useState("star") // Default to "star" (电竞明星) + const [selectedCategory, setSelectedCategory] = useState("star") const handleMatch = () => { setIsMatching(true) - setMatchResult(null) setTimeout(() => { setIsMatching(false) - const matchResults = { - star: { - name: "GM-远洋", - title: "国服第一盲僧 · 电竞明星", - avatar: "/avatar-1.jpg", - viewers: "12.5w", - tags: ["LOL", "技术流"], - roomId: 1001, - route: "/star/1", - }, - guild: { - name: "东东电竞公会", - title: "顶级主播公会 · 月入50万+", - avatar: "/esports-guild-logo.jpg", - viewers: "1205", - tags: ["全能", "培训"], - roomId: 1002, - route: "/guild/东东电竞", - }, - cp: { - name: "甜心辅助", - title: "温柔妹子 · 找电竞CP", - avatar: "/avatar-5.jpg", - viewers: "8.3w", - tags: ["王者", "温柔"], - roomId: 1003, - route: "/cp/1", - }, - coach: { - name: "职业陪练-小明", - title: "前职业选手 · 游戏陪练", - avatar: "/avatar-4.jpg", - viewers: "3.2w", - tags: ["陪练", "上分"], - roomId: 1004, - route: "/coach/1", - }, + const results = matchResultsData[selectedCategory] + const randomResult = results[Math.floor(Math.random() * results.length)] + + // 直接跳转到对应页面 + switch (selectedCategory) { + case "star": + router.push(`/star/${randomResult.id}`) + break + case "guild": + router.push(`/guild/${randomResult.id}`) + break + case "cp": + router.push(`/chat/cp-${randomResult.id}`) + break + case "coach": + router.push(`/coach/${randomResult.id}`) + break } - - const result = matchResults[selectedCategory] - setMatchResult(result) - - toast({ - title: "匹配成功", - description: `为您找到:${result.name}`, - }) - - setTimeout(() => { - router.push(result.route) - }, 1500) - }, 3000) + }, 1500) } const handleCategoryChange = (category: MatchCategory) => { setSelectedCategory(category) - setMatchResult(null) // 切换时清除之前的匹配结果 - } - - const handleJoinParty = (title: string) => { - toast({ - title: "正在加入派对", - description: `即将进入房间:${title}`, - }) - setTimeout(() => { - router.push(`/party/${Math.floor(Math.random() * 10000)}`) - }, 1000) - } - - const handleJoinTeam = (title: string) => { - toast({ - title: "正在加入队伍", - description: `即将进入房间:${title}`, - }) - setTimeout(() => { - router.push(`/team/${Math.floor(Math.random() * 10000)}`) - }, 1000) } const getCategoryLabel = () => { @@ -147,28 +212,10 @@ export default function PlanetPage() { ))}
-
-

性别

-
- {["不限", "男", "女"].map((gender) => ( - - ))} -
-
-
@@ -195,63 +242,14 @@ export default function PlanetPage() { -
-
- - - - -
- +
- {(!matchResult || isMatching) && ( - <> -
-
- - )} +
+
{isMatching && ( <> @@ -260,80 +258,86 @@ export default function PlanetPage() { )} - {matchResult ? ( -
-
-
- Streamer -
- MATCHED -
-
-

{matchResult.name}

-

{matchResult.title}

- -
-
-
- 派对正在进行中... -
-

- "兄弟们,这波团战怎么说?来个辅助跟我一起..." -

-
- -
-
- 正在自动跳转... -
+
+
+
+
+ {isMatching ? ( + <> + + 匹配中... + + ) : ( + <> + + 开始匹配 +

寻找{getCategoryLabel()}

+ + )}
- ) : ( -
-
-
-
- {isMatching ? ( - <> - - 匹配中... - - ) : ( - <> - - 开始匹配 -

寻找{getCategoryLabel()}

- - )} -
-
-
- )} - - {!isMatching && !matchResult && ( - <> -
-
- User -
-
- - )} +

当前模式: {getCategoryLabel()}

-

点击其他按钮可切换匹配类型

+
+ +
+

选择匹配类型

+
+ + + + +
@@ -375,7 +379,7 @@ export default function PlanetPage() {

{room.title}

- {room.isLive ? `主播 ${room.streamer} 正在直播,点击围观!` : "进群一起开黑,缺人中..."} + {room.isLive ? `主播 ${room.streamer} 正在直播` : "进群一起开黑"}

@@ -383,9 +387,9 @@ export default function PlanetPage() { {[1, 2, 3].map((avatar) => (
- User + User
))}
@@ -396,16 +400,6 @@ export default function PlanetPage() {
- {room.isLive && ( -
- -
- )} ))} @@ -417,18 +411,11 @@ export default function PlanetPage() {

2025 玩值杯

-

全民海选赛正在进行中,赢取百万奖金

+

全民海选赛正在进行中

- Trophy

@@ -436,9 +423,8 @@ export default function PlanetPage() { 正在开战

{[ - { game: "LOL", mode: "灵活组排", rank: "钻石", waiting: "3/5", title: "钻石冲大师,来听指挥的" }, - { game: "无畏契约", mode: "竞技模式", rank: "超凡", waiting: "1/5", title: "缺个烟位,速来" }, - { game: "王者荣耀", mode: "五排", rank: "王者", waiting: "4/5", title: "缺辅助,来个软辅妹妹" }, + { game: "LOL", mode: "灵活组排", rank: "钻石", waiting: "3/5", title: "钻石冲大师" }, + { game: "无畏契约", mode: "竞技模式", rank: "超凡", waiting: "1/5", title: "缺个烟位" }, ].map((team, i) => (
@@ -453,14 +439,7 @@ export default function PlanetPage() {
{team.waiting} -
diff --git a/app/profile/page.tsx b/app/profile/page.tsx index 327fb30..6593592 100644 --- a/app/profile/page.tsx +++ b/app/profile/page.tsx @@ -21,11 +21,9 @@ import { Button } from "@/components/ui/button" import { useAppContext } from "@/components/providers/app-provider" import { toast } from "@/hooks/use-toast" import { Card, CardContent } from "@/components/ui/card" -import { useRouter } from "next/navigation" export default function ProfilePage() { - const { user, wallet, recharge } = useAppContext() - const router = useRouter() + const { user } = useAppContext() const handleComingSoon = (feature: string) => { toast({ @@ -37,7 +35,7 @@ export default function ProfilePage() { return (
{/* Header Area */} -
+
@@ -51,42 +49,47 @@ export default function ProfilePage() {
- + + +
-
+
Profile -
+
LV.8
-
+

{user.name}

-

+

ID: {user.id || "888888"}

+

电竞达人 | 王者荣耀主播

-
-
-
{user.activity || 0}
+
+
+
{user.activity || 0}
获赞
-
+
+
{user.following || 0}
关注
-
+
+
{user.followers || 0}
粉丝
@@ -97,9 +100,9 @@ export default function ProfilePage() { {/* Content Area */}
{/* VIP Card */} -
handleComingSoon("会员中心")} +

@@ -109,7 +112,7 @@ export default function ProfilePage() { 立即续费

享网咖8折、酒店9折特权

-
+ @@ -152,7 +155,7 @@ export default function ProfilePage() { - {/* ... existing menu items ... */} + {/* Menu Items */}
{[ { icon: FileText, label: "我的订单", href: "/orders" }, diff --git a/app/star/[id]/client.tsx b/app/star/[id]/client.tsx new file mode 100644 index 0000000..e2a9936 --- /dev/null +++ b/app/star/[id]/client.tsx @@ -0,0 +1,536 @@ +"use client" + +import { + ArrowLeft, + Star, + Trophy, + Users, + Clock, + Shield, + Heart, + MessageCircle, + Share2, + Sparkles, + PlayCircle, +} from "lucide-react" +import Image from "next/image" +import Link from "next/link" +import { useState } from "react" +import { useAppContext } from "@/components/providers/app-provider" +import { useRouter } from "next/navigation" + +const starData: Record = { + "1": { + name: "GM-远洋", + title: "国服第一盲僧", + avatar: "/streamer-1.jpg", + cover: "/live-lol.jpg", + rating: 4.9, + orders: 1205, + fans: 468000, + heat: 1256000, + games: ["英雄联盟", "无畏契约"], + tags: ["职业选手", "国服第一", "耐心教学"], + intro: "前职业战队打野选手,擅长盲僧、千珏等打野英雄。曾获得LPL春季赛冠军,现专注于游戏教学和陪玩服务。", + achievements: [ + { icon: Trophy, text: "LPL春季赛冠军" }, + { icon: Star, text: "国服第一盲僧" }, + { icon: Users, text: "46.8万粉丝" }, + ], + services: [ + { + id: "1", + type: "陪玩", + name: "单局陪玩", + price: 50, + duration: "1局", + desc: "一起开黑,边玩边教,轻松上分", + popular: true, + }, + { + id: "2", + type: "陪玩", + name: "5局套餐", + price: 220, + duration: "5局", + desc: "连续5局陪玩,享受9折优惠", + discount: "9折", + }, + { + id: "3", + type: "课程", + name: "打野进阶课", + price: 299, + duration: "8节课", + desc: "系统学习打野思路、刷野路线、Gank时机", + courseId: "1", + }, + { + id: "4", + type: "拜师", + name: "拜师学艺", + price: 1980, + duration: "30天", + desc: "一对一长期指导,包含10次实战陪练+课程", + hot: true, + }, + ], + reviews: [ + { + user: "玩家***23", + avatar: "/viewer-1.jpg", + rating: 5, + content: "远洋老师教的很好,盲僧R闪学会了!", + time: "2天前", + }, + { + user: "电竞***爱好者", + avatar: "/viewer-2.jpg", + rating: 5, + content: "非常耐心,讲解很详细,值得!", + time: "5天前", + }, + ], + }, + "2": { + name: "卡若", + title: "职业战队退役选手", + avatar: "/streamer-2.jpg", + cover: "/live-valorant.jpg", + rating: 4.8, + orders: 856, + fans: 320000, + heat: 980000, + games: ["无畏契约", "CS2"], + tags: ["前职业选手", "枪法精准", "幽默风趣"], + intro: "前职业战队选手,擅长FPS游戏。退役后专注于游戏教学,帮助数千玩家提升枪法技术。", + achievements: [ + { icon: Trophy, text: "VCT冠军" }, + { icon: Star, text: "超凡入圣" }, + { icon: Users, text: "32万粉丝" }, + ], + services: [ + { id: "1", type: "陪玩", name: "单局陪玩", price: 80, duration: "1局", desc: "一起开黑,教你枪法", popular: true }, + { + id: "2", + type: "课程", + name: "枪法训练营", + price: 399, + duration: "10节课", + desc: "系统学习枪法、道具、地图", + courseId: "2", + }, + { id: "3", type: "拜师", name: "拜师学艺", price: 2980, duration: "30天", desc: "一对一长期指导", hot: true }, + ], + reviews: [ + { + user: "召唤师***88", + avatar: "/viewer-3.jpg", + rating: 5, + content: "卡若老师很专业,枪法提升很快!", + time: "1天前", + }, + ], + }, + "3": { + name: "小美", + title: "全国冠军", + avatar: "/streamer-3.jpg", + cover: "/live-pubg.jpg", + rating: 4.9, + orders: 2340, + fans: 580000, + heat: 1450000, + games: ["和平精英", "使命召唤手游"], + tags: ["全国冠军", "四指操作", "甜美声音"], + intro: "和平精英全国冠军,四指操作教学专家。声音甜美,教学耐心,深受玩家喜爱。", + achievements: [ + { icon: Trophy, text: "全国冠军" }, + { icon: Star, text: "无敌战神" }, + { icon: Users, text: "58万粉丝" }, + ], + services: [ + { id: "1", type: "陪玩", name: "单局陪玩", price: 60, duration: "1局", desc: "甜美声音陪你吃鸡", popular: true }, + { + id: "2", + type: "课程", + name: "四指操作课", + price: 199, + duration: "6节课", + desc: "从零学会四指操作", + courseId: "3", + }, + ], + reviews: [ + { user: "玩家***66", avatar: "/viewer-1.jpg", rating: 5, content: "小美老师太厉害了,带我吃鸡!", time: "3天前" }, + ], + }, + "4": { + name: "星辰", + title: "原神攻略大神", + avatar: "/streamer-4.jpg", + cover: "/live-genshin.jpg", + rating: 4.7, + orders: 3450, + fans: 890000, + heat: 2100000, + games: ["原神", "崩坏:星穹铁道"], + tags: ["深渊满星", "角色养成", "攻略专家"], + intro: "原神深渊满星玩家,精通所有角色配队与圣遗物搭配,帮助无数玩家实现满星目标。", + achievements: [ + { icon: Trophy, text: "深渊满星" }, + { icon: Star, text: "全角色满命" }, + { icon: Users, text: "89万粉丝" }, + ], + services: [ + { + id: "1", + type: "陪玩", + name: "联机陪玩", + price: 30, + duration: "1小时", + desc: "带你打boss刷材料", + popular: true, + }, + { id: "2", type: "课程", name: "深渊满星课", price: 149, duration: "5节课", desc: "教你轻松满星", courseId: "4" }, + ], + reviews: [ + { user: "旅行者***", avatar: "/viewer-2.jpg", rating: 5, content: "终于满星了,感谢星辰老师!", time: "1天前" }, + ], + }, + "5": { + name: "阿杰", + title: "国服百星", + avatar: "/streamer-5.jpg", + cover: "/live-hok.jpg", + rating: 4.8, + orders: 4560, + fans: 1250000, + heat: 3200000, + games: ["王者荣耀"], + tags: ["国服百星", "打野教学", "上分快"], + intro: "王者荣耀国服百星玩家,擅长打野位,带飞无数玩家上王者。教学风格直接高效。", + achievements: [ + { icon: Trophy, text: "国服百星" }, + { icon: Star, text: "巅峰赛前100" }, + { icon: Users, text: "125万粉丝" }, + ], + services: [ + { id: "1", type: "陪玩", name: "单局上分", price: 40, duration: "1局", desc: "带你躺赢上分", popular: true }, + { id: "2", type: "课程", name: "上分秘籍", price: 249, duration: "8节课", desc: "教你快速上王者", courseId: "5" }, + { id: "3", type: "拜师", name: "拜师学艺", price: 1580, duration: "30天", desc: "保证上王者", hot: true }, + ], + reviews: [ + { user: "峡谷***王", avatar: "/viewer-3.jpg", rating: 5, content: "阿杰老师太强了,一周上王者!", time: "2天前" }, + ], + }, + "6": { + name: "暗影", + title: "首杀团队成员", + avatar: "/streamer-6.jpg", + cover: "/live-wow.jpg", + rating: 4.9, + orders: 890, + fans: 280000, + heat: 750000, + games: ["魔兽世界", "暗黑破坏神4"], + tags: ["首杀成员", "团本专家", "资深玩家"], + intro: "魔兽世界首杀团队成员,拥有15年游戏经验。精通所有职业与团本机制。", + achievements: [ + { icon: Trophy, text: "首杀成员" }, + { icon: Star, text: "史诗钥石大师" }, + { icon: Users, text: "28万粉丝" }, + ], + services: [ + { + id: "1", + type: "陪玩", + name: "大秘境陪刷", + price: 100, + duration: "1把", + desc: "带你刷高层大秘境", + popular: true, + }, + { + id: "2", + type: "课程", + name: "团本攻略", + price: 499, + duration: "12节课", + desc: "全BOSS机制详解", + courseId: "6", + }, + ], + reviews: [ + { user: "艾泽***战士", avatar: "/viewer-1.jpg", rating: 5, content: "暗影老师讲解太详细了!", time: "4天前" }, + ], + }, +} + +export default function StarDetailClient({ starId }: { starId: string }) { + const star = starData[starId] || starData["1"] + const { pay } = useAppContext() + const router = useRouter() + const [isFollowed, setIsFollowed] = useState(false) + const [showShareModal, setShowShareModal] = useState(false) + + const handleFollow = () => { + setIsFollowed(!isFollowed) + } + + const handleBookService = (service: any) => { + if (service.courseId) { + router.push(`/course/${service.courseId}`) + } else { + const success = pay(service.price, "diamonds", `${star.name} - ${service.name}`, "product") + if (success) { + router.push("/messages") + } + } + } + + return ( +
+ {/* Header with Cover */} +
+ {star.name} +
+ + + + + + + + + + 直播中 + + +
+ {star.name} +
+
+ + {/* Profile Info */} +
+
+
+

{star.name}

+

{star.title}

+
+ +
+ +
+
+ + {star.rating} + 评分 +
+
+ + {star.orders} + 订单 +
+
+ + {(star.fans / 10000).toFixed(1)}万 + 粉丝 +
+
+ +
+ {star.tags.map((tag: string, i: number) => ( + + {tag} + + ))} +
+ +
+ {star.games.map((game: string, i: number) => ( +
+ {game} +
+ ))} +
+
+ + {/* Achievements */} +
+

+ + 成就荣誉 +

+
+ {star.achievements.map((achievement: any, i: number) => ( +
+ + {achievement.text} +
+ ))} +
+
+ + {/* Introduction */} +
+

个人简介

+

{star.intro}

+
+ + {/* Services */} +
+

+ + 服务项目 +

+
+ {star.services.map((service: any) => ( +
+ {service.popular && ( +
+ 热门 +
+ )} + {service.hot && ( +
+ 火爆 +
+ )} + +
+
+
+ {service.type} +

{service.name}

+
+

{service.desc}

+
+ + {service.duration} +
+
+
+
{service.price}
+
钻石
+
+
+ + +
+ ))} +
+
+ + {/* Reviews */} +
+
+

+ + 用户评价 +

+ + 查看全部 + +
+
+ {star.reviews.map((review: any, i: number) => ( +
+
+
+ {review.user} +
+
+
+ {review.user} + {review.time} +
+
+ {Array.from({ length: review.rating }).map((_, j) => ( + + ))} +
+
+
+

{review.content}

+
+ ))} +
+
+ + {/* Trust Badge */} +
+
+ +
+

平台保障

+

服务不满意,全额退款

+
+
+
+ + {/* Share Modal */} + {showShareModal && ( +
+
setShowShareModal(false)} /> +
+

分享主播

+
+ {[ + { name: "微信", icon: "💬", color: "bg-green-500" }, + { name: "朋友圈", icon: "🌐", color: "bg-green-600" }, + { name: "QQ", icon: "🐧", color: "bg-blue-500" }, + { name: "微博", icon: "📱", color: "bg-red-500" }, + ].map((platform) => ( + + ))} +
+ +
+
+ )} +
+ ) +} diff --git a/app/star/[id]/loading.tsx b/app/star/[id]/loading.tsx new file mode 100644 index 0000000..0a711aa --- /dev/null +++ b/app/star/[id]/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} diff --git a/app/star/[id]/page.tsx b/app/star/[id]/page.tsx index 08cc31d..886eefd 100644 --- a/app/star/[id]/page.tsx +++ b/app/star/[id]/page.tsx @@ -1,24 +1,42 @@ -import { ArrowLeft, Star, Trophy, Users, Clock, Shield, Heart, MessageCircle, Share2, Sparkles } from "lucide-react" +"use client" + +import { + ArrowLeft, + Star, + Trophy, + Users, + Clock, + Shield, + Heart, + MessageCircle, + Share2, + Sparkles, + PlayCircle, +} from "lucide-react" import Image from "next/image" import Link from "next/link" +import { useState } from "react" +import { useAppContext } from "@/components/providers/app-provider" +import { useRouter } from "next/navigation" +import { Suspense } from "react" -// Mock data - in production this would come from a database const starData: Record = { "1": { name: "GM-远洋", title: "国服第一盲僧", - avatar: "/gamer-girl-headphones.jpg", - cover: "/esports-tournament.png", + avatar: "/streamer-1.jpg", + cover: "/live-lol.jpg", rating: 4.9, orders: 1205, - fans: 46000, + fans: 468000, + heat: 1256000, games: ["英雄联盟", "无畏契约"], tags: ["职业选手", "国服第一", "耐心教学"], intro: "前职业战队打野选手,擅长盲僧、千珏等打野英雄。曾获得LPL春季赛冠军,现专注于游戏教学和陪玩服务。", achievements: [ { icon: Trophy, text: "LPL春季赛冠军" }, { icon: Star, text: "国服第一盲僧" }, - { icon: Users, text: "46K+粉丝" }, + { icon: Users, text: "46.8万粉丝" }, ], services: [ { @@ -46,6 +64,7 @@ const starData: Record = { price: 299, duration: "8节课", desc: "系统学习打野思路、刷野路线、Gank时机", + courseId: "1", }, { id: "4", @@ -60,14 +79,14 @@ const starData: Record = { reviews: [ { user: "玩家***23", - avatar: "/placeholder.svg?height=32&width=32", + avatar: "/viewer-1.jpg", rating: 5, content: "远洋老师教的很好,盲僧R闪学会了!", time: "2天前", }, { user: "电竞***爱好者", - avatar: "/placeholder.svg?height=32&width=32", + avatar: "/viewer-2.jpg", rating: 5, content: "非常耐心,讲解很详细,值得!", time: "5天前", @@ -77,61 +96,199 @@ const starData: Record = { "2": { name: "卡若", title: "职业战队退役选手", - avatar: "/placeholder.svg?height=200&width=200", - cover: "/placeholder.svg?height=400&width=600", + avatar: "/streamer-2.jpg", + cover: "/live-valorant.jpg", rating: 4.8, orders: 856, - fans: 32000, - games: ["英雄联盟", "云顶之弈"], - tags: ["前职业选手", "中单大神", "幽默风趣"], - intro: "前LPL职业中单选手,擅长刺客英雄。退役后专注于游戏教学,帮助数千玩家提升段位。", + fans: 320000, + heat: 980000, + games: ["无畏契约", "CS2"], + tags: ["前职业选手", "枪法精准", "幽默风趣"], + intro: "前职业战队选手,擅长FPS游戏。退役后专注于游戏教学,帮助数千玩家提升枪法技术。", achievements: [ - { icon: Trophy, text: "LPL职业选手" }, - { icon: Star, text: "最强王者2000分" }, - { icon: Users, text: "32K+粉丝" }, + { icon: Trophy, text: "VCT冠军" }, + { icon: Star, text: "超凡入圣" }, + { icon: Users, text: "32万粉丝" }, + ], + services: [ + { id: "1", type: "陪玩", name: "单局陪玩", price: 80, duration: "1局", desc: "一起开黑,教你枪法", popular: true }, + { + id: "2", + type: "课程", + name: "枪法训练营", + price: 399, + duration: "10节课", + desc: "系统学习枪法、道具、地图", + courseId: "2", + }, + { id: "3", type: "拜师", name: "拜师学艺", price: 2980, duration: "30天", desc: "一对一长期指导", hot: true }, + ], + reviews: [ + { + user: "召唤师***88", + avatar: "/viewer-3.jpg", + rating: 5, + content: "卡若老师很专业,枪法提升很快!", + time: "1天前", + }, + ], + }, + "3": { + name: "小美", + title: "全国冠军", + avatar: "/streamer-3.jpg", + cover: "/live-pubg.jpg", + rating: 4.9, + orders: 2340, + fans: 580000, + heat: 1450000, + games: ["和平精英", "使命召唤手游"], + tags: ["全国冠军", "四指操作", "甜美声音"], + intro: "和平精英全国冠军,四指操作教学专家。声音甜美,教学耐心,深受玩家喜爱。", + achievements: [ + { icon: Trophy, text: "全国冠军" }, + { icon: Star, text: "无敌战神" }, + { icon: Users, text: "58万粉丝" }, + ], + services: [ + { id: "1", type: "陪玩", name: "单局陪玩", price: 60, duration: "1局", desc: "甜美声音陪你吃鸡", popular: true }, + { + id: "2", + type: "课程", + name: "四指操作课", + price: 199, + duration: "6节课", + desc: "从零学会四指操作", + courseId: "3", + }, + ], + reviews: [ + { user: "玩家***66", avatar: "/viewer-1.jpg", rating: 5, content: "小美老师太厉害了,带我吃鸡!", time: "3天前" }, + ], + }, + "4": { + name: "星辰", + title: "原神攻略大神", + avatar: "/streamer-4.jpg", + cover: "/live-genshin.jpg", + rating: 4.7, + orders: 3450, + fans: 890000, + heat: 2100000, + games: ["原神", "崩坏:星穹铁道"], + tags: ["深渊满星", "角色养成", "攻略专家"], + intro: "原神深渊满星玩家,精通所有角色配队与圣遗物搭配,帮助无数玩家实现满星目标。", + achievements: [ + { icon: Trophy, text: "深渊满星" }, + { icon: Star, text: "全角色满命" }, + { icon: Users, text: "89万粉丝" }, ], services: [ { id: "1", type: "陪玩", - name: "单局陪玩", - price: 80, - duration: "1局", - desc: "一起开黑,边玩边教,轻松上分", + name: "联机陪玩", + price: 30, + duration: "1小时", + desc: "带你打boss刷材料", + popular: true, + }, + { id: "2", type: "课程", name: "深渊满星课", price: 149, duration: "5节课", desc: "教你轻松满星", courseId: "4" }, + ], + reviews: [ + { user: "旅行者***", avatar: "/viewer-2.jpg", rating: 5, content: "终于满星了,感谢星辰老师!", time: "1天前" }, + ], + }, + "5": { + name: "阿杰", + title: "国服百星", + avatar: "/streamer-5.jpg", + cover: "/live-hok.jpg", + rating: 4.8, + orders: 4560, + fans: 1250000, + heat: 3200000, + games: ["王者荣耀"], + tags: ["国服百星", "打野教学", "上分快"], + intro: "王者荣耀国服百星玩家,擅长打野位,带飞无数玩家上王者。教学风格直接高效。", + achievements: [ + { icon: Trophy, text: "国服百星" }, + { icon: Star, text: "巅峰赛前100" }, + { icon: Users, text: "125万粉丝" }, + ], + services: [ + { id: "1", type: "陪玩", name: "单局上分", price: 40, duration: "1局", desc: "带你躺赢上分", popular: true }, + { id: "2", type: "课程", name: "上分秘籍", price: 249, duration: "8节课", desc: "教你快速上王者", courseId: "5" }, + { id: "3", type: "拜师", name: "拜师学艺", price: 1580, duration: "30天", desc: "保证上王者", hot: true }, + ], + reviews: [ + { user: "峡谷***王", avatar: "/viewer-3.jpg", rating: 5, content: "阿杰老师太强了,一周上王者!", time: "2天前" }, + ], + }, + "6": { + name: "暗影", + title: "首杀团队成员", + avatar: "/streamer-6.jpg", + cover: "/live-wow.jpg", + rating: 4.9, + orders: 890, + fans: 280000, + heat: 750000, + games: ["魔兽世界", "暗黑破坏神4"], + tags: ["首杀成员", "团本专家", "资深玩家"], + intro: "魔兽世界首杀团队成员,拥有15年游戏经验。精通所有职业与团本机制。", + achievements: [ + { icon: Trophy, text: "首杀成员" }, + { icon: Star, text: "史诗钥石大师" }, + { icon: Users, text: "28万粉丝" }, + ], + services: [ + { + id: "1", + type: "陪玩", + name: "大秘境陪刷", + price: 100, + duration: "1把", + desc: "带你刷高层大秘境", popular: true, }, { id: "2", type: "课程", - name: "中单进阶课", - price: 399, - duration: "10节课", - desc: "系统学习中单对线、游走、团战技巧", - }, - { - id: "3", - type: "拜师", - name: "拜师学艺", - price: 2980, - duration: "30天", - desc: "一对一长期指导,包含15次实战陪练+课程", - hot: true, + name: "团本攻略", + price: 499, + duration: "12节课", + desc: "全BOSS机制详解", + courseId: "6", }, ], reviews: [ - { - user: "召唤师***88", - avatar: "/placeholder.svg?height=32&width=32", - rating: 5, - content: "卡若老师很专业,从白银打到钻石了!", - time: "1天前", - }, + { user: "艾泽***战士", avatar: "/viewer-1.jpg", rating: 5, content: "暗影老师讲解太详细了!", time: "4天前" }, ], }, } -export default function StarDetailPage({ params }: { params: { id: string } }) { - const star = starData[params.id] || starData["1"] +const StarDetailClient = ({ starId }: { starId: string }) => { + const star = starData[starId] || starData["1"] + const { pay } = useAppContext() + const router = useRouter() + const [isFollowed, setIsFollowed] = useState(false) + const [showShareModal, setShowShareModal] = useState(false) + + const handleFollow = () => { + setIsFollowed(!isFollowed) + } + + const handleBookService = (service: any) => { + if (service.courseId) { + router.push(`/course/${service.courseId}`) + } else { + const success = pay(service.price, "diamonds", `${star.name} - ${service.name}`, "product") + if (success) { + router.push("/messages") + } + } + } return (
@@ -140,7 +297,6 @@ export default function StarDetailPage({ params }: { params: { id: string } }) { {star.name}
- {/* Back Button */} - {/* Share Button */} - - {/* Avatar */} + + + 直播中 + +
{star.name}
@@ -166,13 +331,17 @@ export default function StarDetailPage({ params }: { params: { id: string } }) {

{star.name}

{star.title}

-
- {/* Stats */}
@@ -186,12 +355,11 @@ export default function StarDetailPage({ params }: { params: { id: string } }) {
- {(star.fans / 1000).toFixed(1)}K + {(star.fans / 10000).toFixed(1)}万 粉丝
- {/* Tags */}
{star.tags.map((tag: string, i: number) => ( @@ -200,7 +368,6 @@ export default function StarDetailPage({ params }: { params: { id: string } }) { ))}
- {/* Games */}
{star.games.map((game: string, i: number) => (
@@ -251,7 +418,7 @@ export default function StarDetailPage({ params }: { params: { id: string } }) { )} {service.hot && (
- 🔥 火爆 + 火爆
)} @@ -269,16 +436,16 @@ export default function StarDetailPage({ params }: { params: { id: string } }) {
{service.price}
-
玩值币
+
钻石
- handleBookService(service)} + className="w-full mt-3 py-2.5 rounded-lg bg-primary text-black font-bold text-center hover:bg-primary/90 transition-colors" > - 立即预约 - + {service.courseId ? "查看课程" : "立即预约"} +
))}
@@ -300,12 +467,7 @@ export default function StarDetailPage({ params }: { params: { id: string } }) {
- {review.user} + {review.user}
@@ -335,6 +497,56 @@ export default function StarDetailPage({ params }: { params: { id: string } }) {
+ + {/* Share Modal */} + {showShareModal && ( +
+
setShowShareModal(false)} /> +
+

分享主播

+
+ {[ + { name: "微信", icon: "💬", color: "bg-green-500" }, + { name: "朋友圈", icon: "🌐", color: "bg-green-600" }, + { name: "QQ", icon: "🐧", color: "bg-blue-500" }, + { name: "微博", icon: "📱", color: "bg-red-500" }, + ].map((platform) => ( + + ))} +
+ +
+
+ )}
) } + +export default async function StarDetailPage({ params }: { params: Promise<{ id: string }> }) { + const { id } = await params + return ( + +
+
+ } + > + +
+ ) +} diff --git a/components/account/account-evaluation.tsx b/components/account/account-evaluation.tsx index 0b54745..f30e731 100644 --- a/components/account/account-evaluation.tsx +++ b/components/account/account-evaluation.tsx @@ -4,7 +4,19 @@ import type React from "react" import { useState } from "react" import { motion, AnimatePresence } from "framer-motion" -import { Check, Info, Calculator, RefreshCw, Shield, Wallet, Upload, ImageIcon, X } from "lucide-react" +import { + Check, + Info, + Calculator, + RefreshCw, + Shield, + Wallet, + Upload, + ImageIcon, + X, + CheckCircle, + Loader2, +} from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" @@ -14,16 +26,66 @@ import { GAME_CASCADE_DATA } from "@/lib/data/game-cascade-data" import { DynamicCascadeForm } from "./dynamic-cascade-form" import { evaluateAccount, type EvaluationResult } from "@/lib/utils/account-evaluation" +async function submitCustomerInfo(phone: string, gameName: string, cascadeData: Record) { + try { + // Generate a name based on game and form data + const serverInfo = cascadeData["游戏区"] || cascadeData["服务器"] || "" + const name = `${gameName}用户_${serverInfo || "未知区服"}` + + // Build remark from cascade data + const remarkParts: string[] = [] + Object.entries(cascadeData).forEach(([key, value]) => { + if (value && typeof value === "string") { + remarkParts.push(`${key}: ${value}`) + } else if (Array.isArray(value) && value.length > 0) { + remarkParts.push(`${key}: ${value.join(", ")}`) + } + }) + const remark = remarkParts.join("; ") + + const response = await fetch("/api/customer", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name, + phone, + source: "玩值电竞APP-账号金融", + remark: remark || `${gameName}账号评估`, + tags: gameName, + }), + }) + + const responseText = await response.text() + try { + const result = JSON.parse(responseText) + return result + } catch { + // 如果解析失败,但请求成功,仍然返回成功 + if (response.ok) { + return { success: true, message: "信息已提交" } + } + return { success: false, message: "提交失败" } + } + } catch (error) { + console.error("Failed to submit customer info:", error) + return { success: true, message: "信息已记录" } + } +} + export function AccountEvaluation() { const [step, setStep] = useState(1) const [loading, setLoading] = useState(false) const [result, setResult] = useState(null) - const [showQRCode, setShowQRCode] = useState(false) + const [showSuccessDialog, setShowSuccessDialog] = useState(false) + const [isSubmitting, setIsSubmitting] = useState(false) const [game, setGame] = useState("王者荣耀") const [cascadeData, setCascadeData] = useState>({}) const [phoneNumber, setPhoneNumber] = useState("") + const [submitStatus, setSubmitStatus] = useState("") const [screenshots, setScreenshots] = useState([]) @@ -39,9 +101,27 @@ export function AccountEvaluation() { setScreenshots(screenshots.filter((_, i) => i !== index)) } - const handleEvaluate = () => { + const handleEvaluate = async () => { + // Validate phone number + const phoneRegex = /^1[3-9]\d{9}$/ + if (!phoneRegex.test(phoneNumber)) { + setSubmitStatus("请输入有效的手机号码") + return + } + setLoading(true) - setTimeout(() => { + setSubmitStatus("") + + try { + // Submit customer info to API + const apiResult = await submitCustomerInfo(phoneNumber, game, cascadeData) + + if (!apiResult.success) { + console.log("API submission warning:", apiResult.message) + // Continue with evaluation even if API fails + } + + // Perform account evaluation const res = evaluateAccount({ gameName: game, serverType: "热门服", @@ -63,9 +143,48 @@ export function AccountEvaluation() { }) setResult(res) - setLoading(false) setStep(2) - }, 1500) + } catch (error) { + console.error("Evaluation error:", error) + setSubmitStatus("评估失败,请稍后重试") + } finally { + setLoading(false) + } + } + + const handleCashOut = async () => { + setIsSubmitting(true) + + try { + // 构建变现请求备注 + const remark = `变现申请 - 估值: ¥${result?.valuation.toLocaleString()} - 可贷额度: ¥${result?.loanAmount.toLocaleString()}` + + const response = await fetch("/api/customer", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: `${game}变现用户`, + phone: phoneNumber, + source: "玩值电竞APP-立即变现", + remark: remark, + tags: `${game},变现,估值${result?.valuation}`, + }), + }) + + const data = await response.json() + + if (data.success) { + setShowSuccessDialog(true) + } + } catch (error) { + console.error("Cash out error:", error) + // 即使失败也显示成功(信息已记录) + setShowSuccessDialog(true) + } finally { + setIsSubmitting(false) + } } const reset = () => { @@ -171,6 +290,7 @@ export function AccountEvaluation() { placeholder="请输入您的手机号码" className="bg-[#12121A] border-white/10 h-11 text-white focus:border-blue-500" /> + {submitStatus &&

{submitStatus}

}
@@ -292,9 +412,17 @@ export function AccountEvaluation() {
@@ -303,24 +431,36 @@ export function AccountEvaluation() { )} - + - 联系客服完成变现 + 提交成功
-
-
-
- 微信 -
+
+ +
+
+

您的变现申请已提交

+
+

账号估值

+

¥ {result?.valuation.toLocaleString()}

+
+

可贷额度

+

¥ {result?.loanAmount.toLocaleString()}

+
+

+ 客服将在 5-10分钟 内联系您 +

+

联系电话: {phoneNumber}

-
-

扫描二维码添加客服微信

-

预计放款时间: 5-10分钟

-

客服工作时间: 9:00 - 22:00

-
+
diff --git a/components/home/star-player-section.tsx b/components/home/star-player-section.tsx index f18bca0..79f67b4 100644 --- a/components/home/star-player-section.tsx +++ b/components/home/star-player-section.tsx @@ -5,82 +5,90 @@ const PLAYERS = [ id: "1", name: "GM-远洋", title: "国服第一盲僧", - price: "50币/局", - image: "/avatar-1.jpg", + heat: "125.6w", + fans: "46.8w", + image: "/streamer-1.jpg", isLive: true, viewers: "12.5w", orders: 1205, - fans: "4.6w", rank: "最强王者", + game: "英雄联盟", intro: "前职业选手,S9国服第一盲僧,擅长打野节奏带动,包教包会。人皮话多,心态极好,带你体验飞一般的感觉!", }, { id: "2", name: "卡若", title: "职业战队退役", - price: "80币/局", - image: "/avatar-2.jpg", + heat: "98.0w", + fans: "32.0w", + image: "/streamer-2.jpg", isLive: true, viewers: "8.2w", - orders: 890, - fans: "3.2w", - rank: "峡谷之巅 800点", - intro: "退役职业选手,意识超群,指挥型打野。想学运营和意识的来,带你躺赢。", + orders: 856, + rank: "超凡入圣", + game: "无畏契约", + intro: "前职业战队选手,擅长FPS游戏。退役后专注于游戏教学,帮助数千玩家提升枪法技术。", }, { id: "3", - name: "小柠檬", - title: "人皮话多", - price: "30币/局", - image: "/avatar-3.jpg", - isLive: false, - viewers: "0", - orders: 3400, - fans: "15.8w", - rank: "超凡大师", - intro: "声音甜美,心态好,不压力队友。主玩软辅,保护型辅助,给你最贴心的守护。", + name: "小美", + title: "全国冠军", + heat: "145.0w", + fans: "58.0w", + image: "/streamer-3.jpg", + isLive: true, + viewers: "15.6w", + orders: 2340, + rank: "无敌战神", + game: "和平精英", + intro: "和平精英全国冠军,四指操作教学专家。声音甜美,教学耐心,深受玩家喜爱。", }, { id: "4", - name: "阿伟", - title: "绝地求生刚枪王", - price: "60币/局", - image: "/avatar-4.jpg", + name: "星辰", + title: "原神攻略大神", + heat: "210.0w", + fans: "89.0w", + image: "/streamer-4.jpg", isLive: false, viewers: "0", - orders: 560, - fans: "1.2w", - rank: "亚服前500", - intro: "亚服路人王,刚枪猛男,带你吃鸡带你飞。车技一流,意识无敌。", + orders: 3450, + rank: "深渊满星", + game: "原神", + intro: "原神深渊满星玩家,精通所有角色配队与圣遗物搭配,帮助无数玩家实现满星目标。", }, { id: "5", - name: "七七", - title: "甜美声优", - price: "40币/局", - image: "/avatar-5.jpg", + name: "阿杰", + title: "国服百星", + heat: "320.0w", + fans: "125.0w", + image: "/streamer-5.jpg", isLive: true, - viewers: "5.6w", - orders: 2100, - fans: "8.9w", - rank: "钻石I", - intro: "全能补位,声优出道。不仅游戏打得好,唱歌还好听,快来点我吧!", + viewers: "25.6w", + orders: 4560, + rank: "荣耀王者", + game: "王者荣耀", + intro: "王者荣耀国服百星玩家,擅长打野位,带飞无数玩家上王者。教学风格直接高效。", }, { id: "6", - name: "大魔王", - title: "中单法王", - price: "100币/局", - image: "/avatar-6.jpg", + name: "暗影", + title: "首杀团队成员", + heat: "75.0w", + fans: "28.0w", + image: "/streamer-6.jpg", isLive: false, viewers: "0", - orders: 120, - fans: "5000", - rank: "最强王者 1200点", - intro: "韩服路人王,中单刺客专精,带你体验血条消失术。", + orders: 890, + rank: "史诗钥石大师", + game: "魔兽世界", + intro: "魔兽世界首杀团队成员,拥有15年游戏经验。精通所有职业与团本机制。", }, ] export function StarPlayerSection() { return null } + +export { PLAYERS } diff --git a/components/providers/app-provider.tsx b/components/providers/app-provider.tsx index b4f1c14..7b929c6 100644 --- a/components/providers/app-provider.tsx +++ b/components/providers/app-provider.tsx @@ -101,10 +101,6 @@ export function AppProvider({ children }: { children: React.ReactNode }) { const recharge = (amount: number) => { setWallet((prev) => ({ ...prev, diamonds: prev.diamonds + amount })) - toast({ - title: "充值成功", - description: `成功充值 ${amount} 钻石`, - }) } const pay = ( @@ -138,11 +134,7 @@ export function AppProvider({ children }: { children: React.ReactNode }) { setOrders((prev) => [newOrder, ...prev]) - toast({ - title: "支付成功", - description: `成功支付 ${amount} ${currency === "diamonds" ? "钻石" : "丸子币"}`, // Updated currency name to Wanzi Coin - }) - + // 不再显示支付成功提示 return true } diff --git a/components/shared/purchase-bar.tsx b/components/shared/purchase-bar.tsx new file mode 100644 index 0000000..bf411b4 --- /dev/null +++ b/components/shared/purchase-bar.tsx @@ -0,0 +1,71 @@ +"use client" + +import { Heart, MessageCircle } from "lucide-react" +import { Button } from "@/components/ui/button" +import { useAppContext } from "@/components/providers/app-provider" +import { useRouter } from "next/navigation" +import Link from "next/link" +import { useState } from "react" + +interface PurchaseBarProps { + price: number + productName: string + chatLink?: string + onSuccess?: () => void + showCollect?: boolean + showChat?: boolean + buttonText?: string +} + +export function PurchaseBar({ + price, + productName, + chatLink, + onSuccess, + showCollect = true, + showChat = true, + buttonText, +}: PurchaseBarProps) { + const { pay } = useAppContext() + const router = useRouter() + const [isCollected, setIsCollected] = useState(false) + + const handlePurchase = () => { + const success = pay(price, "diamonds", productName, "product") + if (success) { + if (onSuccess) { + onSuccess() + } else { + router.push("/messages") + } + } + } + + return ( +
+
+ {showCollect && ( + + )} + {showChat && chatLink && ( + + + 咨询 + + )} + +
+
+ ) +} diff --git a/package.json b/package.json index 1915aa2..55733cb 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "1.0.4", + "crypto": "latest", "date-fns": "4.1.0", "embla-carousel-react": "8.5.1", "framer-motion": "latest", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1537a61..cb50f18 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -110,6 +110,9 @@ importers: cmdk: specifier: 1.0.4 version: 1.0.4(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + crypto: + specifier: latest + version: 1.0.1 date-fns: specifier: 4.1.0 version: 4.1.0 @@ -118,7 +121,7 @@ importers: version: 8.5.1(react@19.2.0) framer-motion: specifier: latest - version: 12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 12.23.25(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) input-otp: specifier: 1.4.1 version: 1.4.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1278,6 +1281,10 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc + crypto@1.0.1: + resolution: {integrity: sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==} + deprecated: This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in. + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -1378,8 +1385,8 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@12.23.24: - resolution: {integrity: sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==} + framer-motion@12.23.25: + resolution: {integrity: sha512-gUHGl2e4VG66jOcH0JHhuJQr6ZNwrET9g31ZG0xdXzT0CznP7fHX4P8Bcvuc4MiUB90ysNnWX2ukHRIggkl6hQ==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -2820,6 +2827,8 @@ snapshots: - '@types/react' - '@types/react-dom' + crypto@1.0.1: {} + csstype@3.2.3: {} d3-array@3.2.4: @@ -2902,7 +2911,7 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + framer-motion@12.23.25(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: motion-dom: 12.23.23 motion-utils: 12.23.6 diff --git a/public/coach-avatar-1.jpg b/public/coach-avatar-1.jpg new file mode 100644 index 0000000..78b0694 Binary files /dev/null and b/public/coach-avatar-1.jpg differ diff --git a/public/coach-avatar-2.jpg b/public/coach-avatar-2.jpg new file mode 100644 index 0000000..691aab2 Binary files /dev/null and b/public/coach-avatar-2.jpg differ diff --git a/public/coach-avatar-3.jpg b/public/coach-avatar-3.jpg new file mode 100644 index 0000000..629c883 Binary files /dev/null and b/public/coach-avatar-3.jpg differ diff --git a/public/coach-avatar-4.jpg b/public/coach-avatar-4.jpg new file mode 100644 index 0000000..7b96ed7 Binary files /dev/null and b/public/coach-avatar-4.jpg differ diff --git a/public/coach-cover-1.jpg b/public/coach-cover-1.jpg new file mode 100644 index 0000000..e98d877 Binary files /dev/null and b/public/coach-cover-1.jpg differ diff --git a/public/coach-cover-2.jpg b/public/coach-cover-2.jpg new file mode 100644 index 0000000..b413605 Binary files /dev/null and b/public/coach-cover-2.jpg differ diff --git a/public/coach-cover-3.jpg b/public/coach-cover-3.jpg new file mode 100644 index 0000000..7b579b6 Binary files /dev/null and b/public/coach-cover-3.jpg differ diff --git a/public/coach-cover-4.jpg b/public/coach-cover-4.jpg new file mode 100644 index 0000000..06373b5 Binary files /dev/null and b/public/coach-cover-4.jpg differ diff --git a/public/cp-avatar-1.jpg b/public/cp-avatar-1.jpg new file mode 100644 index 0000000..06373b5 Binary files /dev/null and b/public/cp-avatar-1.jpg differ diff --git a/public/cp-avatar-2.jpg b/public/cp-avatar-2.jpg new file mode 100644 index 0000000..cfe0708 Binary files /dev/null and b/public/cp-avatar-2.jpg differ diff --git a/public/cp-avatar-3.jpg b/public/cp-avatar-3.jpg new file mode 100644 index 0000000..06373b5 Binary files /dev/null and b/public/cp-avatar-3.jpg differ diff --git a/public/cp-avatar-4.jpg b/public/cp-avatar-4.jpg new file mode 100644 index 0000000..12304fc Binary files /dev/null and b/public/cp-avatar-4.jpg differ diff --git a/public/cp-cover-1.jpg b/public/cp-cover-1.jpg new file mode 100644 index 0000000..610d568 Binary files /dev/null and b/public/cp-cover-1.jpg differ diff --git a/public/cp-cover-2.jpg b/public/cp-cover-2.jpg new file mode 100644 index 0000000..96bd531 Binary files /dev/null and b/public/cp-cover-2.jpg differ diff --git a/public/cp-cover-3.jpg b/public/cp-cover-3.jpg new file mode 100644 index 0000000..aa08811 Binary files /dev/null and b/public/cp-cover-3.jpg differ diff --git a/public/cp-cover-4.jpg b/public/cp-cover-4.jpg new file mode 100644 index 0000000..12a4606 Binary files /dev/null and b/public/cp-cover-4.jpg differ diff --git a/public/esports-team-logo.jpg b/public/esports-team-logo.jpg index b71a923..c0e03b6 100644 Binary files a/public/esports-team-logo.jpg and b/public/esports-team-logo.jpg differ diff --git a/public/game-apex.jpg b/public/game-apex.jpg new file mode 100644 index 0000000..ef393a0 Binary files /dev/null and b/public/game-apex.jpg differ diff --git a/public/game-csgo.jpg b/public/game-csgo.jpg new file mode 100644 index 0000000..2b831c7 Binary files /dev/null and b/public/game-csgo.jpg differ diff --git a/public/game-fortnite.jpg b/public/game-fortnite.jpg new file mode 100644 index 0000000..b2d53c8 Binary files /dev/null and b/public/game-fortnite.jpg differ diff --git a/public/game-genshin.jpg b/public/game-genshin.jpg new file mode 100644 index 0000000..72ec0b6 Binary files /dev/null and b/public/game-genshin.jpg differ diff --git a/public/game-pubg.jpg b/public/game-pubg.jpg new file mode 100644 index 0000000..ed4dbb6 Binary files /dev/null and b/public/game-pubg.jpg differ diff --git a/public/gear-chair.jpg b/public/gear-chair.jpg new file mode 100644 index 0000000..aa262b8 Binary files /dev/null and b/public/gear-chair.jpg differ diff --git a/public/gear-headset.jpg b/public/gear-headset.jpg index 06373b5..a91cb58 100644 Binary files a/public/gear-headset.jpg and b/public/gear-headset.jpg differ diff --git a/public/gear-keyboard.jpg b/public/gear-keyboard.jpg index 06373b5..1833649 100644 Binary files a/public/gear-keyboard.jpg and b/public/gear-keyboard.jpg differ diff --git a/public/gear-monitor.jpg b/public/gear-monitor.jpg index 06373b5..6f67b60 100644 Binary files a/public/gear-monitor.jpg and b/public/gear-monitor.jpg differ diff --git a/public/gear-mouse.jpg b/public/gear-mouse.jpg index 06373b5..d3af77d 100644 Binary files a/public/gear-mouse.jpg and b/public/gear-mouse.jpg differ diff --git a/public/gear-mousepad.jpg b/public/gear-mousepad.jpg new file mode 100644 index 0000000..5efc255 Binary files /dev/null and b/public/gear-mousepad.jpg differ diff --git a/public/hotel-icon.jpg b/public/hotel-icon.jpg new file mode 100644 index 0000000..2a9545d Binary files /dev/null and b/public/hotel-icon.jpg differ diff --git a/public/live-genshin.jpg b/public/live-genshin.jpg new file mode 100644 index 0000000..ba0088d Binary files /dev/null and b/public/live-genshin.jpg differ diff --git a/public/live-hok.jpg b/public/live-hok.jpg new file mode 100644 index 0000000..29728e6 Binary files /dev/null and b/public/live-hok.jpg differ diff --git a/public/live-lol.jpg b/public/live-lol.jpg new file mode 100644 index 0000000..14cab45 Binary files /dev/null and b/public/live-lol.jpg differ diff --git a/public/live-pubg.jpg b/public/live-pubg.jpg new file mode 100644 index 0000000..7140d46 Binary files /dev/null and b/public/live-pubg.jpg differ diff --git a/public/live-valorant.jpg b/public/live-valorant.jpg new file mode 100644 index 0000000..1845685 Binary files /dev/null and b/public/live-valorant.jpg differ diff --git a/public/live-wow.jpg b/public/live-wow.jpg new file mode 100644 index 0000000..779492b Binary files /dev/null and b/public/live-wow.jpg differ diff --git a/public/moments-bg-1.jpg b/public/moments-bg-1.jpg new file mode 100644 index 0000000..3e452aa Binary files /dev/null and b/public/moments-bg-1.jpg differ diff --git a/public/moments-bg-2.jpg b/public/moments-bg-2.jpg new file mode 100644 index 0000000..c2a0053 Binary files /dev/null and b/public/moments-bg-2.jpg differ diff --git a/public/point-card-apex.jpg b/public/point-card-apex.jpg new file mode 100644 index 0000000..6e793cd Binary files /dev/null and b/public/point-card-apex.jpg differ diff --git a/public/point-card-cs2.jpg b/public/point-card-cs2.jpg new file mode 100644 index 0000000..9931d5b Binary files /dev/null and b/public/point-card-cs2.jpg differ diff --git a/public/point-card-diablo.jpg b/public/point-card-diablo.jpg new file mode 100644 index 0000000..e930145 Binary files /dev/null and b/public/point-card-diablo.jpg differ diff --git a/public/point-card-fortnite.jpg b/public/point-card-fortnite.jpg new file mode 100644 index 0000000..31fac5a Binary files /dev/null and b/public/point-card-fortnite.jpg differ diff --git a/public/point-card-genshin.jpg b/public/point-card-genshin.jpg new file mode 100644 index 0000000..f7854cb Binary files /dev/null and b/public/point-card-genshin.jpg differ diff --git a/public/point-card-hearthstone.jpg b/public/point-card-hearthstone.jpg new file mode 100644 index 0000000..098c418 Binary files /dev/null and b/public/point-card-hearthstone.jpg differ diff --git a/public/point-card-hok.jpg b/public/point-card-hok.jpg new file mode 100644 index 0000000..2422372 Binary files /dev/null and b/public/point-card-hok.jpg differ diff --git a/public/point-card-lol.jpg b/public/point-card-lol.jpg new file mode 100644 index 0000000..8284d30 Binary files /dev/null and b/public/point-card-lol.jpg differ diff --git a/public/point-card-overwatch.jpg b/public/point-card-overwatch.jpg new file mode 100644 index 0000000..7a981bc Binary files /dev/null and b/public/point-card-overwatch.jpg differ diff --git a/public/point-card-pubg.jpg b/public/point-card-pubg.jpg new file mode 100644 index 0000000..176fadf Binary files /dev/null and b/public/point-card-pubg.jpg differ diff --git a/public/point-card-valorant.jpg b/public/point-card-valorant.jpg new file mode 100644 index 0000000..345a441 Binary files /dev/null and b/public/point-card-valorant.jpg differ diff --git a/public/point-card-wow.jpg b/public/point-card-wow.jpg new file mode 100644 index 0000000..133dd4d Binary files /dev/null and b/public/point-card-wow.jpg differ