Simplify homepage, show chapter counts, display directory, trim bottom nav, in-page match feature, move marketing content, and enhance "My" page. #VERCEL_SKIP Co-authored-by: undefined <undefined+undefined@users.noreply.github.com>
216 lines
8.4 KiB
TypeScript
216 lines
8.4 KiB
TypeScript
"use client"
|
||
|
||
import { useState, useEffect } from "react"
|
||
import { X, Copy, Check, RefreshCw } from "lucide-react"
|
||
import { motion, AnimatePresence } from "framer-motion"
|
||
|
||
interface MatchUser {
|
||
id: string
|
||
nickname: string
|
||
tags: string[]
|
||
matchScore: number
|
||
concept: string
|
||
wechat: string
|
||
}
|
||
|
||
interface MatchModalProps {
|
||
isOpen: boolean
|
||
onClose: () => void
|
||
}
|
||
|
||
export function MatchModal({ isOpen, onClose }: MatchModalProps) {
|
||
const [isMatching, setIsMatching] = useState(false)
|
||
const [currentMatch, setCurrentMatch] = useState<MatchUser | null>(null)
|
||
const [copied, setCopied] = useState(false)
|
||
|
||
const getMockMatch = (): MatchUser => {
|
||
const data = [
|
||
{ nickname: "创业小白", tags: ["电商", "私域"], concept: "想找供应链合作伙伴", wechat: "soul_biz_001" },
|
||
{ nickname: "私域达人", tags: ["内容", "直播"], concept: "擅长内容运营,找技术合伙人", wechat: "soul_biz_002" },
|
||
{ nickname: "供应链老兵", tags: ["供应链", "跨境"], concept: "有工厂资源,找流量渠道", wechat: "soul_biz_003" },
|
||
{ nickname: "技术宅", tags: ["AI", "开发"], concept: "会写代码,想找商业方向", wechat: "soul_biz_004" },
|
||
]
|
||
const item = data[Math.floor(Math.random() * data.length)]
|
||
return {
|
||
id: `user_${Date.now()}`,
|
||
...item,
|
||
matchScore: Math.floor(Math.random() * 20) + 80,
|
||
}
|
||
}
|
||
|
||
const startMatch = () => {
|
||
setIsMatching(true)
|
||
setCurrentMatch(null)
|
||
setCopied(false)
|
||
|
||
setTimeout(() => {
|
||
setIsMatching(false)
|
||
setCurrentMatch(getMockMatch())
|
||
}, 2000)
|
||
}
|
||
|
||
const copyWechat = () => {
|
||
if (currentMatch) {
|
||
navigator.clipboard.writeText(currentMatch.wechat)
|
||
setCopied(true)
|
||
setTimeout(() => setCopied(false), 2000)
|
||
}
|
||
}
|
||
|
||
useEffect(() => {
|
||
if (!isOpen) {
|
||
setCurrentMatch(null)
|
||
setIsMatching(false)
|
||
}
|
||
}, [isOpen])
|
||
|
||
if (!isOpen) return null
|
||
|
||
return (
|
||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
|
||
{/* 背景遮罩 */}
|
||
<div className="absolute inset-0 bg-black/80 backdrop-blur-sm" onClick={onClose} />
|
||
|
||
{/* 弹窗内容 */}
|
||
<motion.div
|
||
initial={{ opacity: 0, scale: 0.95 }}
|
||
animate={{ opacity: 1, scale: 1 }}
|
||
exit={{ opacity: 0, scale: 0.95 }}
|
||
className="relative w-full max-w-sm bg-[#111] rounded-3xl overflow-hidden border border-white/10"
|
||
>
|
||
{/* 关闭按钮 */}
|
||
<button
|
||
onClick={onClose}
|
||
className="absolute top-4 right-4 w-8 h-8 rounded-full bg-white/10 flex items-center justify-center z-10"
|
||
>
|
||
<X className="w-4 h-4 text-white/60" />
|
||
</button>
|
||
|
||
<div className="p-6 pt-12">
|
||
<AnimatePresence mode="wait">
|
||
{/* 初始状态 - 开始匹配 */}
|
||
{!isMatching && !currentMatch && (
|
||
<motion.div
|
||
key="idle"
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
exit={{ opacity: 0 }}
|
||
className="text-center"
|
||
>
|
||
<h2 className="text-xl font-bold text-white mb-2">寻找合作伙伴</h2>
|
||
<p className="text-white/50 text-sm mb-8">找到志同道合的创业伙伴</p>
|
||
|
||
{/* 匹配按钮 - 美化的圆形按钮 */}
|
||
<button onClick={startMatch} className="relative w-40 h-40 mx-auto mb-8 group">
|
||
{/* 外圈光环 */}
|
||
<div className="absolute inset-0 rounded-full bg-gradient-to-br from-[var(--app-brand)]/20 to-purple-500/20 animate-pulse" />
|
||
<div className="absolute inset-2 rounded-full bg-gradient-to-br from-[var(--app-brand)]/30 to-purple-500/30" />
|
||
|
||
{/* 主按钮 */}
|
||
<div className="absolute inset-4 rounded-full bg-gradient-to-br from-[var(--app-brand)] to-purple-500 flex flex-col items-center justify-center shadow-lg shadow-[var(--app-brand)]/30 group-active:scale-95 transition-transform">
|
||
<span className="text-4xl mb-1">🤝</span>
|
||
<span className="text-white font-medium text-sm">开始匹配</span>
|
||
</div>
|
||
</button>
|
||
|
||
<div className="space-y-2 text-left">
|
||
<div className="flex items-center gap-2 text-white/50 text-xs">
|
||
<span>💼</span>
|
||
<span>基于创业方向智能匹配</span>
|
||
</div>
|
||
<div className="flex items-center gap-2 text-white/50 text-xs">
|
||
<span>🔒</span>
|
||
<span>信息安全,双向确认才能联系</span>
|
||
</div>
|
||
</div>
|
||
</motion.div>
|
||
)}
|
||
|
||
{/* 匹配中 */}
|
||
{isMatching && (
|
||
<motion.div
|
||
key="matching"
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
exit={{ opacity: 0 }}
|
||
className="text-center py-12"
|
||
>
|
||
<motion.div
|
||
animate={{ rotate: 360 }}
|
||
transition={{ duration: 2, repeat: Number.POSITIVE_INFINITY, ease: "linear" }}
|
||
className="w-20 h-20 mx-auto mb-6 rounded-full border-4 border-[var(--app-brand)]/30 border-t-[var(--app-brand)]"
|
||
/>
|
||
<p className="text-white font-medium">正在匹配中...</p>
|
||
<p className="text-white/40 text-sm mt-1">寻找最佳合作伙伴</p>
|
||
</motion.div>
|
||
)}
|
||
|
||
{/* 匹配成功 */}
|
||
{currentMatch && !isMatching && (
|
||
<motion.div
|
||
key="matched"
|
||
initial={{ opacity: 0, y: 20 }}
|
||
animate={{ opacity: 1, y: 0 }}
|
||
exit={{ opacity: 0 }}
|
||
>
|
||
<div className="text-center mb-4">
|
||
<span className="text-3xl">✨</span>
|
||
<h3 className="text-lg font-bold text-white mt-2">匹配成功!</h3>
|
||
</div>
|
||
|
||
{/* 用户卡片 */}
|
||
<div className="bg-white/5 rounded-2xl p-4 mb-4">
|
||
<div className="flex items-center justify-between mb-3">
|
||
<div>
|
||
<h4 className="text-white font-medium">{currentMatch.nickname}</h4>
|
||
<div className="flex gap-1 mt-1">
|
||
{currentMatch.tags.map((tag) => (
|
||
<span
|
||
key={tag}
|
||
className="px-2 py-0.5 rounded-full text-[10px] bg-[var(--app-brand)]/20 text-[var(--app-brand)]"
|
||
>
|
||
{tag}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="text-right">
|
||
<span className="text-2xl font-bold text-[var(--app-brand)]">{currentMatch.matchScore}%</span>
|
||
<p className="text-white/40 text-[10px]">匹配度</p>
|
||
</div>
|
||
</div>
|
||
<p className="text-white/60 text-sm">{currentMatch.concept}</p>
|
||
</div>
|
||
|
||
{/* 微信号 */}
|
||
<div className="bg-white/5 rounded-xl p-3 mb-4">
|
||
<p className="text-white/40 text-xs mb-1">微信号</p>
|
||
<div className="flex items-center justify-between">
|
||
<code className="text-[var(--app-brand)] font-mono">{currentMatch.wechat}</code>
|
||
<button
|
||
onClick={copyWechat}
|
||
className="flex items-center gap-1 px-3 py-1.5 rounded-lg bg-[var(--app-brand)] text-white text-xs"
|
||
>
|
||
{copied ? <Check className="w-3 h-3" /> : <Copy className="w-3 h-3" />}
|
||
{copied ? "已复制" : "复制"}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 重新匹配 */}
|
||
<button
|
||
onClick={startMatch}
|
||
className="w-full py-3 rounded-xl bg-white/5 text-white/60 text-sm flex items-center justify-center gap-2"
|
||
>
|
||
<RefreshCw className="w-4 h-4" />
|
||
换一个
|
||
</button>
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
</div>
|
||
</motion.div>
|
||
</div>
|
||
)
|
||
}
|