refactor: redesign homepage and navigation based on trends
Update homepage layout and navigation to match current trends. #VERCEL_SKIP Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
This commit is contained in:
@@ -2,55 +2,74 @@
|
||||
|
||||
import Link from "next/link"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { Home, User } from "lucide-react"
|
||||
import { Home, List, Sparkles, User } from "lucide-react"
|
||||
|
||||
export function BottomNav() {
|
||||
const pathname = usePathname()
|
||||
|
||||
// 在文档页面和管理后台不显示底部导航
|
||||
if (pathname.startsWith("/documentation") || pathname.startsWith("/admin")) {
|
||||
// 在文档页面、管理后台、阅读页面和关于页面不显示底部导航
|
||||
if (
|
||||
pathname.startsWith("/documentation") ||
|
||||
pathname.startsWith("/admin") ||
|
||||
pathname.startsWith("/read") ||
|
||||
pathname.startsWith("/about")
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
const navItems = [
|
||||
{ href: "/", icon: Home, label: "首页" },
|
||||
{ href: "/match", emoji: "🤝", label: "匹配合作" },
|
||||
{ href: "/chapters", icon: List, label: "目录" },
|
||||
{ href: "/match", icon: Sparkles, label: "匹配", isCenter: true },
|
||||
{ href: "/my", icon: User, label: "我的" },
|
||||
]
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* iOS风格底部导航 - 只有3个按钮 */}
|
||||
<nav className="fixed bottom-0 left-0 right-0 z-40 glass-nav safe-bottom">
|
||||
<nav className="fixed bottom-0 left-0 right-0 z-40 bg-[#1c1c1e]/95 backdrop-blur-xl border-t border-white/5 safe-bottom">
|
||||
<div className="flex items-center justify-around py-2 max-w-lg mx-auto">
|
||||
{navItems.map((item, index) => {
|
||||
const isActive = pathname === item.href || (item.href === '/match' && pathname.startsWith('/match'))
|
||||
const isActive = pathname === item.href
|
||||
const Icon = item.icon
|
||||
|
||||
// 中间的匹配按钮特殊处理
|
||||
if (item.isCenter) {
|
||||
return (
|
||||
<Link key={index} href={item.href} className="flex flex-col items-center py-2 px-6 -mt-4">
|
||||
<div
|
||||
className={`w-14 h-14 rounded-full flex items-center justify-center shadow-lg transition-all ${
|
||||
isActive
|
||||
? "bg-gradient-to-br from-[#00CED1] to-[#20B2AA] shadow-[#00CED1]/30"
|
||||
: "bg-gradient-to-br from-[#00CED1] to-[#20B2AA] shadow-[#00CED1]/30"
|
||||
}`}
|
||||
>
|
||||
<Icon className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<span className={`text-xs mt-1 ${isActive ? "text-[#00CED1] font-medium" : "text-gray-500"}`}>
|
||||
{item.label}
|
||||
</span>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={index}
|
||||
href={item.href!}
|
||||
className="flex flex-col items-center py-2 px-4 sm:px-6 touch-feedback transition-all duration-200"
|
||||
href={item.href}
|
||||
className="flex flex-col items-center py-2 px-4 touch-feedback transition-all duration-200"
|
||||
>
|
||||
<div className={`w-7 h-7 flex items-center justify-center mb-1 transition-colors ${
|
||||
isActive ? "text-[var(--app-brand)]" : "text-[var(--app-text-tertiary)]"
|
||||
}`}>
|
||||
{item.emoji ? (
|
||||
<span className="text-2xl">{item.emoji}</span>
|
||||
) : (
|
||||
<Icon className="w-6 h-6" strokeWidth={isActive ? 2.5 : 1.5} />
|
||||
)}
|
||||
<div
|
||||
className={`w-6 h-6 flex items-center justify-center mb-1 transition-colors ${
|
||||
isActive ? "text-[#00CED1]" : "text-gray-500"
|
||||
}`}
|
||||
>
|
||||
<Icon className="w-5 h-5" strokeWidth={isActive ? 2 : 1.5} />
|
||||
</div>
|
||||
<span className={`text-[10px] font-medium transition-colors ${
|
||||
isActive ? "text-[var(--app-brand)]" : "text-[var(--app-text-tertiary)]"
|
||||
}`}>
|
||||
<span
|
||||
className={`text-xs transition-colors ${isActive ? "text-[#00CED1] font-medium" : "text-gray-500"}`}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
{/* 激活指示器 */}
|
||||
{isActive && (
|
||||
<div className="absolute -bottom-0.5 w-1 h-1 rounded-full bg-[var(--app-brand)]" />
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -22,6 +22,7 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont
|
||||
const [isAuthOpen, setIsAuthOpen] = useState(false)
|
||||
const [paymentType, setPaymentType] = useState<"section" | "fullbook">("section")
|
||||
const [readingProgress, setReadingProgress] = useState(0)
|
||||
const [showPaywall, setShowPaywall] = useState(false)
|
||||
|
||||
const { user, isLoggedIn, hasPurchased } = useStore()
|
||||
const fullBookPrice = getFullBookPrice()
|
||||
@@ -37,11 +38,15 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont
|
||||
const docHeight = document.documentElement.scrollHeight - window.innerHeight
|
||||
const progress = docHeight > 0 ? Math.min((scrollTop / docHeight) * 100, 100) : 0
|
||||
setReadingProgress(progress)
|
||||
|
||||
if (progress >= 20 && !canAccess) {
|
||||
setShowPaywall(true)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", handleScroll)
|
||||
return () => window.removeEventListener("scroll", handleScroll)
|
||||
}, [])
|
||||
}, [canAccess])
|
||||
|
||||
// 加载内容
|
||||
useEffect(() => {
|
||||
@@ -78,15 +83,14 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont
|
||||
}
|
||||
|
||||
const contentLines = content.split("\n").filter((line) => line.trim())
|
||||
const previewLineCount = Math.ceil(contentLines.length * 0.1) // 改为10%
|
||||
const previewLineCount = Math.ceil(contentLines.length * 0.2) // 改为20%
|
||||
const previewContent = contentLines.slice(0, previewLineCount).join("\n")
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-black text-white">
|
||||
{/* 阅读进度条 */}
|
||||
<div className="fixed top-0 left-0 right-0 z-50 h-0.5 bg-[#1c1c1e]">
|
||||
<div
|
||||
className="h-full bg-gradient-to-r from-[#ff3b5c] to-[#ff6b8a] transition-all duration-150"
|
||||
className="h-full bg-gradient-to-r from-[#00CED1] to-[#20B2AA] transition-all duration-150"
|
||||
style={{ width: `${readingProgress}%` }}
|
||||
/>
|
||||
</div>
|
||||
@@ -95,7 +99,7 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont
|
||||
<header className="sticky top-0 z-40 bg-black/80 backdrop-blur-xl border-b border-white/5">
|
||||
<div className="max-w-2xl mx-auto px-4 py-3 flex items-center justify-between">
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
onClick={() => router.push("/chapters")}
|
||||
className="w-9 h-9 rounded-full bg-[#1c1c1e] flex items-center justify-center active:bg-[#2c2c2e]"
|
||||
>
|
||||
<ChevronLeft className="w-5 h-5 text-gray-400" />
|
||||
@@ -119,13 +123,12 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont
|
||||
|
||||
{/* 阅读内容 */}
|
||||
<main className="max-w-2xl mx-auto px-5 py-8 pb-32">
|
||||
{/* 标题 */}
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<span className="text-[#ff3b5c] text-sm font-medium bg-[#ff3b5c]/10 px-3 py-1 rounded-full">
|
||||
<span className="text-[#00CED1] text-sm font-medium bg-[#00CED1]/10 px-3 py-1 rounded-full">
|
||||
{section.id}
|
||||
</span>
|
||||
{section.isFree && <span className="text-xs text-[#00E5FF] bg-[#00E5FF]/10 px-2 py-0.5 rounded">免费</span>}
|
||||
{section.isFree && <span className="text-xs text-[#00CED1] bg-[#00CED1]/10 px-2 py-0.5 rounded">免费</span>}
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold text-white leading-tight">{section.title}</h1>
|
||||
</div>
|
||||
@@ -166,54 +169,57 @@ export function ChapterContent({ section, partTitle, chapterTitle }: ChapterCont
|
||||
)}
|
||||
</article>
|
||||
|
||||
{/* 渐变遮罩 */}
|
||||
<div className="relative">
|
||||
<div className="absolute -top-32 left-0 right-0 h-32 bg-gradient-to-t from-black to-transparent pointer-events-none" />
|
||||
</div>
|
||||
|
||||
{/* 付费提示卡片 */}
|
||||
<div className="mt-8 p-6 rounded-2xl bg-gradient-to-b from-[#1c1c1e] to-[#2c2c2e] border border-white/10">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 mx-auto mb-4 rounded-2xl bg-[#ff3b5c]/10 flex items-center justify-center">
|
||||
<Lock className="w-8 h-8 text-[#ff3b5c]" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-white mb-2">解锁完整内容</h3>
|
||||
<p className="text-gray-400 text-sm mb-6">
|
||||
已阅读10%,{isLoggedIn ? "购买后继续阅读" : "登录并购买后继续阅读"}
|
||||
</p>
|
||||
|
||||
{/* 购买选项 */}
|
||||
<div className="space-y-3 mb-6">
|
||||
<button
|
||||
onClick={() => handlePurchaseClick("section")}
|
||||
className="w-full py-3.5 px-6 rounded-xl bg-[#2c2c2e] border border-white/10 text-white font-medium active:scale-[0.98] transition-transform"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<span>购买本章</span>
|
||||
<span className="text-[#ff3b5c]">¥{section.price}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handlePurchaseClick("fullbook")}
|
||||
className="w-full py-3.5 px-6 rounded-xl bg-gradient-to-r from-[#ff3b5c] to-[#ff6b8a] text-white font-medium active:scale-[0.98] transition-transform shadow-lg shadow-[#ff3b5c]/20"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>解锁全部 {totalSections} 章</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<span className="text-lg font-bold">¥{fullBookPrice}</span>
|
||||
<span className="text-xs ml-1 opacity-70">省82%</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
{showPaywall && (
|
||||
<>
|
||||
{/* 渐变遮罩 */}
|
||||
<div className="relative">
|
||||
<div className="absolute -top-32 left-0 right-0 h-32 bg-gradient-to-t from-black to-transparent pointer-events-none" />
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-gray-500">分享给好友购买,你可获得90%佣金</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 p-6 rounded-2xl bg-gradient-to-b from-[#1c1c1e] to-[#2c2c2e] border border-[#00CED1]/20">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 mx-auto mb-4 rounded-2xl bg-[#00CED1]/10 flex items-center justify-center">
|
||||
<Lock className="w-8 h-8 text-[#00CED1]" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-white mb-2">解锁完整内容</h3>
|
||||
<p className="text-gray-400 text-sm mb-6">
|
||||
已阅读20%,{isLoggedIn ? "购买后继续阅读" : "登录并购买后继续阅读"}
|
||||
</p>
|
||||
|
||||
{/* 购买选项 */}
|
||||
<div className="space-y-3 mb-6">
|
||||
<button
|
||||
onClick={() => handlePurchaseClick("section")}
|
||||
className="w-full py-3.5 px-6 rounded-xl bg-[#2c2c2e] border border-white/10 text-white font-medium active:scale-[0.98] transition-transform"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<span>购买本章</span>
|
||||
<span className="text-[#00CED1]">¥{section.price}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handlePurchaseClick("fullbook")}
|
||||
className="w-full py-3.5 px-6 rounded-xl bg-gradient-to-r from-[#00CED1] to-[#20B2AA] text-white font-medium active:scale-[0.98] transition-transform shadow-lg shadow-[#00CED1]/20"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>解锁全部 {totalSections} 章</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<span className="text-lg font-bold">¥{fullBookPrice}</span>
|
||||
<span className="text-xs ml-1 opacity-70">省82%</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-gray-500">分享给好友购买,你可获得90%佣金</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user