104 lines
3.2 KiB
TypeScript
104 lines
3.2 KiB
TypeScript
import { useState, useMemo } from 'react'
|
|
import Taro from '@tarojs/taro'
|
|
import { View, ScrollView } from '@tarojs/components'
|
|
import { Search } from '@antmjs/vantui'
|
|
import TaskCard from '@/components/TaskCard'
|
|
import { tasks } from '@/mock/tasks'
|
|
import './index.less'
|
|
|
|
/** 筛选标签 */
|
|
const FILTER_TABS = [
|
|
{ title: '全部', value: 'all' as const },
|
|
{ title: '快递代取', value: 'express' as const },
|
|
{ title: '二手交易', value: 'secondhand' as const },
|
|
{ title: '求助', value: 'help' as const },
|
|
{ title: '活动', value: 'activity' as const },
|
|
{ title: '拼车', value: 'carpool' as const },
|
|
]
|
|
|
|
/** 任务类型 → emoji */
|
|
const TYPE_EMOJI: Record<string, string> = {
|
|
all: '📋',
|
|
express: '📦',
|
|
secondhand: '🛍️',
|
|
help: '🆘',
|
|
activity: '🎉',
|
|
carpool: '🚗',
|
|
}
|
|
|
|
export default function Tasks() {
|
|
const [activeFilter, setActiveFilter] = useState(0)
|
|
const [searchValue, setSearchValue] = useState('')
|
|
|
|
const filteredTasks = useMemo(() => {
|
|
const filterValue = FILTER_TABS[activeFilter]?.value || 'all'
|
|
let list = filterValue === 'all' ? tasks : tasks.filter((t) => t.type === filterValue)
|
|
if (searchValue.trim()) {
|
|
const kw = searchValue.trim().toLowerCase()
|
|
list = list.filter(
|
|
(t) =>
|
|
t.title.toLowerCase().includes(kw) ||
|
|
t.desc.toLowerCase().includes(kw) ||
|
|
t.location.toLowerCase().includes(kw),
|
|
)
|
|
}
|
|
return list
|
|
}, [activeFilter, searchValue])
|
|
|
|
const handleTaskClick = (id: string) => {
|
|
Taro.navigateTo({ url: `/pages/task-detail/index?id=${id}` })
|
|
}
|
|
|
|
return (
|
|
<View className='tasks-page'>
|
|
{/* 搜索栏 */}
|
|
<View className='tasks-search-bar'>
|
|
<Search
|
|
value={searchValue}
|
|
placeholder='搜索校园任务...'
|
|
shape='round'
|
|
onChange={(e) => setSearchValue(e.detail)}
|
|
onClear={() => setSearchValue('')}
|
|
/>
|
|
</View>
|
|
|
|
{/* 分类标签 */}
|
|
<View className='tasks-filter'>
|
|
<ScrollView scrollX enhanced showScrollbar={false} className='filter-scroll'>
|
|
<View className='filter-tabs'>
|
|
{FILTER_TABS.map((tab, idx) => (
|
|
<View
|
|
key={tab.value}
|
|
className={`filter-tab ${activeFilter === idx ? 'active' : ''}`}
|
|
onClick={() => setActiveFilter(idx)}
|
|
>
|
|
<View className='filter-emoji'>{TYPE_EMOJI[tab.value]}</View>
|
|
<View className='filter-label'>{tab.title}</View>
|
|
</View>
|
|
))}
|
|
</View>
|
|
</ScrollView>
|
|
</View>
|
|
|
|
{/* 任务列表 */}
|
|
<ScrollView className='tasks-scroll' scrollY enhanced showScrollbar={false}>
|
|
<View className='tasks-list'>
|
|
{filteredTasks.map((task) => (
|
|
<View
|
|
key={task.id}
|
|
className='task-card-wrap'
|
|
onClick={() => handleTaskClick(task.id)}
|
|
>
|
|
<TaskCard task={task} />
|
|
</View>
|
|
))}
|
|
{filteredTasks.length === 0 && (
|
|
<View className='empty-tip'>暂无相关任务</View>
|
|
)}
|
|
</View>
|
|
<View className='bottom-safe' />
|
|
</ScrollView>
|
|
</View>
|
|
)
|
|
}
|