首页
This commit is contained in:
+161
-27
@@ -1,34 +1,168 @@
|
||||
import { View } from '@tarojs/components'
|
||||
import { Button } from '@antmjs/vantui'
|
||||
import { useState, useMemo } from 'react'
|
||||
import Taro from '@tarojs/taro'
|
||||
import { View, ScrollView } from '@tarojs/components'
|
||||
import { Search, Swiper, SwiperItem, Grid, GridItem, Tabs, Tab, Image as VantImage } from '@antmjs/vantui'
|
||||
import ArticleCard from '@/components/ArticleCard'
|
||||
import { banners, navItems, articles } from '@/mock/articles'
|
||||
import type { ArticleCategory } from '@/types/article'
|
||||
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 TAB_LIST = [
|
||||
{ title: '最新', value: 'latest' as ArticleCategory },
|
||||
{ title: '推荐', value: 'recommend' as ArticleCategory },
|
||||
{ title: '热点', value: 'hot' as ArticleCategory },
|
||||
]
|
||||
|
||||
export default function Index() {
|
||||
const [activeTab, setActiveTab] = useState(0)
|
||||
const navBarHeight = useMemo(() => getNavBarHeight(), [])
|
||||
|
||||
/** 根据当前 tab 筛选文章 */
|
||||
const filteredArticles = useMemo(() => {
|
||||
const category = TAB_LIST[activeTab]?.value || 'latest'
|
||||
return articles.filter((a) => a.category === category)
|
||||
}, [activeTab])
|
||||
|
||||
/** 搜索 */
|
||||
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}` })
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='index'>
|
||||
<View><Button type='primary'>Hello world!</Button></View>
|
||||
<View>上面的按钮的颜色已经通过全局主题重写覆盖了,参见src/styles/index.less</View>
|
||||
<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='tabs-section'>
|
||||
<Tabs
|
||||
active={activeTab}
|
||||
onChange={(e) => setActiveTab(e.detail.index)}
|
||||
sticky
|
||||
offsetTop={navBarHeight.totalHeight}
|
||||
color='#1989fa'
|
||||
titleActiveColor='#1989fa'
|
||||
titleInactiveColor='#646566'
|
||||
>
|
||||
{TAB_LIST.map((tab) => (
|
||||
<Tab key={tab.value} title={tab.title} />
|
||||
))}
|
||||
</Tabs>
|
||||
</View>
|
||||
|
||||
{/* ========== 文章列表 ========== */}
|
||||
<View className='article-list'>
|
||||
{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 className='bottom-safe' />
|
||||
</ScrollView>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
// export default class Index extends Component {
|
||||
|
||||
// componentWillMount () { }
|
||||
|
||||
// componentDidMount () { }
|
||||
|
||||
// componentWillUnmount () { }
|
||||
|
||||
// componentDidShow () { }
|
||||
|
||||
// componentDidHide () { }
|
||||
|
||||
// render () {
|
||||
// return (
|
||||
// <View className='index'>
|
||||
// <View><Button type='primary'>Hello world!</Button></View>
|
||||
// <View>上面的按钮的颜色已经通过全局主题重写覆盖了,参见src/style/index.less</View>
|
||||
// </View>
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user