limo-platform/client/limo-mobile-h5/app/immersive/page.tsx
2025-07-11 15:41:48 +08:00

257 lines
8.8 KiB
TypeScript

"use client"
import type React from "react"
import { useState, useRef } from "react"
import Image from "next/image"
import { ArrowLeft, Heart, MessageCircle, Share, Play, Volume2, VolumeX } from "lucide-react"
import Link from "next/link"
interface VideoData {
id: number
venue: string
title: string
description: string
likes: number
comments: number
shares: number
videoUrl: string
thumbnail: string
isLiked: boolean
}
const mockVideos: VideoData[] = [
{
id: 1,
venue: "RONIN黄金篮球馆",
title: "精彩三分球集锦",
description: "今日比赛精彩瞬间,连续三分命中!#篮球 #精彩瞬间",
likes: 1234,
comments: 89,
shares: 45,
videoUrl: "/placeholder.svg?height=800&width=400&text=Basketball+Highlights",
thumbnail: "/placeholder.svg?height=800&width=400&text=Basketball+Game+1",
isLiked: false,
},
{
id: 2,
venue: "Panda惊怒熊猫运动俱乐部",
title: "激烈对抗瞬间",
description: "双方激烈对抗,精彩防守反击!#运动 #篮球对抗",
likes: 2156,
comments: 156,
shares: 78,
videoUrl: "/placeholder.svg?height=800&width=400&text=Basketball+Defense",
thumbnail: "/placeholder.svg?height=800&width=400&text=Basketball+Game+2",
isLiked: true,
},
{
id: 3,
venue: "星光篮球场",
title: "完美扣篮时刻",
description: "力量与技巧的完美结合,震撼扣篮!#扣篮 #力量",
likes: 3421,
comments: 234,
shares: 123,
videoUrl: "/placeholder.svg?height=800&width=400&text=Basketball+Dunk",
thumbnail: "/placeholder.svg?height=800&width=400&text=Basketball+Game+3",
isLiked: false,
},
{
id: 4,
venue: "蓝天体育馆",
title: "团队配合精彩",
description: "完美的团队配合,流畅的传球配合!#团队 #配合",
likes: 987,
comments: 67,
shares: 34,
videoUrl: "/placeholder.svg?height=800&width=400&text=Team+Play",
thumbnail: "/placeholder.svg?height=800&width=400&text=Basketball+Game+4",
isLiked: false,
},
]
export default function ImmersivePage() {
const [currentIndex, setCurrentIndex] = useState(0)
const [videos, setVideos] = useState(mockVideos)
const [isPlaying, setIsPlaying] = useState(true)
const [isMuted, setIsMuted] = useState(false)
const containerRef = useRef<HTMLDivElement>(null)
const startY = useRef(0)
const currentY = useRef(0)
const handleTouchStart = (e: React.TouchEvent) => {
startY.current = e.touches[0].clientY
}
const handleTouchMove = (e: React.TouchEvent) => {
currentY.current = e.touches[0].clientY
}
const handleTouchEnd = () => {
const deltaY = startY.current - currentY.current
const threshold = 50
if (Math.abs(deltaY) > threshold) {
if (deltaY > 0 && currentIndex < videos.length - 1) {
// 向上滑动,下一个视频
setCurrentIndex(currentIndex + 1)
} else if (deltaY < 0 && currentIndex > 0) {
// 向下滑动,上一个视频
setCurrentIndex(currentIndex - 1)
}
}
}
const handleLike = (videoId: number) => {
setVideos(
videos.map((video) => {
if (video.id === videoId) {
return {
...video,
isLiked: !video.isLiked,
likes: video.isLiked ? video.likes - 1 : video.likes + 1,
}
}
return video
}),
)
}
const formatNumber = (num: number) => {
if (num >= 1000) {
return (num / 1000).toFixed(1) + "k"
}
return num.toString()
}
const currentVideo = videos[currentIndex]
return (
<div className="fixed inset-0 bg-black overflow-hidden">
{/* Header - Minimized */}
<div className="absolute top-0 left-0 right-0 z-20 p-3">
<div className="flex items-center justify-between">
<Link href="/">
<div className="w-8 h-8 bg-black bg-opacity-30 rounded-full flex items-center justify-center">
<ArrowLeft className="w-4 h-4 text-white" />
</div>
</Link>
<div className="text-white text-sm font-medium"></div>
<div className="w-8 h-8"></div>
</div>
</div>
{/* Video Container */}
<div
ref={containerRef}
className="h-full w-full relative"
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
style={{
transform: `translateY(-${currentIndex * 100}%)`,
transition: "transform 0.3s ease-out",
}}
>
{videos.map((video, index) => (
<div key={video.id} className="absolute inset-0 w-full h-full" style={{ top: `${index * 100}%` }}>
{/* Video Background */}
<div className="relative w-full h-full">
<Image
src={video.thumbnail || "/placeholder.svg"}
alt={video.title}
fill
className="object-cover"
priority={Math.abs(index - currentIndex) <= 1}
/>
{/* Video Overlay */}
<div className="absolute inset-0 bg-black bg-opacity-10" />
{/* Play/Pause Button - Minimized */}
<div
className="absolute inset-0 flex items-center justify-center"
onClick={() => setIsPlaying(!isPlaying)}
>
{!isPlaying && (
<div className="w-12 h-12 bg-white bg-opacity-20 rounded-full flex items-center justify-center">
<Play className="w-6 h-6 text-white ml-0.5" fill="currentColor" />
</div>
)}
</div>
</div>
{/* Right Side Actions - Minimized */}
<div className="absolute right-3 bottom-24 flex flex-col items-center space-y-4">
{/* Like Button */}
<div className="flex flex-col items-center">
<button
onClick={() => handleLike(video.id)}
className={`w-9 h-9 rounded-full flex items-center justify-center ${
video.isLiked ? "bg-red-500" : "bg-black bg-opacity-20"
}`}
>
<Heart
className={`w-4 h-4 ${video.isLiked ? "text-white" : "text-white"}`}
fill={video.isLiked ? "currentColor" : "none"}
/>
</button>
<span className="text-white text-xs mt-1 font-medium">{formatNumber(video.likes)}</span>
</div>
{/* Comment Button */}
<div className="flex flex-col items-center">
<button className="w-9 h-9 bg-black bg-opacity-20 rounded-full flex items-center justify-center">
<MessageCircle className="w-4 h-4 text-white" />
</button>
<span className="text-white text-xs mt-1 font-medium">{formatNumber(video.comments)}</span>
</div>
{/* Share Button */}
<div className="flex flex-col items-center">
<button className="w-9 h-9 bg-black bg-opacity-20 rounded-full flex items-center justify-center">
<Share className="w-4 h-4 text-white" />
</button>
<span className="text-white text-xs mt-1 font-medium">{formatNumber(video.shares)}</span>
</div>
{/* Volume Button */}
<button
onClick={() => setIsMuted(!isMuted)}
className="w-9 h-9 bg-black bg-opacity-20 rounded-full flex items-center justify-center"
>
{isMuted ? <VolumeX className="w-4 h-4 text-white" /> : <Volume2 className="w-4 h-4 text-white" />}
</button>
</div>
{/* Bottom Info - Minimized */}
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/50 to-transparent p-3 pb-6">
<div className="max-w-xs">
<h3 className="text-white font-medium text-base mb-1">{video.venue}</h3>
<p className="text-white text-sm opacity-90 leading-relaxed line-clamp-2">{video.description}</p>
</div>
</div>
{/* Progress Indicator - Minimized */}
<div className="absolute right-1 top-1/2 transform -translate-y-1/2 flex flex-col space-y-1">
{videos.map((_, idx) => (
<div
key={idx}
className={`w-0.5 h-6 rounded-full ${idx === currentIndex ? "bg-white" : "bg-white bg-opacity-30"}`}
/>
))}
</div>
</div>
))}
</div>
{/* Swipe Hint - Minimized */}
{currentIndex === 0 && (
<div className="absolute bottom-16 left-1/2 transform -translate-x-1/2 text-white text-xs opacity-60 animate-bounce">
</div>
)}
</div>
)
}