diff --git a/app/match/page.tsx b/app/match/page.tsx index 8ff75603..f0b57ab2 100644 --- a/app/match/page.tsx +++ b/app/match/page.tsx @@ -1,7 +1,8 @@ "use client" -import { useState, useEffect } from "react" +import { useState } from "react" import { motion, AnimatePresence } from "framer-motion" +import { Mic } from "lucide-react" interface MatchUser { id: string @@ -14,56 +15,62 @@ interface MatchUser { commonInterests: Array<{ icon: string; text: string }> } +const matchTypes = [ + { id: "partner", label: "创业合伙", icon: "⭐", color: "#00E5FF" }, + { id: "investor", label: "资源对接", icon: "👥", color: "#7B61FF" }, + { id: "mentor", label: "导师顾问", icon: "❤️", color: "#E91E63" }, + { id: "team", label: "团队招募", icon: "🎮", color: "#4CAF50" }, +] + export default function MatchPage() { const [isMatching, setIsMatching] = useState(false) const [currentMatch, setCurrentMatch] = useState(null) const [matchAttempts, setMatchAttempts] = useState(0) + const [selectedType, setSelectedType] = useState("partner") + const [activeTab, setActiveTab] = useState<"voice" | "party" | "team">("voice") 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) + setTimeout( + () => { + clearInterval(interval) + setIsMatching(false) + setCurrentMatch(getMockMatch()) + }, + Math.random() * 3000 + 3000, + ) } const getMockMatch = (): MatchUser => { - const nicknames = ['阅读爱好者', '创业小白', '私域达人', '书虫一枚', '灵魂摆渡人'] + const nicknames = ["创业先锋", "资源整合者", "私域专家", "商业导师", "连续创业者"] const randomIndex = Math.floor(Math.random() * nicknames.length) const concepts = [ - '一个坚持长期主义的私域玩家,擅长内容结构化。', - '相信阅读可以改变人生,每天坚持读书1小时。', - '在Soul上分享创业经验,希望帮助更多人少走弯路。' + "专注私域流量运营5年,帮助100+品牌实现从0到1的增长。", + "连续创业者,擅长商业模式设计和资源整合。", + "在Soul分享真实创业故事,希望找到志同道合的合作伙伴。", ] - const wechats = [ - 'soul_book_friend_1', - 'soul_reader_2024', - 'soul_party_fan' - ] - + const wechats = ["soul_partner_1", "soul_business_2024", "soul_startup_fan"] + return { id: `user_${Date.now()}`, nickname: nicknames[randomIndex], avatar: `https://picsum.photos/200/200?random=${randomIndex}`, - tags: ['创业者', '私域运营', 'MBTI-INTP'], + tags: ["创业者", "私域运营", matchTypes.find((t) => t.id === selectedType)?.label || ""], matchScore: Math.floor(Math.random() * 20) + 80, concept: concepts[randomIndex % concepts.length], wechat: wechats[randomIndex % wechats.length], commonInterests: [ - { icon: '📚', text: '都在读《创业实验》' }, - { icon: '💼', text: '对私域运营感兴趣' }, - { icon: '🎯', text: '相似的职业背景' } - ] + { icon: "📚", text: "都在读《创业实验》" }, + { icon: "💼", text: "对私域运营感兴趣" }, + { icon: "🎯", text: "相似的创业方向" }, + ], } } @@ -74,286 +81,303 @@ export default function MatchPage() { const handleAddWechat = () => { if (!currentMatch) return - - // 复制微信号 - navigator.clipboard.writeText(currentMatch.wechat).then(() => { - alert(`微信号已复制:${currentMatch.wechat}\n\n请打开微信添加好友,备注"书友"即可。`) - }).catch(() => { - alert(`微信号:${currentMatch.wechat}\n\n请手动复制并添加好友。`) - }) + 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· 获取独家资源') - } + const currentTypeLabel = matchTypes.find((t) => t.id === selectedType)?.label || "创业合伙" return ( -
- {/* 星空背景 */} -
- {Array.from({ length: 100 }).map((_, i) => ( +
+ {/* 顶部标题 */} +
+

星球

+ +
+ + {/* Tab切换 */} +
+ + + +
+ + + {!isMatching && !currentMatch && ( - ))} -
- -
- {/* 头部 */} -
-

寻找合作伙伴

-

- 找到和你一起创业的灵魂 -

-
- - {/* 匹配状态区 */} -
- - {!isMatching && !currentMatch && ( + key="idle" + initial={{ opacity: 0, y: 20 }} + animate={{ opacity: 1, y: 0 }} + exit={{ opacity: 0, y: -20 }} + className="flex flex-col items-center px-6" + > + {/* 中央匹配圆环 */} + + {/* 外层光环 */} - {/* 中央大星球 */} - - -
🤝
-
开始匹配
-
寻找合作伙伴
-
- - - + className="absolute inset-[-30px] rounded-full" + style={{ + background: "radial-gradient(circle, transparent 50%, rgba(0, 229, 255, 0.1) 70%, transparent 100%)", + }} + animate={{ + scale: [1, 1.1, 1], + opacity: [0.5, 0.8, 0.5], + }} + transition={{ + duration: 2, + repeat: Number.POSITIVE_INFINITY, + ease: "easeInOut", + }} + /> - {/* 匹配提示 */} -
-
-
- 💼 - 共同的创业方向 -
-
- 💬 - 实时在线交流 -
-
- 🎯 - 相似的商业洞察 -
-
-
+ {/* 中间光环 */} + + + {/* 内层渐变球 */} + + {/* 内部渐变光效 */} +
+ + {/* 中心图标 */} + +
开始匹配
+
寻找{currentTypeLabel}
- )} + - {isMatching && ( - - {/* 匹配动画 */} - - 🌍 - {[1, 2, 3].map((ring) => ( - - ))} - + {/* 当前模式显示 */} +

+ 当前模式: {currentTypeLabel} +

-

- 正在寻找志同道合的书友... -

-

- 已匹配 {matchAttempts} 次 -

+ {/* 分隔线 */} +
+ {/* 选择匹配类型 */} +

选择匹配类型

+
+ {matchTypes.map((type) => ( - - )} + ))} +
+ + )} - {currentMatch && !isMatching && ( + {isMatching && ( + + {/* 匹配动画 */} +
- {/* 成功动画 */} + className="absolute inset-0 rounded-full bg-gradient-to-br from-[#00E5FF] via-[#7B61FF] to-[#E91E63]" + animate={{ rotate: 360 }} + transition={{ duration: 3, repeat: Number.POSITIVE_INFINITY, ease: "linear" }} + /> +
- + +
- {/* 用户卡片 */} -
-
- {currentMatch.nickname} -
-

- {currentMatch.nickname} -

-
- {currentMatch.tags.map((tag) => ( - - {tag} - - ))} -
-
-
-
- {currentMatch.matchScore}% -
-
- 匹配度 -
-
-
+ {/* 扩散波纹 */} + {[1, 2, 3].map((ring) => ( + + ))} +
- {/* 共同兴趣 */} -
-

- 共同兴趣 -

-
- {currentMatch.commonInterests.map((interest, i) => ( -
- {interest.icon} - {interest.text} -
- ))} -
-
+

正在寻找合作伙伴...

+

已匹配 {matchAttempts} 次

- {/* 核心理念 */} -
-

- 核心理念 -

-

- {currentMatch.concept} -

+ + + )} + + {currentMatch && !isMatching && ( + + {/* 成功动画 */} + + + + + {/* 用户卡片 */} +
+
+ {currentMatch.nickname} +
+

{currentMatch.nickname}

+
+ {currentMatch.tags.map((tag) => ( + + {tag} + + ))}
- - {/* 操作按钮 */} -
-
- - -
- +
+
{currentMatch.matchScore}%
+
匹配度
- - )} - -
-
+
+ + {/* 共同兴趣 */} +
+

共同兴趣

+
+ {currentMatch.commonInterests.map((interest, i) => ( +
+ {interest.icon} + {interest.text} +
+ ))} +
+
+ + {/* 核心理念 */} +
+

核心理念

+

{currentMatch.concept}

+
+
+ + {/* 操作按钮 */} +
+ + +
+
+ )} +
) } diff --git a/app/my/page.tsx b/app/my/page.tsx index e6bc2951..db5b3fe2 100644 --- a/app/my/page.tsx +++ b/app/my/page.tsx @@ -2,15 +2,16 @@ import { useState, useEffect } from "react" import Link from "next/link" -import { User, ShoppingBag, Share2, LogOut, ChevronRight, BookOpen } from "lucide-react" +import { User, ChevronRight, Copy, Check } from "lucide-react" import { useStore } from "@/lib/store" import { AuthModal } from "@/components/modules/auth/auth-modal" -import { getFullBookPrice } from "@/lib/book-data" +import { getFullBookPrice, getTotalSectionCount } from "@/lib/book-data" export default function MyPage() { - const { user, isLoggedIn, logout } = useStore() + const { user, isLoggedIn, logout, getAllPurchases } = useStore() const [showAuthModal, setShowAuthModal] = useState(false) const [mounted, setMounted] = useState(false) + const [copied, setCopied] = useState(false) useEffect(() => { setMounted(true) @@ -18,133 +19,402 @@ export default function MyPage() { if (!mounted) { return ( -
-
+
+
) } - if (!isLoggedIn) { - return ( -
-
-
-
- -
-

登录后查看更多

-

查看购买记录、分销收益

- -
-
- setShowAuthModal(false)} /> -
- ) - } - const fullBookPrice = getFullBookPrice() + const totalSections = getTotalSectionCount() + const purchasedCount = user?.hasFullBook ? totalSections : user?.purchasedSections?.length || 0 - return ( -
- {/* User Profile Header */} -
-
-
-
- + // 计算阅读时长(模拟数据,实际应该从localStorage读取) + const readingMinutes = Math.floor(Math.random() * 100) + const bookmarks = user?.purchasedSections?.length || 0 + + const handleCopyCode = () => { + if (user?.referralCode) { + navigator.clipboard.writeText(user.referralCode) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + } + } + + // 未登录状态 + if (!isLoggedIn) { + return ( +
+ {/* 顶部标题 */} +
+

Soul派对·创业实验

+
+ + {/* 用户卡片 - 未登录 */} +
+
+
+
-

{user?.nickname || "用户"}

-

{user?.phone}

+ +

ID: ---

- {/* Stats */} -
-
-

- {user?.hasFullBook ? "全部" : user?.purchasedSections.length || 0} -

-

已购章节

+ {/* 统计数据 */} +
+
+

0

+

已读章节

-
-

¥{(user?.earnings || 0).toFixed(1)}

-

累计收益

+
+

0

+

阅读时长(分)

+
+
+

0

+

书签

-
- {/* Menu Items */} -
-
- {/* Purchase prompt */} - {!user?.hasFullBook && ( - -
-
-
- - 购买整本书 -
- ¥{fullBookPrice} -
-
- - )} - - {/* Menu List - simplified, removed settings and docs */} -
- -
- - 我的购买 -
- - - - -
- - 分销收益 -
-
- ¥{(user?.earnings || 0).toFixed(1)} - -
- + {/* 分销中心 - 未登录 */} +
+
+
+ 💰 + 分销中心 +
+ 佣金比例: 90%
- {/* Referral Code */} -
+ {/* 收益卡片 */} +
+

累计收益

+

¥0.00

+
+
+

可提现

+

¥0.00

+
+
+

已提现

+

¥0.00

+
+
+
+ + {/* 按钮 */} +
+ + +
+ + {/* 统计 */} +
+
+

0

+

推荐人数

+
+
+

0

+

成交订单

+
+
+

90%

+

佣金率

+
+
+ + {/* 邀请码 */} +
-

我的邀请码

- {user?.referralCode} +

我的邀请码

+

- - -

- - {/* Logout */} -
+ + {/* 菜单列表 */} +
+ { + e.preventDefault() + setShowAuthModal(true) + }} + className="flex items-center justify-between p-4 border-b border-white/5 active:bg-white/5" + > +
+ 📦 + 我的订单 +
+ + + { + e.preventDefault() + setShowAuthModal(true) + }} + className="flex items-center justify-between p-4 border-b border-white/5 active:bg-white/5" + > +
+ 🏷️ + 我的书签 +
+ + + { + e.preventDefault() + setShowAuthModal(true) + }} + className="flex items-center justify-between p-4 active:bg-white/5" + > +
+ 📝 + 阅读笔记 +
+ + +
+ + {/* 设置菜单 */} +
+ +
+ ⚙️ + 设置 +
+ + + +
+ 💬 + 联系客服 +
+ + + +
+ ℹ️ + 关于我们 +
+ + +
+ + setShowAuthModal(false)} /> +
+ ) + } + + // 已登录状态 + const userPurchases = getAllPurchases().filter((p) => p.userId === user?.id) + const completedOrders = userPurchases.filter((p) => p.status === "completed").length + + return ( +
+ {/* 顶部标题 */} +
+

