hookehuyr

refactor: 迁移所有剩余页面到 LoadMoreList 组件

- message 页面:添加下拉刷新功能
- product-center 页面:保留搜索、tabs、计划书弹窗
- material-list 页面:保留分类缓存、搜索防抖
- search 页面:保留双列表、自动 tab 切换、三种状态

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This diff is collapsed. Click to expand it.
1 +<!--
2 + * @Date: 2026-02-08
3 + * @Description: 我的消息页 - 使用 LoadMoreList 组件重构版本
4 +-->
1 <template> 5 <template>
2 - <view class="min-h-screen bg-[#F9FAFB] pb-safe"> 6 + <LoadMoreList
7 + :list="currentList"
8 + :page="currentPage"
9 + :page-size="pageSize"
10 + :has-more="hasMore"
11 + :loading="loading"
12 + :loading-more="loadingMore"
13 + :enable-pull-down-refresh="true"
14 + key-field="id"
15 + @load-more="handleLoadMore"
16 + @refresh="handleRefresh"
17 + >
18 + <!-- 头部 -->
19 + <template #header>
3 <NavHeader title="我的消息" /> 20 <NavHeader title="我的消息" />
21 + </template>
4 22
5 - <!-- 列表区域 --> 23 + <!-- 列表项 -->
6 - <view class="p-4"> 24 + <template #item="{ item }">
7 - <template v-if="messageList.length > 0">
8 <view 25 <view
9 - v-for="item in messageList" 26 + class="message-item bg-white rounded-xl p-4 mb-3 shadow-sm active:opacity-70 transition-opacity"
10 - :key="item.id"
11 - class="bg-white rounded-xl p-4 mb-3 shadow-sm active:opacity-70 transition-opacity"
12 @tap="handleItemClick(item)" 27 @tap="handleItemClick(item)"
13 > 28 >
14 <view class="flex justify-between items-start mb-2"> 29 <view class="flex justify-between items-start mb-2">
...@@ -26,29 +41,20 @@ ...@@ -26,29 +41,20 @@
26 {{ item.intro || item.content || '暂无简介' }} 41 {{ item.intro || item.content || '暂无简介' }}
27 </view> 42 </view>
28 </view> 43 </view>
29 -
30 - <!-- 加载更多/没有更多 -->
31 - <view class="py-4 text-center text-[24rpx] text-gray-400">
32 - <text v-if="loading">加载中...</text>
33 - <text v-else-if="!hasMore">没有更多了</text>
34 - <text v-else>上拉加载更多</text>
35 - </view>
36 </template> 44 </template>
37 45
38 <!-- 空状态 --> 46 <!-- 空状态 -->
39 - <nut-empty 47 + <template #empty>
40 - v-else-if="!loading && messageList.length === 0" 48 + <nut-empty description="暂无消息" image="empty" />
41 - description="暂无消息" 49 + </template>
42 - image="empty" 50 + </LoadMoreList>
43 - />
44 - </view>
45 - </view>
46 </template> 51 </template>
47 52
48 <script setup> 53 <script setup>
49 import { ref } from 'vue' 54 import { ref } from 'vue'
50 -import { useLoad, usePullDownRefresh, useReachBottom, stopPullDownRefresh } from '@tarojs/taro' 55 +import { useLoad } from '@tarojs/taro'
51 import { useGo } from '@/hooks/useGo' 56 import { useGo } from '@/hooks/useGo'
57 +import LoadMoreList from '@/components/LoadMoreList'
52 import NavHeader from '@/components/NavHeader.vue' 58 import NavHeader from '@/components/NavHeader.vue'
53 import { myListAPI } from '@/api/news' 59 import { myListAPI } from '@/api/news'
54 import { mockMessageListAPI } from '@/utils/mockData' 60 import { mockMessageListAPI } from '@/utils/mockData'
...@@ -58,91 +64,165 @@ const USE_MOCK_DATA = process.env.NODE_ENV === 'development' ...@@ -58,91 +64,165 @@ const USE_MOCK_DATA = process.env.NODE_ENV === 'development'
58 64
59 const go = useGo() 65 const go = useGo()
60 66
61 -const messageList = ref([]) 67 +/**
62 -const page = ref(1) 68 + * 当前列表数据
63 -const limit = ref(10) 69 + * @type {Ref<Array<any>>}
70 + */
71 +const currentList = ref([])
72 +
73 +/**
74 + * 当前页码(从1开始)
75 + * @type {Ref<number>}
76 + */
77 +const currentPage = ref(1)
78 +
79 +/**
80 + * 每页数量
81 + * @type {number}
82 + */
83 +const pageSize = 10
84 +
85 +/**
86 + * 是否还有更多数据
87 + * @type {Ref<boolean>}
88 + */
64 const hasMore = ref(true) 89 const hasMore = ref(true)
65 -const loading = ref(false)
66 90
67 /** 91 /**
68 - * @description 加载消息列表 92 + * 首次加载状态
69 - * @param {boolean} refresh 是否刷新 93 + * @type {Ref<boolean>}
70 */ 94 */
71 -const fetchMessageList = async (refresh = false) => { 95 +const loading = ref(false)
72 - if (loading.value) return
73 96
74 - if (refresh) { 97 +/**
75 - page.value = 1 98 + * 加载更多状态
76 - hasMore.value = true 99 + * @type {Ref<boolean>}
77 - } else if (!hasMore.value) { 100 + */
78 - return 101 +const loadingMore = ref(false)
79 - }
80 102
103 +/**
104 + * 获取消息列表
105 + *
106 + * @param {Object} params - 请求参数
107 + * @param {number} params.page - 页码(从1开始)
108 + * @param {number} params.limit - 每页数量
109 + * @param {boolean} isLoadMore - 是否为加载更多
110 + * @returns {Promise<void>}
111 + */
112 +const fetchMessageList = async (params = {}, isLoadMore = false) => {
113 + try {
114 + // 如果是加载更多,使用 loadingMore 状态,否则使用 loading 状态
115 + if (isLoadMore) {
116 + loadingMore.value = true
117 + } else {
81 loading.value = true 118 loading.value = true
119 + }
82 120
83 - try { 121 + console.log('[Message] 请求参数:', params)
84 console.log('[Message] 使用 Mock 数据:', USE_MOCK_DATA) 122 console.log('[Message] 使用 Mock 数据:', USE_MOCK_DATA)
85 123
86 // 根据开关选择使用真实 API 或 Mock 数据 124 // 根据开关选择使用真实 API 或 Mock 数据
87 const res = USE_MOCK_DATA 125 const res = USE_MOCK_DATA
88 - ? await mockMessageListAPI({ 126 + ? await mockMessageListAPI(params)
89 - page: page.value, 127 + : await myListAPI(params)
90 - limit: limit.value 128 +
91 - }) 129 + if (res.code === 1 && res.data) {
92 - : await myListAPI({ 130 + console.log('[Message] 数据:', res.data)
93 - page: page.value, 131 +
94 - limit: limit.value 132 + // 处理列表数据
95 - }) 133 + if (res.data.list?.length) {
96 - 134 + const listData = res.data.list
97 - if (res.code === 1) { 135 +
98 - const list = res.data?.list || [] 136 + if (isLoadMore) {
99 - 137 + // 加载更多:追加数据
100 - if (refresh) { 138 + currentList.value = [...currentList.value, ...listData]
101 - messageList.value = list
102 } else { 139 } else {
103 - messageList.value = [...messageList.value, ...list] 140 + // 首次加载或刷新:替换数据
141 + currentList.value = listData
104 } 142 }
105 143
106 - if (list.length < limit.value) { 144 + // 判断是否还有更多数据
145 + // 如果返回的数据量少于请求的量,说明没有更多了
146 + hasMore.value = listData.length >= params.limit
147 + } else {
148 + // 没有数据了
149 + if (isLoadMore) {
107 hasMore.value = false 150 hasMore.value = false
108 } else { 151 } else {
109 - page.value++ 152 + currentList.value = []
153 + }
110 } 154 }
155 + } else {
156 + console.error('[Message] API 返回错误:', res.msg)
111 } 157 }
112 - } catch (err) { 158 + } catch (error) {
113 - console.error('获取消息列表失败:', err) 159 + console.error('[Message] 获取消息列表失败:', error)
114 } finally { 160 } finally {
161 + if (isLoadMore) {
162 + loadingMore.value = false
163 + } else {
115 loading.value = false 164 loading.value = false
116 - if (refresh) {
117 - stopPullDownRefresh()
118 } 165 }
119 } 166 }
120 } 167 }
121 168
122 /** 169 /**
123 - * @description 跳转到详情页 170 + * 页面加载时获取数据
124 - * @param {Object} item 消息对象
125 */ 171 */
126 -const handleItemClick = (item) => { 172 +useLoad(async (options) => {
127 - go('/pages/message-detail/index', { id: item.id }) 173 + console.log('[Message] 页面参数:', options)
128 -}
129 174
130 -// 页面加载 175 + // 重置分页状态
131 -useLoad(() => { 176 + currentPage.value = 1
132 - fetchMessageList(true) 177 + hasMore.value = true
133 -})
134 178
135 -// 下拉刷新 179 + // 获取消息列表
136 -usePullDownRefresh(() => { 180 + await fetchMessageList({ page: 1, limit: pageSize })
137 - fetchMessageList(true)
138 }) 181 })
139 182
140 -// 上拉加载更多 183 +/**
141 -useReachBottom(() => { 184 + * 处理加载更多事件
142 - fetchMessageList() 185 + *
143 -}) 186 + * @param {number} page - 下一页页码
187 + * @returns {Promise<void>}
188 + */
189 +const handleLoadMore = async (page) => {
190 + console.log('[Message] 加载更多,页码:', page)
191 +
192 + // 更新页码
193 + currentPage.value = page
194 +
195 + // 加载下一页数据
196 + await fetchMessageList(
197 + { page: page, limit: pageSize },
198 + true // 标记为加载更多
199 + )
200 +}
201 +
202 +/**
203 + * 处理下拉刷新事件
204 + */
205 +const handleRefresh = async () => {
206 + console.log('[Message] 下拉刷新')
207 +
208 + // 重置分页状态
209 + currentPage.value = 1
210 + hasMore.value = true
211 +
212 + // 刷新数据
213 + await fetchMessageList({ page: 1, limit: pageSize })
214 +}
215 +
216 +/**
217 + * 跳转到详情页
218 + *
219 + * @param {Object} item - 消息对象
220 + */
221 +const handleItemClick = (item) => {
222 + go('/pages/message-detail/index', { id: item.id })
223 +}
144 </script> 224 </script>
145 225
146 <style lang="less"> 226 <style lang="less">
147 -/* Scoped styles if needed */ 227 +/* LoadMoreList 组件已内置样式,此处无需额外样式 */
148 </style> 228 </style>
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.