feat(反馈列表): 添加反馈状态显示和下拉刷新功能
- 在反馈列表中添加状态标签显示 - 实现下拉刷新功能 - 将模拟数据替换为真实API调用 - 更新相关样式和字段映射
Showing
3 changed files
with
95 additions
and
70 deletions
| ... | @@ -38,6 +38,12 @@ | ... | @@ -38,6 +38,12 @@ |
| 38 | color: #999; | 38 | color: #999; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | + .header-right { | ||
| 42 | + display: flex; | ||
| 43 | + align-items: center; | ||
| 44 | + gap: 12rpx; | ||
| 45 | + } | ||
| 46 | + | ||
| 41 | .feedback-type { | 47 | .feedback-type { |
| 42 | background: #fb923c; | 48 | background: #fb923c; |
| 43 | color: #fff; | 49 | color: #fff; |
| ... | @@ -46,6 +52,25 @@ | ... | @@ -46,6 +52,25 @@ |
| 46 | font-size: 22rpx; | 52 | font-size: 22rpx; |
| 47 | font-weight: 500; | 53 | font-weight: 500; |
| 48 | } | 54 | } |
| 55 | + | ||
| 56 | + .feedback-status { | ||
| 57 | + padding: 6rpx 12rpx; | ||
| 58 | + border-radius: 16rpx; | ||
| 59 | + font-size: 20rpx; | ||
| 60 | + font-weight: 500; | ||
| 61 | + | ||
| 62 | + &.status-pending { | ||
| 63 | + background: #fef3c7; | ||
| 64 | + color: #d97706; | ||
| 65 | + border: 1rpx solid #fbbf24; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + &.status-processed { | ||
| 69 | + background: #d1fae5; | ||
| 70 | + color: #059669; | ||
| 71 | + border: 1rpx solid #34d399; | ||
| 72 | + } | ||
| 73 | + } | ||
| 49 | } | 74 | } |
| 50 | 75 | ||
| 51 | .feedback-content { | 76 | .feedback-content { | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-19 14:11:06 | 2 | * @Date: 2022-09-19 14:11:06 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-07-17 12:19:40 | 4 | + * @LastEditTime: 2025-07-18 16:08:29 |
| 5 | * @FilePath: /jgdl/src/pages/feedBackList/index.vue | 5 | * @FilePath: /jgdl/src/pages/feedBackList/index.vue |
| 6 | * @Description: 意见反馈列表页面 | 6 | * @Description: 意见反馈列表页面 |
| 7 | --> | 7 | --> |
| ... | @@ -14,6 +14,10 @@ | ... | @@ -14,6 +14,10 @@ |
| 14 | :style="scrollStyle" | 14 | :style="scrollStyle" |
| 15 | @scrolltolower="loadMore" | 15 | @scrolltolower="loadMore" |
| 16 | :lower-threshold="50" | 16 | :lower-threshold="50" |
| 17 | + :refresher-enabled="true" | ||
| 18 | + :refresher-triggered="refreshing" | ||
| 19 | + @refresherrefresh="onRefresh" | ||
| 20 | + @refresherrestore="onRefreshRestore" | ||
| 17 | > | 21 | > |
| 18 | <!-- 反馈列表 --> | 22 | <!-- 反馈列表 --> |
| 19 | <view class="feedback-list" v-if="feedbackList.length > 0"> | 23 | <view class="feedback-list" v-if="feedbackList.length > 0"> |
| ... | @@ -22,10 +26,13 @@ | ... | @@ -22,10 +26,13 @@ |
| 22 | :key="index" | 26 | :key="index" |
| 23 | class="feedback-card" | 27 | class="feedback-card" |
| 24 | > | 28 | > |
| 25 | - <!-- 卡片头部:时间和类型 --> | 29 | + <!-- 卡片头部:时间、类型和状态 --> |
| 26 | <view class="card-header"> | 30 | <view class="card-header"> |
| 27 | - <view class="feedback-time">{{ formatTime(item.created_at) }}</view> | 31 | + <view class="feedback-time">{{ item.created_time }}</view> |
| 28 | - <view class="feedback-type">{{ getCategoryName(item.category) }}</view> | 32 | + <view class="header-right"> |
| 33 | + <view class="feedback-type">{{ getCategoryName(item.category) }}</view> | ||
| 34 | + <view class="feedback-status" :class="getStatusClass(item.status)">{{ getStatusText(item.status) }}</view> | ||
| 35 | + </view> | ||
| 29 | </view> | 36 | </view> |
| 30 | 37 | ||
| 31 | <!-- 反馈内容 --> | 38 | <!-- 反馈内容 --> |
| ... | @@ -52,13 +59,13 @@ | ... | @@ -52,13 +59,13 @@ |
| 52 | </view> | 59 | </view> |
| 53 | 60 | ||
| 54 | <!-- 回复内容 --> | 61 | <!-- 回复内容 --> |
| 55 | - <view class="reply-section" v-if="item.reply_content"> | 62 | + <view class="reply-section" v-if="item.reply"> |
| 56 | <view class="reply-header"> | 63 | <view class="reply-header"> |
| 57 | <text class="reply-label">回复内容:</text> | 64 | <text class="reply-label">回复内容:</text> |
| 58 | - <text class="reply-time">{{ formatTime(item.reply_time) }}</text> | 65 | + <text class="reply-time">{{ item.reply_time }}</text> |
| 59 | </view> | 66 | </view> |
| 60 | <view class="reply-content"> | 67 | <view class="reply-content"> |
| 61 | - <text class="reply-text">{{ item.reply_content }}</text> | 68 | + <text class="reply-text">{{ item.reply }}</text> |
| 62 | </view> | 69 | </view> |
| 63 | </view> | 70 | </view> |
| 64 | </view> | 71 | </view> |
| ... | @@ -103,8 +110,9 @@ | ... | @@ -103,8 +110,9 @@ |
| 103 | import { ref, computed, onMounted } from 'vue' | 110 | import { ref, computed, onMounted } from 'vue' |
| 104 | import Taro from '@tarojs/taro' | 111 | import Taro from '@tarojs/taro' |
| 105 | import { Toast } from '@nutui/nutui-taro' | 112 | import { Toast } from '@nutui/nutui-taro' |
| 106 | -// import { getFeedbackListAPI } from '@/api/other' | ||
| 107 | import './index.less' | 113 | import './index.less' |
| 114 | +// 导入接口 | ||
| 115 | +import { getFeedbackListAPI } from '@/api/other' | ||
| 108 | 116 | ||
| 109 | // 反馈类型映射 | 117 | // 反馈类型映射 |
| 110 | const categoryMap = { | 118 | const categoryMap = { |
| ... | @@ -161,6 +169,27 @@ const getCategoryName = (category) => { | ... | @@ -161,6 +169,27 @@ const getCategoryName = (category) => { |
| 161 | } | 169 | } |
| 162 | 170 | ||
| 163 | /** | 171 | /** |
| 172 | + * 获取状态文本 | ||
| 173 | + */ | ||
| 174 | +const getStatusText = (status) => { | ||
| 175 | + const statusMap = { | ||
| 176 | + 3: '待处理', | ||
| 177 | + 5: '已处理' | ||
| 178 | + } | ||
| 179 | + return statusMap[status] || '未知状态' | ||
| 180 | +} | ||
| 181 | + | ||
| 182 | +/** | ||
| 183 | + * 获取状态样式类 | ||
| 184 | + */ | ||
| 185 | +const getStatusClass = (status) => { | ||
| 186 | + return { | ||
| 187 | + 'status-pending': status === 3, | ||
| 188 | + 'status-processed': status === 5 | ||
| 189 | + } | ||
| 190 | +} | ||
| 191 | + | ||
| 192 | +/** | ||
| 164 | * 格式化时间 | 193 | * 格式化时间 |
| 165 | */ | 194 | */ |
| 166 | const formatTime = (timestamp) => { | 195 | const formatTime = (timestamp) => { |
| ... | @@ -175,7 +204,7 @@ const formatTime = (timestamp) => { | ... | @@ -175,7 +204,7 @@ const formatTime = (timestamp) => { |
| 175 | } | 204 | } |
| 176 | 205 | ||
| 177 | /** | 206 | /** |
| 178 | - * 获取反馈列表数据 - 使用Mock数据 | 207 | + * 获取反馈列表数据 - 使用真实API |
| 179 | */ | 208 | */ |
| 180 | const getFeedbackList = async (isRefresh = false) => { | 209 | const getFeedbackList = async (isRefresh = false) => { |
| 181 | if (loading.value) return | 210 | if (loading.value) return |
| ... | @@ -183,74 +212,38 @@ const getFeedbackList = async (isRefresh = false) => { | ... | @@ -183,74 +212,38 @@ const getFeedbackList = async (isRefresh = false) => { |
| 183 | loading.value = true | 212 | loading.value = true |
| 184 | 213 | ||
| 185 | try { | 214 | try { |
| 186 | - // Mock数据 | 215 | + const page = isRefresh ? 0 : currentPage.value |
| 187 | - const mockData = [ | 216 | + const params = { |
| 188 | - { | 217 | + page: page, |
| 189 | - id: 1, | 218 | + limit: pageSize.value |
| 190 | - category: '1', | 219 | + } |
| 191 | - note: '希望能增加夜间模式功能,这样在晚上使用时眼睛会更舒服一些。', | ||
| 192 | - images: ['https://picsum.photos/200/200?random=1', 'https://picsum.photos/200/200?random=2'], | ||
| 193 | - contact: '138****8888', | ||
| 194 | - created_at: Math.floor(Date.now() / 1000) - 86400, | ||
| 195 | - reply_content: '感谢您的建议,我们已将夜间模式功能加入开发计划,预计下个版本上线。', | ||
| 196 | - reply_time: Math.floor(Date.now() / 1000) - 3600 | ||
| 197 | - }, | ||
| 198 | - { | ||
| 199 | - id: 2, | ||
| 200 | - category: '3', | ||
| 201 | - note: '首页的搜索框位置有点偏上,建议调整到更容易点击的位置。', | ||
| 202 | - images: [], | ||
| 203 | - contact: 'wechat_user123', | ||
| 204 | - created_at: Math.floor(Date.now() / 1000) - 172800, | ||
| 205 | - reply_content: null, | ||
| 206 | - reply_time: null | ||
| 207 | - }, | ||
| 208 | - { | ||
| 209 | - id: 3, | ||
| 210 | - category: '5', | ||
| 211 | - note: '发现有些车辆信息显示不完整,价格和配置信息缺失。', | ||
| 212 | - images: ['https://picsum.photos/200/200?random=3'], | ||
| 213 | - contact: '159****6666', | ||
| 214 | - created_at: Math.floor(Date.now() / 1000) - 259200, | ||
| 215 | - reply_content: '我们已经修复了车辆信息显示问题,感谢您的反馈!', | ||
| 216 | - reply_time: Math.floor(Date.now() / 1000) - 86400 | ||
| 217 | - }, | ||
| 218 | - { | ||
| 219 | - id: 4, | ||
| 220 | - category: '7', | ||
| 221 | - note: '应用启动速度有点慢,希望能优化一下性能。', | ||
| 222 | - images: [], | ||
| 223 | - contact: null, | ||
| 224 | - created_at: Math.floor(Date.now() / 1000) - 345600, | ||
| 225 | - reply_content: null, | ||
| 226 | - reply_time: null | ||
| 227 | - } | ||
| 228 | - ] | ||
| 229 | 220 | ||
| 230 | - // 模拟网络延迟 | 221 | + const response = await getFeedbackListAPI(params) |
| 231 | - await new Promise(resolve => setTimeout(resolve, 1000)) | ||
| 232 | 222 | ||
| 233 | - const startIndex = isRefresh ? 0 : currentPage.value * pageSize.value | 223 | + if (response && response.code === 1 && response.data) { |
| 234 | - const endIndex = startIndex + pageSize.value | 224 | + const newData = response.data.list || [] |
| 235 | - const newData = mockData.slice(startIndex, endIndex) | ||
| 236 | 225 | ||
| 237 | - if (isRefresh) { | 226 | + if (isRefresh) { |
| 238 | - feedbackList.value = newData | 227 | + feedbackList.value = newData |
| 239 | - currentPage.value = 0 | 228 | + currentPage.value = 0 |
| 240 | - } else { | 229 | + } else { |
| 241 | - feedbackList.value.push(...newData) | 230 | + feedbackList.value.push(...newData) |
| 242 | - } | 231 | + } |
| 243 | 232 | ||
| 244 | - // 判断是否还有更多数据 | 233 | + // 判断是否还有更多数据 |
| 245 | - hasMore.value = endIndex < mockData.length | 234 | + const totalLoaded = isRefresh ? newData.length : feedbackList.value.length |
| 235 | + hasMore.value = totalLoaded < response.data.total | ||
| 246 | 236 | ||
| 247 | - if (!isRefresh) { | 237 | + if (!isRefresh) { |
| 248 | - currentPage.value++ | 238 | + currentPage.value++ |
| 239 | + } | ||
| 240 | + } else { | ||
| 241 | + console.error('API返回错误:', response) | ||
| 242 | + Toast.fail(response?.msg || '获取数据失败') | ||
| 249 | } | 243 | } |
| 250 | - | ||
| 251 | } catch (error) { | 244 | } catch (error) { |
| 252 | console.error('获取反馈列表失败:', error) | 245 | console.error('获取反馈列表失败:', error) |
| 253 | - Toast.fail(error.message || '获取数据失败') | 246 | + Toast.fail(error.message || '网络错误,请重试') |
| 254 | } finally { | 247 | } finally { |
| 255 | loading.value = false | 248 | loading.value = false |
| 256 | refreshing.value = false | 249 | refreshing.value = false |
| ... | @@ -266,6 +259,13 @@ const onRefresh = () => { | ... | @@ -266,6 +259,13 @@ const onRefresh = () => { |
| 266 | } | 259 | } |
| 267 | 260 | ||
| 268 | /** | 261 | /** |
| 262 | + * 下拉刷新恢复 | ||
| 263 | + */ | ||
| 264 | +const onRefreshRestore = () => { | ||
| 265 | + refreshing.value = false | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +/** | ||
| 269 | * 加载更多 | 269 | * 加载更多 |
| 270 | */ | 270 | */ |
| 271 | const loadMore = () => { | 271 | const loadMore = () => { | ... | ... |
| ... | @@ -169,7 +169,7 @@ const onHelpCenter = () => { | ... | @@ -169,7 +169,7 @@ const onHelpCenter = () => { |
| 169 | */ | 169 | */ |
| 170 | const onFeedback = () => { | 170 | const onFeedback = () => { |
| 171 | Taro.navigateTo({ | 171 | Taro.navigateTo({ |
| 172 | - url: '/pages/feedBack/index' | 172 | + url: '/pages/feedBackList/index' |
| 173 | }) | 173 | }) |
| 174 | } | 174 | } |
| 175 | 175 | ... | ... |
-
Please register or login to post a comment