任务、消息

This commit is contained in:
liu
2026-07-01 22:16:15 +08:00
parent 137db25b49
commit d98457e1dd
22 changed files with 1504 additions and 63 deletions
+81 -13
View File
@@ -1,29 +1,97 @@
/* ========================================
校园任务页面
======================================== */
.tasks-page {
min-height: 100vh;
display: flex;
flex-direction: column;
background: #f7f8fa;
}
.page-placeholder {
/* 搜索栏 */
.tasks-search-bar {
padding: 20px 24px;
background: #fff;
}
/* 分类筛选 */
.tasks-filter {
background: #fff;
padding-bottom: 16px;
.filter-scroll {
white-space: nowrap;
}
.filter-tabs {
display: flex;
padding: 0 24px;
gap: 12px;
}
.filter-tab {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: 300px;
padding: 16px 20px;
border-radius: 16px;
background: #f7f8fa;
flex-shrink: 0;
min-width: 120px;
transition: all 0.2s;
.placeholder-icon {
font-size: 96px;
margin-bottom: 24px;
&.active {
background: #1989fa;
box-shadow: 0 4px 16px rgba(25, 137, 250, 0.3);
.filter-emoji {
transform: scale(1.1);
}
.filter-label {
color: #fff;
}
}
.placeholder-text {
.filter-emoji {
font-size: 36px;
font-weight: 500;
color: #323233;
margin-bottom: 12px;
margin-bottom: 6px;
transition: transform 0.2s;
}
.placeholder-desc {
font-size: 28px;
color: #969799;
.filter-label {
font-size: 24px;
color: #646566;
}
}
}
/* 任务列表 */
.tasks-scroll {
flex: 1;
}
.tasks-list {
padding: 16px 24px;
.task-card-wrap {
margin-bottom: 16px;
transition: transform 0.2s;
&:active {
transform: scale(0.98);
}
}
.empty-tip {
text-align: center;
padding: 120px 0;
font-size: 28px;
color: #969799;
}
}
.bottom-safe {
height: 20px;
}
+97 -6
View File
@@ -1,15 +1,106 @@
import { View, Text } from '@tarojs/components'
import CustomTabBar from "@/custom-tab-bar"
import { useState, useMemo } from 'react'
import Taro from '@tarojs/taro'
import { View, ScrollView } from '@tarojs/components'
import { Search, Tabs, Tab } from '@antmjs/vantui'
import TaskCard from '@/components/TaskCard'
import CustomTabBar from '@/custom-tab-bar'
import { tasks } from '@/mock/tasks'
import type { TaskType } from '@/types/task'
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.showToast({ title: '任务详情即将上线', icon: 'none' })
}
return (
<View className='tasks-page'>
<View className='page-placeholder'>
<Text className='placeholder-icon'>📋</Text>
<Text className='placeholder-text'></Text>
<Text className='placeholder-desc'>线</Text>
{/* 搜索栏 */}
<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>
<CustomTabBar activeKey='tasks' />
</View>
)