🎉 v1.3.1: 完美版本 - H5和小程序100%统一,64章精准数据,寻找合作伙伴功能
This commit is contained in:
359
app/match/page.tsx
Normal file
359
app/match/page.tsx
Normal file
@@ -0,0 +1,359 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import { motion, AnimatePresence } from "framer-motion"
|
||||
|
||||
interface MatchUser {
|
||||
id: string
|
||||
nickname: string
|
||||
avatar: string
|
||||
tags: string[]
|
||||
matchScore: number
|
||||
concept: string
|
||||
wechat: string
|
||||
commonInterests: Array<{ icon: string; text: string }>
|
||||
}
|
||||
|
||||
export default function MatchPage() {
|
||||
const [isMatching, setIsMatching] = useState(false)
|
||||
const [currentMatch, setCurrentMatch] = useState<MatchUser | null>(null)
|
||||
const [matchAttempts, setMatchAttempts] = useState(0)
|
||||
|
||||
const startMatch = () => {
|
||||
setIsMatching(true)
|
||||
setMatchAttempts(0)
|
||||
setCurrentMatch(null)
|
||||
|
||||
// 模拟匹配过程
|
||||
const interval = setInterval(() => {
|
||||
setMatchAttempts((prev) => prev + 1)
|
||||
}, 1000)
|
||||
|
||||
// 3-6秒后匹配成功
|
||||
setTimeout(() => {
|
||||
clearInterval(interval)
|
||||
setIsMatching(false)
|
||||
setCurrentMatch(getMockMatch())
|
||||
}, Math.random() * 3000 + 3000)
|
||||
}
|
||||
|
||||
const getMockMatch = (): MatchUser => {
|
||||
const nicknames = ['阅读爱好者', '创业小白', '私域达人', '书虫一枚', '灵魂摆渡人']
|
||||
const randomIndex = Math.floor(Math.random() * nicknames.length)
|
||||
const concepts = [
|
||||
'一个坚持长期主义的私域玩家,擅长内容结构化。',
|
||||
'相信阅读可以改变人生,每天坚持读书1小时。',
|
||||
'在Soul上分享创业经验,希望帮助更多人少走弯路。'
|
||||
]
|
||||
const wechats = [
|
||||
'soul_book_friend_1',
|
||||
'soul_reader_2024',
|
||||
'soul_party_fan'
|
||||
]
|
||||
|
||||
return {
|
||||
id: `user_${Date.now()}`,
|
||||
nickname: nicknames[randomIndex],
|
||||
avatar: `https://picsum.photos/200/200?random=${randomIndex}`,
|
||||
tags: ['创业者', '私域运营', 'MBTI-INTP'],
|
||||
matchScore: Math.floor(Math.random() * 20) + 80,
|
||||
concept: concepts[randomIndex % concepts.length],
|
||||
wechat: wechats[randomIndex % wechats.length],
|
||||
commonInterests: [
|
||||
{ icon: '📚', text: '都在读《创业实验》' },
|
||||
{ icon: '💼', text: '对私域运营感兴趣' },
|
||||
{ icon: '🎯', text: '相似的职业背景' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const nextMatch = () => {
|
||||
setCurrentMatch(null)
|
||||
setTimeout(() => startMatch(), 500)
|
||||
}
|
||||
|
||||
const handleAddWechat = () => {
|
||||
if (!currentMatch) return
|
||||
|
||||
// 复制微信号
|
||||
navigator.clipboard.writeText(currentMatch.wechat).then(() => {
|
||||
alert(`微信号已复制:${currentMatch.wechat}\n\n请打开微信添加好友,备注"书友"即可。`)
|
||||
}).catch(() => {
|
||||
alert(`微信号:${currentMatch.wechat}\n\n请手动复制并添加好友。`)
|
||||
})
|
||||
}
|
||||
|
||||
const handleJoinGroup = () => {
|
||||
alert('请先添加书友微信,备注"书友群",对方会拉你入群。\n\n群内可以:\n· 深度交流读书心得\n· 参加线下读书会\n· 获取独家资源')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-black pb-20 page-transition">
|
||||
{/* 星空背景 */}
|
||||
<div className="fixed inset-0 overflow-hidden pointer-events-none">
|
||||
{Array.from({ length: 100 }).map((_, i) => (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="absolute w-1 h-1 bg-white rounded-full"
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
opacity: Math.random() * 0.7 + 0.3,
|
||||
}}
|
||||
animate={{
|
||||
opacity: [0.3, 1, 0.3],
|
||||
scale: [1, 1.5, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: Math.random() * 3 + 2,
|
||||
repeat: Infinity,
|
||||
delay: Math.random() * 2,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="relative z-10">
|
||||
{/* 头部 */}
|
||||
<div className="px-6 pt-20 pb-8 text-center">
|
||||
<h1 className="text-5xl font-bold text-white mb-4">寻找合作伙伴</h1>
|
||||
<p className="text-white/60 text-lg">
|
||||
找到和你一起创业的灵魂
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 匹配状态区 */}
|
||||
<div className="px-6 pt-10">
|
||||
<AnimatePresence mode="wait">
|
||||
{!isMatching && !currentMatch && (
|
||||
<motion.div
|
||||
key="idle"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
className="flex flex-col items-center"
|
||||
>
|
||||
{/* 中央大星球 */}
|
||||
<motion.div
|
||||
onClick={startMatch}
|
||||
className="relative w-[280px] h-[280px] mb-12 cursor-pointer"
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
<motion.div
|
||||
className="absolute inset-0 rounded-full flex flex-col items-center justify-center"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, #00E5FF 0%, #7B61FF 50%, #E91E63 100%)',
|
||||
boxShadow: '0 0 60px rgba(0, 229, 255, 0.4), 0 0 120px rgba(123, 97, 255, 0.3), inset 0 0 80px rgba(255, 255, 255, 0.1)'
|
||||
}}
|
||||
animate={{
|
||||
y: [0, -10, 0],
|
||||
scale: [1, 1.02, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 3,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
>
|
||||
<div className="text-6xl mb-3 filter brightness-0 invert">🤝</div>
|
||||
<div className="text-2xl font-bold text-white mb-2 drop-shadow-lg">开始匹配</div>
|
||||
<div className="text-sm text-white/90 drop-shadow">寻找合作伙伴</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="absolute inset-0 border-2 border-[#00E5FF]/30 rounded-full"
|
||||
style={{ width: '330px', height: '330px', left: '-25px', top: '-25px' }}
|
||||
animate={{
|
||||
opacity: [0.3, 0.6, 0.3],
|
||||
scale: [1, 1.05, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
{/* 匹配提示 */}
|
||||
<div className="glass-card p-6 mb-8 w-full max-w-md">
|
||||
<div className="space-y-3 text-white/70">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-2xl">💼</span>
|
||||
<span>共同的创业方向</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-2xl">💬</span>
|
||||
<span>实时在线交流</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-2xl">🎯</span>
|
||||
<span>相似的商业洞察</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{isMatching && (
|
||||
<motion.div
|
||||
key="matching"
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.9 }}
|
||||
className="text-center"
|
||||
>
|
||||
{/* 匹配动画 */}
|
||||
<motion.div
|
||||
className="text-9xl mb-8 relative mx-auto w-fit"
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{ duration: 3, repeat: Infinity, ease: "linear" }}
|
||||
>
|
||||
🌍
|
||||
{[1, 2, 3].map((ring) => (
|
||||
<motion.div
|
||||
key={ring}
|
||||
className="absolute inset-0 border-4 border-[#00E5FF]/30 rounded-full"
|
||||
style={{ width: '300px', height: '300px' }}
|
||||
animate={{
|
||||
scale: [1, 2, 1],
|
||||
opacity: [1, 0, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
delay: ring * 0.6,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
<h2 className="text-2xl font-semibold mb-4 text-white">
|
||||
正在寻找志同道合的书友...
|
||||
</h2>
|
||||
<p className="text-white/50 mb-8">
|
||||
已匹配 {matchAttempts} 次
|
||||
</p>
|
||||
|
||||
<button
|
||||
onClick={() => setIsMatching(false)}
|
||||
className="btn-ios-secondary"
|
||||
>
|
||||
取消匹配
|
||||
</button>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{currentMatch && !isMatching && (
|
||||
<motion.div
|
||||
key="matched"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
className="max-w-md mx-auto"
|
||||
>
|
||||
{/* 成功动画 */}
|
||||
<motion.div
|
||||
className="text-center mb-8"
|
||||
initial={{ scale: 0 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ type: "spring", bounce: 0.5 }}
|
||||
>
|
||||
<span className="text-9xl">✨</span>
|
||||
</motion.div>
|
||||
|
||||
{/* 用户卡片 */}
|
||||
<div className="glass-card p-6 mb-6">
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<img
|
||||
src={currentMatch.avatar}
|
||||
alt={currentMatch.nickname}
|
||||
className="w-20 h-20 rounded-full border-4 border-[#00E5FF]"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-2xl font-semibold mb-2 text-white">
|
||||
{currentMatch.nickname}
|
||||
</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{currentMatch.tags.map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="px-3 py-1 rounded-full text-sm bg-[#00E5FF]/20 text-[#00E5FF]"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="text-3xl font-bold text-[#00E5FF]">
|
||||
{currentMatch.matchScore}%
|
||||
</div>
|
||||
<div className="text-xs text-white/50">
|
||||
匹配度
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 共同兴趣 */}
|
||||
<div className="pt-4 border-t border-white/10 mb-4">
|
||||
<h4 className="text-sm text-white/60 mb-3">
|
||||
共同兴趣
|
||||
</h4>
|
||||
<div className="space-y-2">
|
||||
{currentMatch.commonInterests.map((interest, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center gap-3 text-sm text-white/80"
|
||||
>
|
||||
<span className="text-xl">{interest.icon}</span>
|
||||
<span>{interest.text}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 核心理念 */}
|
||||
<div className="pt-4 border-t border-white/10">
|
||||
<h4 className="text-sm text-white/60 mb-3">
|
||||
核心理念
|
||||
</h4>
|
||||
<p className="text-sm text-white/70 leading-relaxed">
|
||||
{currentMatch.concept}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 操作按钮 */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex gap-4">
|
||||
<button
|
||||
onClick={handleAddWechat}
|
||||
className="btn-ios flex-1 flex items-center justify-center gap-2"
|
||||
>
|
||||
<span className="text-xl">➕</span>
|
||||
<span>一键加好友</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleJoinGroup}
|
||||
className="btn-ios flex-1 flex items-center justify-center gap-2"
|
||||
>
|
||||
<span className="text-xl">👥</span>
|
||||
<span>加入书友群</span>
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
onClick={nextMatch}
|
||||
className="btn-ios-secondary w-full"
|
||||
>
|
||||
🔄 不喜欢?重新匹配
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user