index.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import React, { useState, useEffect } from 'react'
  2. import { View, Text, ScrollView } from '@tarojs/components'
  3. import Taro from '@tarojs/taro'
  4. import { Navbar } from '@/components/ui/navbar'
  5. import TDesignSearch from '@/components/tdesign/search'
  6. import './index.css'
  7. // 本地存储搜索历史
  8. const SEARCH_HISTORY_KEY = 'search_history'
  9. const SearchPage: React.FC = () => {
  10. const [searchValue, setSearchValue] = useState('')
  11. const [historyWords, setHistoryWords] = useState<string[]>([])
  12. const [popularWords, setPopularWords] = useState<string[]>([])
  13. // 获取搜索历史
  14. const getSearchHistory = (): string[] => {
  15. try {
  16. const history = Taro.getStorageSync(SEARCH_HISTORY_KEY)
  17. return Array.isArray(history) ? history : []
  18. } catch (error) {
  19. console.error('获取搜索历史失败:', error)
  20. return []
  21. }
  22. }
  23. // 保存搜索历史
  24. const saveSearchHistory = (keyword: string) => {
  25. try {
  26. const history = getSearchHistory()
  27. // 移除重复的关键词
  28. const filteredHistory = history.filter(word => word !== keyword)
  29. // 将新关键词添加到前面
  30. const newHistory = [keyword, ...filteredHistory]
  31. // 限制历史记录数量
  32. const limitedHistory = newHistory.slice(0, 10)
  33. Taro.setStorageSync(SEARCH_HISTORY_KEY, limitedHistory)
  34. setHistoryWords(limitedHistory)
  35. } catch (error) {
  36. console.error('保存搜索历史失败:', error)
  37. }
  38. }
  39. // 清空搜索历史
  40. const clearSearchHistory = () => {
  41. try {
  42. Taro.removeStorageSync(SEARCH_HISTORY_KEY)
  43. setHistoryWords([])
  44. } catch (error) {
  45. console.error('清空搜索历史失败:', error)
  46. }
  47. }
  48. // 获取热门搜索词(模拟数据)
  49. const getPopularSearchWords = (): string[] => {
  50. return [
  51. '手机',
  52. '笔记本电脑',
  53. '耳机',
  54. '智能手表',
  55. '平板电脑',
  56. '数码相机',
  57. '游戏机',
  58. '智能家居'
  59. ]
  60. }
  61. // 页面显示时加载数据
  62. useEffect(() => {
  63. setHistoryWords(getSearchHistory())
  64. setPopularWords(getPopularSearchWords())
  65. }, [])
  66. // 处理搜索提交
  67. const handleSubmit = (value: string) => {
  68. if (!value.trim()) return
  69. // 保存搜索历史
  70. saveSearchHistory(value.trim())
  71. // 跳转到搜索结果页面
  72. Taro.navigateTo({
  73. url: `/pages/search-result/index?keyword=${encodeURIComponent(value)}`
  74. })
  75. }
  76. // 点击历史搜索项
  77. const handleHistoryTap = (word: string) => {
  78. setSearchValue(word)
  79. // 保存搜索历史
  80. saveSearchHistory(word)
  81. Taro.navigateTo({
  82. url: `/pages/search-result/index?keyword=${encodeURIComponent(word)}`
  83. })
  84. }
  85. // 点击热门搜索项
  86. const handlePopularTap = (word: string) => {
  87. setSearchValue(word)
  88. // 保存搜索历史
  89. saveSearchHistory(word)
  90. Taro.navigateTo({
  91. url: `/pages/search-result/index?keyword=${encodeURIComponent(word)}`
  92. })
  93. }
  94. // 清空搜索历史
  95. const handleClearHistory = () => {
  96. clearSearchHistory()
  97. }
  98. return (
  99. <View className="search-page">
  100. <Navbar
  101. title="搜索"
  102. leftIcon="i-heroicons-chevron-left-20-solid"
  103. onClickLeft={() => Taro.navigateBack()}
  104. className="bg-white"
  105. />
  106. <ScrollView className="search-page-content" scrollY>
  107. {/* 搜索栏 */}
  108. <View className="search-input-container">
  109. <TDesignSearch
  110. placeholder="搜索商品..."
  111. shape="round"
  112. value={searchValue}
  113. onChange={(value) => setSearchValue(value)}
  114. onSubmit={() => handleSubmit(searchValue)}
  115. onClear={() => setSearchValue('')}
  116. />
  117. </View>
  118. {/* 搜索历史 */}
  119. {historyWords.length > 0 && (
  120. <View className="search-section">
  121. <View className="search-header">
  122. <Text className="search-title">搜索历史</Text>
  123. <Text
  124. className="search-clear"
  125. onClick={handleClearHistory}
  126. data-testid="clear-history"
  127. >
  128. 清空
  129. </Text>
  130. </View>
  131. <View className="search-content">
  132. {historyWords.map((word: string, index: number) => (
  133. <View
  134. key={index}
  135. className="search-item"
  136. onClick={() => handleHistoryTap(word)}
  137. data-testid="history-item"
  138. >
  139. <Text className="search-item-text">{word}</Text>
  140. </View>
  141. ))}
  142. </View>
  143. </View>
  144. )}
  145. {/* 热门搜索 */}
  146. {popularWords.length > 0 && (
  147. <View className="search-section">
  148. <View className="search-header">
  149. <Text className="search-title">热门搜索</Text>
  150. </View>
  151. <View className="search-content">
  152. {popularWords.map((word: string, index: number) => (
  153. <View
  154. key={index}
  155. className="search-item"
  156. onClick={() => handlePopularTap(word)}
  157. data-testid="popular-item"
  158. >
  159. <Text className="search-item-text">{word}</Text>
  160. </View>
  161. ))}
  162. </View>
  163. </View>
  164. )}
  165. {/* 空状态 */}
  166. {historyWords.length === 0 && popularWords.length === 0 && (
  167. <View className="empty-state" data-testid="empty-state">
  168. <View className="i-heroicons-magnifying-glass-20-solid empty-icon" />
  169. <Text className="empty-text">暂无搜索记录</Text>
  170. <Text className="empty-subtext">输入关键词搜索商品</Text>
  171. </View>
  172. )}
  173. </ScrollView>
  174. </View>
  175. )
  176. }
  177. export default SearchPage