Soul派对·创业实验

+
+ + {/* 用户卡片 */} +
+
+
+ +
+
+

{user?.nickname || "用户"}

+

ID: {user?.id?.slice(-8) || "---"}

+
+
+ + {/* 统计数据 */} +
+
+

{purchasedCount}

+

已读章节

+
+
+

{readingMinutes}

+

阅读时长(分)

+
+
+

{bookmarks}

+

书签

+
+
+
+ + {/* 分销中心 */} +
+
+
+ 💰 + 分销中心 +
+ 佣金比例: 90% +
+ + {/* 收益卡片 */} +
+

累计收益

+

¥{(user?.earnings || 0).toFixed(2)}

+
+
+

可提现

+

¥{(user?.pendingEarnings || 0).toFixed(2)}

+
+
+

已提现

+

¥{(user?.withdrawnEarnings || 0).toFixed(2)}

+
+
+
+ + {/* 按钮 */} +
+ + 生成推广海报 + + + 立即提现 + +
+ + {/* 统计 */} +
+
+

{user?.referralCount || 0}

+

推荐人数

+
+
+

{completedOrders}

+

成交订单

+
+
+

90%

+

佣金率

+
+
+ + {/* 邀请码 */} +
+
+
+

我的邀请码

+

{user?.referralCode || "---"}

