forked from gxwebsoft/mp-10550
- 新增优惠券卡片对齐修复文档 - 新增优惠券状态显示调试文档 - 新增优惠券组件警告修复文档- 更新用ShopInfo Hook字段迁移文档 - 更新Arguments关键字修复文档
238 lines
6.9 KiB
TypeScript
238 lines
6.9 KiB
TypeScript
import {SetStateAction, useEffect, useState} from 'react'
|
|
import {useRouter} from '@tarojs/taro'
|
|
import Taro from '@tarojs/taro'
|
|
import {View} from '@tarojs/components'
|
|
import {Loading, Empty, InfiniteLoading, Input, Button} from '@nutui/nutui-react-taro'
|
|
import {Search} from '@nutui/icons-react-taro';
|
|
import {ShopGoods} from '@/api/shop/shopGoods/model'
|
|
import {pageShopGoods} from '@/api/shop/shopGoods'
|
|
import GoodsItem from './components/GoodsItem'
|
|
import './index.scss'
|
|
|
|
const SearchPage = () => {
|
|
const router = useRouter()
|
|
const [keywords, setKeywords] = useState<string>('')
|
|
const [goodsList, setGoodsList] = useState<ShopGoods[]>([])
|
|
const [loading, setLoading] = useState(false)
|
|
const [page, setPage] = useState(1)
|
|
const [hasMore, setHasMore] = useState(true)
|
|
const [total, setTotal] = useState(0)
|
|
const [searchHistory, setSearchHistory] = useState<string[]>([])
|
|
|
|
// 从路由参数获取搜索关键词
|
|
useEffect(() => {
|
|
const {keywords: routeKeywords} = router.params || {}
|
|
if (routeKeywords) {
|
|
setKeywords(decodeURIComponent(routeKeywords))
|
|
handleSearch(decodeURIComponent(routeKeywords), 1).then()
|
|
}
|
|
|
|
// 加载搜索历史
|
|
loadSearchHistory()
|
|
}, [])
|
|
|
|
// 加载搜索历史
|
|
const loadSearchHistory = () => {
|
|
try {
|
|
const history = Taro.getStorageSync('search_history') || []
|
|
setSearchHistory(history)
|
|
} catch (error) {
|
|
console.error('加载搜索历史失败:', error)
|
|
}
|
|
}
|
|
|
|
// 保存搜索历史
|
|
const saveSearchHistory = (keyword: string) => {
|
|
try {
|
|
let history = Taro.getStorageSync('search_history') || []
|
|
// 去重并添加到开头
|
|
history = history.filter((item: string) => item !== keyword)
|
|
history.unshift(keyword)
|
|
// 只保留最近10条
|
|
history = history.slice(0, 10)
|
|
Taro.setStorageSync('search_history', history)
|
|
setSearchHistory(history)
|
|
} catch (error) {
|
|
console.error('保存搜索历史失败:', error)
|
|
}
|
|
}
|
|
|
|
const handleKeywords = (keywords: SetStateAction<string>) => {
|
|
setKeywords(keywords)
|
|
handleSearch(typeof keywords === "string" ? keywords : '').then()
|
|
}
|
|
|
|
// 搜索商品
|
|
const handleSearch = async (searchKeywords: string, pageNum: number = 1) => {
|
|
if (!searchKeywords.trim()) {
|
|
Taro.showToast({
|
|
title: '请输入搜索关键词',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
setLoading(true)
|
|
|
|
try {
|
|
const params = {
|
|
keywords: searchKeywords.trim(),
|
|
page: pageNum,
|
|
size: 10,
|
|
isShow: 1 // 只搜索上架商品
|
|
}
|
|
|
|
const result = await pageShopGoods(params)
|
|
|
|
if (pageNum === 1) {
|
|
setGoodsList(result?.list || [])
|
|
setTotal(result?.count || 0)
|
|
// 保存搜索历史
|
|
saveSearchHistory(searchKeywords.trim())
|
|
} else {
|
|
setGoodsList(prev => [...prev, ...(result?.list || [])])
|
|
}
|
|
|
|
setHasMore((result?.list?.length || 0) >= 10)
|
|
setPage(pageNum)
|
|
|
|
} catch (error) {
|
|
console.error('搜索失败:', error)
|
|
Taro.showToast({
|
|
title: '搜索失败,请重试',
|
|
icon: 'none'
|
|
})
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
// 加载更多
|
|
const loadMore = () => {
|
|
if (!loading && hasMore && keywords.trim()) {
|
|
handleSearch(keywords, page + 1).then()
|
|
}
|
|
}
|
|
|
|
// 点击历史搜索
|
|
const onHistoryClick = (keyword: string) => {
|
|
setKeywords(keyword)
|
|
setPage(1)
|
|
handleSearch(keyword, 1)
|
|
}
|
|
|
|
// 清空搜索历史
|
|
const clearHistory = () => {
|
|
Taro.showModal({
|
|
title: '提示',
|
|
content: '确定要清空搜索历史吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
try {
|
|
Taro.removeStorageSync('search_history')
|
|
setSearchHistory([])
|
|
} catch (error) {
|
|
console.error('清空搜索历史失败:', error)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
return (
|
|
<View className="search-page pt-3">
|
|
<div className={'px-2'}>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
background: '#ffffff',
|
|
padding: '0 5px',
|
|
borderRadius: '20px',
|
|
marginTop: '5px',
|
|
}}
|
|
>
|
|
<Search size={18} className={'ml-2 text-gray-400'}/>
|
|
<Input
|
|
placeholder="搜索商品"
|
|
value={keywords}
|
|
onChange={handleKeywords}
|
|
onConfirm={() => handleSearch(keywords)}
|
|
style={{padding: '9px 8px'}}
|
|
/>
|
|
<div
|
|
className={'flex items-center'}
|
|
>
|
|
<Button type="success" style={{background: 'linear-gradient(to bottom, #1cd98a, #24ca94)'}}
|
|
onClick={() => handleSearch(keywords)}>
|
|
搜索
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/*<SearchBar style={{height: `${statusBarHeight}px`}} shape="round" placeholder="搜索商品" onChange={setKeywords} onSearch={handleSearch}/>*/}
|
|
|
|
{/* 搜索内容 */}
|
|
<View className="search-content">
|
|
{/* 搜索历史 */}
|
|
{!keywords && searchHistory.length > 0 && (
|
|
<View className="search-history">
|
|
<View className="history-header">
|
|
<View className="text-sm">搜索历史</View>
|
|
<View className={'text-gray-400'} onClick={clearHistory}>清空</View>
|
|
</View>
|
|
<View className="history-list">
|
|
{searchHistory.map((item, index) => (
|
|
<View
|
|
key={index}
|
|
className="history-item"
|
|
onClick={() => onHistoryClick(item)}
|
|
>
|
|
{item}
|
|
</View>
|
|
))}
|
|
</View>
|
|
</View>
|
|
)}
|
|
|
|
{/* 搜索结果 */}
|
|
{keywords && (
|
|
<View className="search-results">
|
|
{/* 结果统计 */}
|
|
<View className="result-header">
|
|
找到 {total} 件相关商品
|
|
</View>
|
|
|
|
{/* 商品列表 */}
|
|
{loading && page === 1 ? (
|
|
<View className="loading-wrapper">
|
|
<Loading>搜索中...</Loading>
|
|
</View>
|
|
) : goodsList.length > 0 ? (
|
|
<div className={'py-3'}>
|
|
<div className={'flex flex-col justify-between items-center rounded-lg px-2'}>
|
|
<InfiniteLoading
|
|
hasMore={hasMore}
|
|
// @ts-ignore
|
|
onLoadMore={loadMore}
|
|
loadingText="加载中..."
|
|
loadMoreText="没有更多了"
|
|
>
|
|
{goodsList.map((item) => (
|
|
<GoodsItem key={item.goodsId} goods={item}/>
|
|
))}
|
|
</InfiniteLoading>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<Empty description="暂无相关商品"/>
|
|
)}
|
|
</View>
|
|
)}
|
|
</View>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
export default SearchPage
|