269 lines
8.9 KiB
TypeScript
269 lines
8.9 KiB
TypeScript
import { useState, useMemo } from 'react'
|
||
import Taro from '@tarojs/taro'
|
||
import { View, Text, ScrollView } from '@tarojs/components'
|
||
import { Search, Swiper, SwiperItem, Grid, GridItem, Tabs, Tab, Image as VantImage } from '@antmjs/vantui'
|
||
import ArticleCard from '@/components/ArticleCard'
|
||
import ProductCard from '@/components/ProductCard'
|
||
import { banners, navItems, articles } from '@/mock/articles'
|
||
import { products } from '@/mock/products'
|
||
import type { ArticleCategory } from '@/types/article'
|
||
import type { ProductCategory } from '@/types/product'
|
||
import type { Product } from '@/types/product'
|
||
import CustomTabBar from "@/custom-tab-bar";
|
||
import './index.less'
|
||
|
||
/** 获取状态栏和导航栏高度 */
|
||
function getNavBarHeight() {
|
||
const systemInfo = Taro.getSystemInfoSync()
|
||
const statusBarHeight = systemInfo.statusBarHeight || 20
|
||
// 微信小程序导航栏高度一般为 44px,总高度 = 状态栏 + 导航栏
|
||
const navBarHeight = 44
|
||
return {
|
||
statusBarHeight,
|
||
navBarHeight,
|
||
totalHeight: statusBarHeight + navBarHeight,
|
||
}
|
||
}
|
||
|
||
/** 统一板块标签:校园商城 + 文章分类 */
|
||
const MAIN_TABS = [
|
||
{ title: '校园商城', value: 'mall' },
|
||
{ title: '最新', value: 'latest' },
|
||
{ title: '推荐', value: 'recommend' },
|
||
{ title: '热点', value: 'hot' },
|
||
]
|
||
|
||
/** 商品分类标签 */
|
||
const PRODUCT_CATEGORIES: { title: string; value: ProductCategory | 'all' }[] = [
|
||
{ title: '全部', value: 'all' },
|
||
{ title: '数码', value: 'digital' },
|
||
{ title: '图书', value: 'book' },
|
||
{ title: '生活', value: 'life' },
|
||
{ title: '美食', value: 'food' },
|
||
{ title: '服饰', value: 'cloth' },
|
||
]
|
||
|
||
export default function Index() {
|
||
const [activeMainTab, setActiveMainTab] = useState(0)
|
||
const [activeCategory, setActiveCategory] = useState(0)
|
||
const navBarHeight = useMemo(() => getNavBarHeight(), [])
|
||
|
||
/** 当前选中的板块 */
|
||
const currentTab = MAIN_TABS[activeMainTab]?.value || 'mall'
|
||
|
||
/** 根据文章分类筛 */
|
||
const filteredArticles = useMemo(() => {
|
||
const value = MAIN_TABS[activeMainTab]?.value || 'latest'
|
||
if (value === 'mall') return articles.filter((a) => a.category === 'latest')
|
||
return articles.filter((a) => a.category === value)
|
||
}, [activeMainTab])
|
||
|
||
/** 根据当前分类筛选商品 */
|
||
const filteredProducts = useMemo(() => {
|
||
const catValue = PRODUCT_CATEGORIES[activeCategory]?.value || 'all'
|
||
if (catValue === 'all') return products
|
||
return products.filter((p) => p.category === catValue)
|
||
}, [activeCategory])
|
||
|
||
/** 搜索 */
|
||
const handleSearch = () => {
|
||
Taro.navigateTo({ url: '/pages/search/index' })
|
||
}
|
||
|
||
/** 导航项点击 */
|
||
const handleNavClick = (item: { path: string; label: string }) => {
|
||
if (item.path) {
|
||
Taro.navigateTo({ url: item.path })
|
||
} else {
|
||
Taro.showToast({ title: `${item.label}即将上线`, icon: 'none' })
|
||
}
|
||
}
|
||
|
||
/** 文章点击 */
|
||
const handleArticleClick = (id: string) => {
|
||
Taro.navigateTo({ url: `/pages/article/index?id=${id}` })
|
||
}
|
||
|
||
/** 商品点击 */
|
||
const handleProductClick = (product: Product) => {
|
||
Taro.navigateTo({ url: `/pages/product-detail/index?id=${product.id}` })
|
||
}
|
||
|
||
/** 查看全部商品 */
|
||
const handleViewAll = () => {
|
||
Taro.showToast({ title: '商城即将上线', icon: 'none' })
|
||
}
|
||
|
||
/** 商家入驻 */
|
||
const handleMerchantJoin = () => {
|
||
Taro.showToast({ title: '商家入驻即将上线', icon: 'none' })
|
||
}
|
||
|
||
return (
|
||
<View className='home-page'>
|
||
{/* ========== 自定义导航栏 (毛玻璃) ========== */}
|
||
<View
|
||
className='custom-navbar'
|
||
style={{ paddingTop: `${navBarHeight.statusBarHeight}px` }}
|
||
>
|
||
<View className='navbar-content' style={{ height: `${navBarHeight.navBarHeight}px` }}>
|
||
<View className='navbar-search'>
|
||
<Search
|
||
placeholder='搜索课程、资讯、活动...'
|
||
onFocus={handleSearch}
|
||
shape='round'
|
||
background='transparent'
|
||
/>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
|
||
{/* 占位,补偿固定导航栏高度 */}
|
||
<View style={{ height: `${navBarHeight.totalHeight}px` }} />
|
||
|
||
{/* ========== 可滚动内容区 ========== */}
|
||
<ScrollView
|
||
className='page-scroll'
|
||
scrollY
|
||
enhanced
|
||
showScrollbar={false}
|
||
>
|
||
{/* ========== 卡片轮播图 ========== */}
|
||
<View className='swiper-section'>
|
||
<Swiper
|
||
className='banner-swiper'
|
||
paginationColor='rgba(255,255,255,0.5)'
|
||
height={220}
|
||
autoPlay={3000}
|
||
duration={500}
|
||
loop
|
||
>
|
||
{banners.map((banner) => (
|
||
<SwiperItem key={banner.id}>
|
||
<View className='swiper-card'>
|
||
<VantImage
|
||
className='banner-image'
|
||
src={banner.image}
|
||
fit='cover'
|
||
width='100%'
|
||
height='100%'
|
||
radius={12}
|
||
/>
|
||
<View className='banner-title'>{banner.title}</View>
|
||
</View>
|
||
</SwiperItem>
|
||
))}
|
||
</Swiper>
|
||
</View>
|
||
|
||
{/* ========== 导航组 2行 x 5列 ========== */}
|
||
<View className='nav-section'>
|
||
<Grid columnNum={5} border={false} gutter={8}>
|
||
{navItems.map((item) => (
|
||
<GridItem
|
||
key={item.id}
|
||
icon={item.icon}
|
||
text={item.label}
|
||
onClick={() => handleNavClick(item)}
|
||
/>
|
||
))}
|
||
</Grid>
|
||
</View>
|
||
|
||
{/* ========== 统一板块:校园商城 | 最新 | 推荐 | 热点 ========== */}
|
||
<View className='main-tabs-section'>
|
||
<Tabs
|
||
active={activeMainTab}
|
||
onChange={(e) => setActiveMainTab(e.detail.index)}
|
||
sticky
|
||
offsetTop={navBarHeight.totalHeight}
|
||
color='#1989fa'
|
||
titleActiveColor='#1989fa'
|
||
titleInactiveColor='#646566'
|
||
animated
|
||
swipeable
|
||
>
|
||
{MAIN_TABS.map((tab) => (
|
||
<Tab key={tab.value} title={tab.title} />
|
||
))}
|
||
</Tabs>
|
||
|
||
{/* ===== 校园商城内容 ===== */}
|
||
{currentTab === 'mall' && (
|
||
<View className='mall-content'>
|
||
{/* 商品分类标签 */}
|
||
<ScrollView
|
||
className='category-scroll'
|
||
scrollX
|
||
enhanced
|
||
showScrollbar={false}
|
||
>
|
||
<View className='category-tabs'>
|
||
{PRODUCT_CATEGORIES.map((cat, idx) => (
|
||
<View
|
||
key={cat.value}
|
||
className={`category-tab ${activeCategory === idx ? 'active' : ''}`}
|
||
onClick={() => setActiveCategory(idx)}
|
||
>
|
||
<Text className='category-text'>{cat.title}</Text>
|
||
</View>
|
||
))}
|
||
</View>
|
||
</ScrollView>
|
||
|
||
{/* 商品双列网格 */}
|
||
<View className='product-grid'>
|
||
{filteredProducts.map((product) => (
|
||
<ProductCard
|
||
key={product.id}
|
||
product={product}
|
||
onClick={handleProductClick}
|
||
/>
|
||
))}
|
||
{filteredProducts.length === 0 && (
|
||
<View className='empty-grid'>暂无商品</View>
|
||
)}
|
||
</View>
|
||
|
||
{/* 商家入驻入口 */}
|
||
<View className='merchant-join-card' onClick={handleMerchantJoin}>
|
||
<View className='join-content'>
|
||
<Text className='join-icon'>🏪</Text>
|
||
<View className='join-text-wrap'>
|
||
<Text className='join-title'>商家入驻</Text>
|
||
<Text className='join-desc'>拥有自己的店铺,开启校园创业之旅</Text>
|
||
</View>
|
||
</View>
|
||
<Text className='join-arrow'>›</Text>
|
||
</View>
|
||
</View>
|
||
)}
|
||
|
||
{/* ===== 文章列表内容 ===== */}
|
||
{currentTab !== 'mall' && (
|
||
<View className='article-content'>
|
||
{filteredArticles.map((article) => (
|
||
<View
|
||
key={article.id}
|
||
className='article-item'
|
||
onClick={() => handleArticleClick(article.id)}
|
||
>
|
||
<ArticleCard article={article} />
|
||
</View>
|
||
))}
|
||
{filteredArticles.length === 0 && (
|
||
<View className='empty-tip'>暂无文章</View>
|
||
)}
|
||
</View>
|
||
)}
|
||
</View>
|
||
|
||
{/* 底部安全距离 */}
|
||
<View className='bottom-safe' />
|
||
</ScrollView>
|
||
|
||
{/*<CustomTabBar activeKey='index' />*/}
|
||
</View>
|
||
)
|
||
}
|