+
+ +
+
+
+ + {/* 菜单列表 */} +
+ +
+ 📦 + 我的订单 +
+ + + +
+ 🏷️ + 我的书签 +
+ + + +
+ 📝 + 阅读笔记 +
+ + +
+ + {/* 设置菜单 */} +
+ +
+ ⚙️ + 设置 +
+ + + +
+ 💬 + 联系客服 +
+ + + +
+ ℹ️ + 关于我们 +
+ + +
+ + {/* 退出登录 */} +
+
) diff --git a/components/chapter-content.tsx b/components/chapter-content.tsx index ec0a3a77..294c8611 100644 --- a/components/chapter-content.tsx +++ b/components/chapter-content.tsx @@ -6,6 +6,7 @@ import { ChevronLeft, Lock, Share2, Sparkles } from "lucide-react" import { type Section, getFullBookPrice, getTotalSectionCount } from "@/lib/book-data" import { useStore } from "@/lib/store" import { PaymentModal } from "./payment-modal" +import { AuthModal } from "./modules/auth/auth-modal" interface ChapterContentProps { section: Section & { filePath: string } @@ -18,6 +19,7 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont const [content, setContent] = useState("") const [isLoading, setIsLoading] = useState(true) const [isPaymentOpen, setIsPaymentOpen] = useState(false) + const [isAuthOpen, setIsAuthOpen] = useState(false) const [paymentType, setPaymentType] = useState<"section" | "fullbook">("section") const [readingProgress, setReadingProgress] = useState(0) @@ -68,25 +70,23 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont const handlePurchaseClick = (type: "section" | "fullbook") => { if (!isLoggedIn) { - router.push("/login") + setIsAuthOpen(true) return } setPaymentType(type) setIsPaymentOpen(true) } - // 计算预览内容(前50%) const contentLines = content.split("\n").filter((line) => line.trim()) - const previewLineCount = Math.ceil(contentLines.length * 0.5) + const previewLineCount = Math.ceil(contentLines.length * 0.1) // 改为10% const previewContent = contentLines.slice(0, previewLineCount).join("\n") - const hiddenContent = contentLines.slice(previewLineCount).join("\n") return (
{/* 阅读进度条 */}
@@ -122,10 +122,10 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont {/* 标题 */}
- + {section.id} - {section.isFree && 免费} + {section.isFree && 免费}

{section.title}

@@ -153,7 +153,6 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont )} ) : ( - // 付费墙:前半免费,后半付费
{/* 免费预览部分 */}
@@ -175,12 +174,12 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont {/* 付费提示卡片 */}
-
- +
+

解锁完整内容

- 已阅读50%,{isLoggedIn ? "购买后继续阅读" : "登录并购买后继续阅读"} + 已阅读10%,{isLoggedIn ? "购买后继续阅读" : "登录并购买后继续阅读"}

{/* 购买选项 */} @@ -191,13 +190,13 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont >
购买本章 - ¥{section.price} + ¥{section.price}
+ {/* 登录弹窗 */} + setIsAuthOpen(false)} /> + {/* 支付弹窗 */} { + if (href === "/") return pathname === "/" + return pathname.startsWith(href) + } + + return ( + + ) +} diff --git a/components/modules/auth/auth-modal.tsx b/components/modules/auth/auth-modal.tsx index a4b1a914..be5bd5d7 100644 --- a/components/modules/auth/auth-modal.tsx +++ b/components/modules/auth/auth-modal.tsx @@ -1,7 +1,7 @@ "use client" import { useState } from "react" -import { X, Phone, User, Gift } from "lucide-react" +import { X, Phone, Lock, User, Gift } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { useStore } from "@/lib/store" @@ -15,46 +15,58 @@ interface AuthModalProps { export function AuthModal({ isOpen, onClose, defaultTab = "login" }: AuthModalProps) { const [tab, setTab] = useState<"login" | "register">(defaultTab) const [phone, setPhone] = useState("") - const [code, setCode] = useState("") + const [password, setPassword] = useState("") const [nickname, setNickname] = useState("") const [referralCode, setReferralCode] = useState("") const [error, setError] = useState("") - const [codeSent, setCodeSent] = useState(false) + const [isLoading, setIsLoading] = useState(false) const { login, register } = useStore() - const handleSendCode = () => { + const handleLogin = async () => { + setError("") if (phone.length !== 11) { setError("请输入正确的手机号") return } - // Simulate sending verification code - setCodeSent(true) - setError("") - alert("验证码已发送,测试验证码: 123456") - } + if (!password) { + setError("请输入密码") + return + } + + setIsLoading(true) + // 使用密码替代验证码进行登录 + const success = await login(phone, password) + setIsLoading(false) - const handleLogin = async () => { - setError("") - const success = await login(phone, code) if (success) { onClose() } else { - setError("验证码错误或用户不存在,请先注册") + setError("手机号或密码错误,请先注册") } } const handleRegister = async () => { setError("") - if (!nickname.trim()) { - setError("请输入昵称") + if (phone.length !== 11) { + setError("请输入正确的手机号") return } - const success = await register(phone, nickname, referralCode || undefined) + if (!password || password.length < 6) { + setError("密码至少6位") + return + } + + setIsLoading(true) + // 昵称可选,默认使用手机号后四位 + const name = nickname.trim() || `用户${phone.slice(-4)}` + const success = await register(phone, name, referralCode || undefined) + setIsLoading(false) + if (success) { onClose() } else { - setError("该手机号已注册") + setError("该手机号已注册,请直接登录") } } @@ -63,32 +75,38 @@ export function AuthModal({ isOpen, onClose, defaultTab = "login" }: AuthModalPr return (
{/* Backdrop */} -
+
{/* Modal */} -
+
{/* Close button */} {/* Tabs */} -
+
- {error &&

{error}

} + {error &&

{error}

} - + +

测试账号:任意11位手机号,密码:123456

) : (
- +
- + setPhone(e.target.value)} placeholder="请输入手机号" - className="pl-10 bg-[#0a1628] border-gray-700 text-white placeholder:text-gray-500" + className="pl-10 bg-[#2c2c2e] border-white/10 text-white placeholder:text-white/30 h-12 rounded-xl" maxLength={11} />
- +
- + + setPassword(e.target.value)} + placeholder="设置密码(至少6位)" + className="pl-10 bg-[#2c2c2e] border-white/10 text-white placeholder:text-white/30 h-12 rounded-xl" + /> +
+
+ +
+ +
+ setNickname(e.target.value)} - placeholder="请输入昵称" - className="pl-10 bg-[#0a1628] border-gray-700 text-white placeholder:text-gray-500" + placeholder="不填则使用默认昵称" + className="pl-10 bg-[#2c2c2e] border-white/10 text-white placeholder:text-white/30 h-12 rounded-xl" />
- -
- setCode(e.target.value)} - placeholder="请输入验证码" - className="bg-[#0a1628] border-gray-700 text-white placeholder:text-gray-500" - maxLength={6} - /> - -
-
- -
- +
- + setReferralCode(e.target.value)} - placeholder="填写邀请码可获得优惠" - className="pl-10 bg-[#0a1628] border-gray-700 text-white placeholder:text-gray-500" + placeholder="填写可获得优惠" + className="pl-10 bg-[#2c2c2e] border-white/10 text-white placeholder:text-white/30 h-12 rounded-xl" />
- {error &&

{error}

} + {error &&

{error}

} -
)}