feat(反馈): 新增意见反馈列表页面及功能
添加反馈列表页面,包含以下功能: 1. 展示用户反馈历史记录 2. 支持图片预览和分页加载 3. 添加底部反馈按钮跳转 4. 更新API接口和组件类型定义 5. 优化反馈提交后的返回逻辑
Showing
8 changed files
with
582 additions
and
3 deletions
| ... | @@ -22,6 +22,7 @@ declare module 'vue' { | ... | @@ -22,6 +22,7 @@ declare module 'vue' { |
| 22 | NutFormItem: typeof import('@nutui/nutui-taro')['FormItem'] | 22 | NutFormItem: typeof import('@nutui/nutui-taro')['FormItem'] |
| 23 | NutImagePreview: typeof import('@nutui/nutui-taro')['ImagePreview'] | 23 | NutImagePreview: typeof import('@nutui/nutui-taro')['ImagePreview'] |
| 24 | NutInput: typeof import('@nutui/nutui-taro')['Input'] | 24 | NutInput: typeof import('@nutui/nutui-taro')['Input'] |
| 25 | + NutLoading: typeof import('@nutui/nutui-taro')['Loading'] | ||
| 25 | NutMenu: typeof import('@nutui/nutui-taro')['Menu'] | 26 | NutMenu: typeof import('@nutui/nutui-taro')['Menu'] |
| 26 | NutMenuItem: typeof import('@nutui/nutui-taro')['MenuItem'] | 27 | NutMenuItem: typeof import('@nutui/nutui-taro')['MenuItem'] |
| 27 | NutOverlay: typeof import('@nutui/nutui-taro')['Overlay'] | 28 | NutOverlay: typeof import('@nutui/nutui-taro')['Overlay'] | ... | ... |
| ... | @@ -12,6 +12,7 @@ const Api = { | ... | @@ -12,6 +12,7 @@ const Api = { |
| 12 | GET_BRANDS_MODELS: '/srv/?a=common&t=get_brands_models', | 12 | GET_BRANDS_MODELS: '/srv/?a=common&t=get_brands_models', |
| 13 | GET_VEHICLE_BRANDS: '/srv/?a=common&t=get_vehicle_brands', | 13 | GET_VEHICLE_BRANDS: '/srv/?a=common&t=get_vehicle_brands', |
| 14 | SUBMIT_FEEDBACK: '/srv/?a=feedback&t=add', | 14 | SUBMIT_FEEDBACK: '/srv/?a=feedback&t=add', |
| 15 | + GET_FEEDBACK_LIST: '/srv/?a=feedback&t=list', | ||
| 15 | GET_FAVORITE_LIST: '/srv/?a=favorite&t=list', | 16 | GET_FAVORITE_LIST: '/srv/?a=favorite&t=list', |
| 16 | TOGGLE_FAVORITE_ADD: '/srv/?a=favorite&t=add', | 17 | TOGGLE_FAVORITE_ADD: '/srv/?a=favorite&t=add', |
| 17 | TOGGLE_FAVORITE_DEL: '/srv/?a=favorite&t=del', | 18 | TOGGLE_FAVORITE_DEL: '/srv/?a=favorite&t=del', |
| ... | @@ -56,6 +57,15 @@ export const toggleFavoriteAddAPI = (params) => fn(fetch.post(Api.TOGGLE_FAVORIT | ... | @@ -56,6 +57,15 @@ export const toggleFavoriteAddAPI = (params) => fn(fetch.post(Api.TOGGLE_FAVORIT |
| 56 | export const toggleFavoriteDelAPI = (params) => fn(fetch.post(Api.TOGGLE_FAVORITE_DEL, params)); | 57 | export const toggleFavoriteDelAPI = (params) => fn(fetch.post(Api.TOGGLE_FAVORITE_DEL, params)); |
| 57 | 58 | ||
| 58 | /** | 59 | /** |
| 60 | + * @description: 获取反馈列表 | ||
| 61 | + * @param {*} params | ||
| 62 | + * @param {number} params.page - 页码,从0开始 | ||
| 63 | + * @param {number} params.limit - 每页数量 | ||
| 64 | + * @returns | ||
| 65 | + */ | ||
| 66 | +export const getFeedbackListAPI = (params) => fn(fetch.get(Api.GET_FEEDBACK_LIST, params)); | ||
| 67 | + | ||
| 68 | +/** | ||
| 59 | * @description: 提交反馈 | 69 | * @description: 提交反馈 |
| 60 | * @param {*} params | 70 | * @param {*} params |
| 61 | * @param {string} params.category - 反馈类型(1=功能建议,3=界面设计,5=车辆信息, 7=其他) | 71 | * @param {string} params.category - 反馈类型(1=功能建议,3=界面设计,5=车辆信息, 7=其他) | ... | ... |
| ... | @@ -25,6 +25,7 @@ export default { | ... | @@ -25,6 +25,7 @@ export default { |
| 25 | 'pages/myOrders/index', | 25 | 'pages/myOrders/index', |
| 26 | 'pages/myAuthCar/index', | 26 | 'pages/myAuthCar/index', |
| 27 | 'pages/feedBack/index', | 27 | 'pages/feedBack/index', |
| 28 | + 'pages/feedBackList/index', | ||
| 28 | 'pages/helpCenter/index', | 29 | 'pages/helpCenter/index', |
| 29 | 'pages/search/index', | 30 | 'pages/search/index', |
| 30 | 'pages/recommendCarList/index', | 31 | 'pages/recommendCarList/index', | ... | ... |
| 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-15 13:14:50 | 4 | + * @LastEditTime: 2025-07-17 12:22:47 |
| 5 | * @FilePath: /jgdl/src/pages/feedBack/index.vue | 5 | * @FilePath: /jgdl/src/pages/feedBack/index.vue |
| 6 | * @Description: 意见反馈页面 | 6 | * @Description: 意见反馈页面 |
| 7 | --> | 7 | --> |
| ... | @@ -329,6 +329,11 @@ const closeSuccessModal = () => { | ... | @@ -329,6 +329,11 @@ const closeSuccessModal = () => { |
| 329 | feedbackText.value = '' | 329 | feedbackText.value = '' |
| 330 | contactInfo.value = '' | 330 | contactInfo.value = '' |
| 331 | uploadedImages.value = [] | 331 | uploadedImages.value = [] |
| 332 | + | ||
| 333 | + // 返回上一页 | ||
| 334 | + Taro.navigateBack({ | ||
| 335 | + delta: 1 | ||
| 336 | + }) | ||
| 332 | } | 337 | } |
| 333 | </script> | 338 | </script> |
| 334 | 339 | ... | ... |
src/pages/feedBackList/index.config.js
0 → 100755
src/pages/feedBackList/index.less
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-09-19 14:11:06 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-07-17 11:23:10 | ||
| 5 | + * @FilePath: /jgdl/src/pages/feedBackList/index.less | ||
| 6 | + * @Description: 意见反馈列表页面样式 | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | +.feedback-list-page { | ||
| 10 | + position: relative; | ||
| 11 | + height: 100vh; | ||
| 12 | + background-color: #f5f5f5; | ||
| 13 | + | ||
| 14 | + .scroll-view { | ||
| 15 | + padding: 20rpx; | ||
| 16 | + box-sizing: border-box; | ||
| 17 | + overflow-y: auto; | ||
| 18 | + -webkit-overflow-scrolling: touch; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + .feedback-list { | ||
| 22 | + .feedback-card { | ||
| 23 | + background: #fff; | ||
| 24 | + border-radius: 16rpx; | ||
| 25 | + padding: 24rpx; | ||
| 26 | + margin-bottom: 20rpx; | ||
| 27 | + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06); | ||
| 28 | + border: 1rpx solid #f0f0f0; | ||
| 29 | + | ||
| 30 | + .card-header { | ||
| 31 | + display: flex; | ||
| 32 | + justify-content: space-between; | ||
| 33 | + align-items: center; | ||
| 34 | + margin-bottom: 16rpx; | ||
| 35 | + | ||
| 36 | + .feedback-time { | ||
| 37 | + font-size: 24rpx; | ||
| 38 | + color: #999; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + .feedback-type { | ||
| 42 | + background: #fb923c; | ||
| 43 | + color: #fff; | ||
| 44 | + padding: 8rpx 16rpx; | ||
| 45 | + border-radius: 20rpx; | ||
| 46 | + font-size: 22rpx; | ||
| 47 | + font-weight: 500; | ||
| 48 | + } | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + .feedback-content { | ||
| 52 | + margin-bottom: 16rpx; | ||
| 53 | + | ||
| 54 | + .content-text { | ||
| 55 | + font-size: 28rpx; | ||
| 56 | + color: #333; | ||
| 57 | + line-height: 1.6; | ||
| 58 | + word-break: break-all; | ||
| 59 | + } | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + .feedback-images { | ||
| 63 | + display: flex; | ||
| 64 | + flex-wrap: wrap; | ||
| 65 | + gap: 12rpx; | ||
| 66 | + margin-bottom: 16rpx; | ||
| 67 | + | ||
| 68 | + .image-item { | ||
| 69 | + width: 120rpx; | ||
| 70 | + height: 120rpx; | ||
| 71 | + border-radius: 8rpx; | ||
| 72 | + overflow: hidden; | ||
| 73 | + border: 1rpx solid #eee; | ||
| 74 | + | ||
| 75 | + .feedback-image { | ||
| 76 | + width: 100%; | ||
| 77 | + height: 100%; | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + .contact-info { | ||
| 83 | + background: #f8f9fa; | ||
| 84 | + padding: 16rpx; | ||
| 85 | + border-radius: 8rpx; | ||
| 86 | + margin-bottom: 16rpx; | ||
| 87 | + border-left: 4rpx solid #fb923c; | ||
| 88 | + | ||
| 89 | + .contact-label { | ||
| 90 | + font-size: 24rpx; | ||
| 91 | + color: #666; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + .contact-text { | ||
| 95 | + font-size: 26rpx; | ||
| 96 | + color: #333; | ||
| 97 | + font-weight: 500; | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + .reply-section { | ||
| 102 | + background: #f0f8ff; | ||
| 103 | + padding: 16rpx; | ||
| 104 | + border-radius: 8rpx; | ||
| 105 | + border-left: 4rpx solid #fb923c; | ||
| 106 | + | ||
| 107 | + .reply-header { | ||
| 108 | + display: flex; | ||
| 109 | + justify-content: space-between; | ||
| 110 | + align-items: center; | ||
| 111 | + margin-bottom: 12rpx; | ||
| 112 | + | ||
| 113 | + .reply-label { | ||
| 114 | + font-size: 24rpx; | ||
| 115 | + color: #fb923c; | ||
| 116 | + font-weight: 500; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + .reply-time { | ||
| 120 | + font-size: 22rpx; | ||
| 121 | + color: #999; | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + .reply-content { | ||
| 126 | + .reply-text { | ||
| 127 | + font-size: 26rpx; | ||
| 128 | + color: #333; | ||
| 129 | + line-height: 1.6; | ||
| 130 | + word-break: break-all; | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + // 空状态样式 | ||
| 138 | + .empty-state { | ||
| 139 | + display: flex; | ||
| 140 | + flex-direction: column; | ||
| 141 | + align-items: center; | ||
| 142 | + justify-content: center; | ||
| 143 | + padding: 120rpx 40rpx; | ||
| 144 | + text-align: center; | ||
| 145 | + | ||
| 146 | + .empty-icon { | ||
| 147 | + font-size: 120rpx; | ||
| 148 | + margin-bottom: 24rpx; | ||
| 149 | + opacity: 0.6; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + .empty-text { | ||
| 153 | + font-size: 32rpx; | ||
| 154 | + color: #666; | ||
| 155 | + margin-bottom: 12rpx; | ||
| 156 | + font-weight: 500; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + .empty-desc { | ||
| 160 | + font-size: 26rpx; | ||
| 161 | + color: #999; | ||
| 162 | + line-height: 1.5; | ||
| 163 | + } | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + // 加载状态样式 | ||
| 167 | + .loading-container { | ||
| 168 | + display: flex; | ||
| 169 | + align-items: center; | ||
| 170 | + justify-content: center; | ||
| 171 | + padding: 40rpx; | ||
| 172 | + gap: 16rpx; | ||
| 173 | + | ||
| 174 | + .loading-text { | ||
| 175 | + font-size: 26rpx; | ||
| 176 | + color: #666; | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + // 没有更多数据样式 | ||
| 181 | + .no-more-container { | ||
| 182 | + display: flex; | ||
| 183 | + align-items: center; | ||
| 184 | + justify-content: center; | ||
| 185 | + padding: 40rpx; | ||
| 186 | + | ||
| 187 | + .no-more-text { | ||
| 188 | + font-size: 24rpx; | ||
| 189 | + color: #999; | ||
| 190 | + position: relative; | ||
| 191 | + | ||
| 192 | + &::before, | ||
| 193 | + &::after { | ||
| 194 | + content: ''; | ||
| 195 | + position: absolute; | ||
| 196 | + top: 50%; | ||
| 197 | + width: 60rpx; | ||
| 198 | + height: 1rpx; | ||
| 199 | + background: #ddd; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + &::before { | ||
| 203 | + left: -80rpx; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + &::after { | ||
| 207 | + right: -80rpx; | ||
| 208 | + } | ||
| 209 | + } | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + // 底部固定按钮 | ||
| 213 | + .fixed-bottom { | ||
| 214 | + position: fixed; | ||
| 215 | + bottom: 0; | ||
| 216 | + left: 0; | ||
| 217 | + right: 0; | ||
| 218 | + background: #fff; | ||
| 219 | + padding: 20rpx 30rpx; | ||
| 220 | + padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); | ||
| 221 | + border-top: 1rpx solid #eee; | ||
| 222 | + box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.06); | ||
| 223 | + z-index: 100; | ||
| 224 | + | ||
| 225 | + .feedback-btn { | ||
| 226 | + width: 100%; | ||
| 227 | + height: 88rpx; | ||
| 228 | + background: #fb923c; | ||
| 229 | + color: #fff; | ||
| 230 | + border: none; | ||
| 231 | + border-radius: 44rpx; | ||
| 232 | + font-size: 32rpx; | ||
| 233 | + font-weight: 500; | ||
| 234 | + display: flex; | ||
| 235 | + align-items: center; | ||
| 236 | + justify-content: center; | ||
| 237 | + box-shadow: 0 4rpx 12rpx rgba(251, 146, 60, 0.3); | ||
| 238 | + transition: all 0.3s ease; | ||
| 239 | + | ||
| 240 | + &:active { | ||
| 241 | + transform: translateY(2rpx); | ||
| 242 | + box-shadow: 0 2rpx 8rpx rgba(251, 146, 60, 0.2); | ||
| 243 | + } | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/pages/feedBackList/index.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-09-19 14:11:06 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-07-17 12:19:40 | ||
| 5 | + * @FilePath: /jgdl/src/pages/feedBackList/index.vue | ||
| 6 | + * @Description: 意见反馈列表页面 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <view class="feedback-list-page"> | ||
| 10 | + <!-- 滚动视图 --> | ||
| 11 | + <scroll-view | ||
| 12 | + class="scroll-view" | ||
| 13 | + :scroll-y="true" | ||
| 14 | + :style="scrollStyle" | ||
| 15 | + @scrolltolower="loadMore" | ||
| 16 | + :lower-threshold="50" | ||
| 17 | + > | ||
| 18 | + <!-- 反馈列表 --> | ||
| 19 | + <view class="feedback-list" v-if="feedbackList.length > 0"> | ||
| 20 | + <view | ||
| 21 | + v-for="(item, index) in feedbackList" | ||
| 22 | + :key="index" | ||
| 23 | + class="feedback-card" | ||
| 24 | + > | ||
| 25 | + <!-- 卡片头部:时间和类型 --> | ||
| 26 | + <view class="card-header"> | ||
| 27 | + <view class="feedback-time">{{ formatTime(item.created_at) }}</view> | ||
| 28 | + <view class="feedback-type">{{ getCategoryName(item.category) }}</view> | ||
| 29 | + </view> | ||
| 30 | + | ||
| 31 | + <!-- 反馈内容 --> | ||
| 32 | + <view class="feedback-content"> | ||
| 33 | + <text class="content-text">{{ item.note }}</text> | ||
| 34 | + </view> | ||
| 35 | + | ||
| 36 | + <!-- 图片展示 --> | ||
| 37 | + <view class="feedback-images" v-if="item.images && item.images.length > 0"> | ||
| 38 | + <view | ||
| 39 | + v-for="(image, imgIndex) in item.images" | ||
| 40 | + :key="imgIndex" | ||
| 41 | + class="image-item" | ||
| 42 | + @click="previewImage(item.images, imgIndex)" | ||
| 43 | + > | ||
| 44 | + <image :src="image" class="feedback-image" mode="aspectFill" /> | ||
| 45 | + </view> | ||
| 46 | + </view> | ||
| 47 | + | ||
| 48 | + <!-- 联系方式 --> | ||
| 49 | + <view class="contact-info" v-if="item.contact"> | ||
| 50 | + <text class="contact-label">联系方式:</text> | ||
| 51 | + <text class="contact-text">{{ item.contact }}</text> | ||
| 52 | + </view> | ||
| 53 | + | ||
| 54 | + <!-- 回复内容 --> | ||
| 55 | + <view class="reply-section" v-if="item.reply_content"> | ||
| 56 | + <view class="reply-header"> | ||
| 57 | + <text class="reply-label">回复内容:</text> | ||
| 58 | + <text class="reply-time">{{ formatTime(item.reply_time) }}</text> | ||
| 59 | + </view> | ||
| 60 | + <view class="reply-content"> | ||
| 61 | + <text class="reply-text">{{ item.reply_content }}</text> | ||
| 62 | + </view> | ||
| 63 | + </view> | ||
| 64 | + </view> | ||
| 65 | + </view> | ||
| 66 | + | ||
| 67 | + <!-- 空状态 --> | ||
| 68 | + <view class="empty-state" v-if="!loading && feedbackList.length === 0"> | ||
| 69 | + <view class="empty-icon">📝</view> | ||
| 70 | + <view class="empty-text">暂无反馈记录</view> | ||
| 71 | + <view class="empty-desc">您还没有提交过任何反馈</view> | ||
| 72 | + </view> | ||
| 73 | + | ||
| 74 | + <!-- 加载状态 --> | ||
| 75 | + <view class="loading-container" v-if="loading"> | ||
| 76 | + <text class="loading-text">加载中...</text> | ||
| 77 | + </view> | ||
| 78 | + | ||
| 79 | + <!-- 没有更多数据 --> | ||
| 80 | + <view class="no-more-container" v-if="!hasMore && feedbackList.length > 0"> | ||
| 81 | + <text class="no-more-text">没有更多数据了</text> | ||
| 82 | + </view> | ||
| 83 | + </scroll-view> | ||
| 84 | + | ||
| 85 | + <!-- 底部固定按钮 --> | ||
| 86 | + <view class="fixed-bottom"> | ||
| 87 | + <button class="feedback-btn" @click="goToFeedback"> | ||
| 88 | + 我要反馈 | ||
| 89 | + </button> | ||
| 90 | + </view> | ||
| 91 | + | ||
| 92 | + <!-- 图片预览 --> | ||
| 93 | + <nut-image-preview | ||
| 94 | + v-model:show="previewVisible" | ||
| 95 | + :images="previewImages" | ||
| 96 | + :init-no="previewIndex" | ||
| 97 | + @close="closePreview" | ||
| 98 | + /> | ||
| 99 | + </view> | ||
| 100 | +</template> | ||
| 101 | + | ||
| 102 | +<script setup> | ||
| 103 | +import { ref, computed, onMounted } from 'vue' | ||
| 104 | +import Taro from '@tarojs/taro' | ||
| 105 | +import { Toast } from '@nutui/nutui-taro' | ||
| 106 | +// import { getFeedbackListAPI } from '@/api/other' | ||
| 107 | +import './index.less' | ||
| 108 | + | ||
| 109 | +// 反馈类型映射 | ||
| 110 | +const categoryMap = { | ||
| 111 | + '1': '功能建议', | ||
| 112 | + '3': '界面设计', | ||
| 113 | + '5': '车辆信息', | ||
| 114 | + '7': '其他问题' | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +// 响应式数据 | ||
| 118 | +const loading = ref(false) | ||
| 119 | +const refreshing = ref(false) | ||
| 120 | +const hasMore = ref(true) | ||
| 121 | +const currentPage = ref(0) | ||
| 122 | +const pageSize = ref(10) | ||
| 123 | +const feedbackList = ref([]) | ||
| 124 | + | ||
| 125 | +// 图片预览相关 | ||
| 126 | +const previewVisible = ref(false) | ||
| 127 | +const previewImages = ref([]) | ||
| 128 | +const previewIndex = ref(0) | ||
| 129 | + | ||
| 130 | +// 计算滚动视图样式 | ||
| 131 | +const scrollStyle = computed(() => { | ||
| 132 | + const systemInfo = Taro.getSystemInfoSync() | ||
| 133 | + const windowHeight = systemInfo.windowHeight | ||
| 134 | + | ||
| 135 | + // 动态计算底部区域高度:padding + 按钮高度 + 边框 + 安全区域 | ||
| 136 | + // 转换rpx到px: rpx值 / 750 * 屏幕宽度 | ||
| 137 | + const rpxToPx = systemInfo.screenWidth / 750 | ||
| 138 | + const topPadding = 20 * rpxToPx // 顶部padding | ||
| 139 | + const bottomPadding = 20 * rpxToPx // 底部基础padding | ||
| 140 | + const buttonHeight = 88 * rpxToPx // 按钮高度 | ||
| 141 | + const borderHeight = 1 * rpxToPx // 边框高度 | ||
| 142 | + | ||
| 143 | + // 获取安全区域底部高度 | ||
| 144 | + const safeAreaInsetBottom = systemInfo.safeArea | ||
| 145 | + ? Math.max(0, systemInfo.screenHeight - systemInfo.safeArea.bottom) | ||
| 146 | + : 0 | ||
| 147 | + | ||
| 148 | + // 总的底部高度 = 顶部padding + 底部padding + 按钮高度 + 边框高度 + 安全区域 | ||
| 149 | + const totalBottomHeight = topPadding + bottomPadding + buttonHeight + borderHeight + safeAreaInsetBottom | ||
| 150 | + | ||
| 151 | + const scrollHeight = Math.max(200, windowHeight - totalBottomHeight) | ||
| 152 | + | ||
| 153 | + return `height: ${scrollHeight}px;` | ||
| 154 | +}) | ||
| 155 | + | ||
| 156 | +/** | ||
| 157 | + * 获取反馈类型名称 | ||
| 158 | + */ | ||
| 159 | +const getCategoryName = (category) => { | ||
| 160 | + return categoryMap[category] || '未知类型' | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +/** | ||
| 164 | + * 格式化时间 | ||
| 165 | + */ | ||
| 166 | +const formatTime = (timestamp) => { | ||
| 167 | + if (!timestamp) return '' | ||
| 168 | + const date = new Date(timestamp * 1000) | ||
| 169 | + const year = date.getFullYear() | ||
| 170 | + const month = String(date.getMonth() + 1).padStart(2, '0') | ||
| 171 | + const day = String(date.getDate()).padStart(2, '0') | ||
| 172 | + const hours = String(date.getHours()).padStart(2, '0') | ||
| 173 | + const minutes = String(date.getMinutes()).padStart(2, '0') | ||
| 174 | + return `${year}-${month}-${day} ${hours}:${minutes}` | ||
| 175 | +} | ||
| 176 | + | ||
| 177 | +/** | ||
| 178 | + * 获取反馈列表数据 - 使用Mock数据 | ||
| 179 | + */ | ||
| 180 | +const getFeedbackList = async (isRefresh = false) => { | ||
| 181 | + if (loading.value) return | ||
| 182 | + | ||
| 183 | + loading.value = true | ||
| 184 | + | ||
| 185 | + try { | ||
| 186 | + // Mock数据 | ||
| 187 | + const mockData = [ | ||
| 188 | + { | ||
| 189 | + id: 1, | ||
| 190 | + category: '1', | ||
| 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 | + | ||
| 230 | + // 模拟网络延迟 | ||
| 231 | + await new Promise(resolve => setTimeout(resolve, 1000)) | ||
| 232 | + | ||
| 233 | + const startIndex = isRefresh ? 0 : currentPage.value * pageSize.value | ||
| 234 | + const endIndex = startIndex + pageSize.value | ||
| 235 | + const newData = mockData.slice(startIndex, endIndex) | ||
| 236 | + | ||
| 237 | + if (isRefresh) { | ||
| 238 | + feedbackList.value = newData | ||
| 239 | + currentPage.value = 0 | ||
| 240 | + } else { | ||
| 241 | + feedbackList.value.push(...newData) | ||
| 242 | + } | ||
| 243 | + | ||
| 244 | + // 判断是否还有更多数据 | ||
| 245 | + hasMore.value = endIndex < mockData.length | ||
| 246 | + | ||
| 247 | + if (!isRefresh) { | ||
| 248 | + currentPage.value++ | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + } catch (error) { | ||
| 252 | + console.error('获取反馈列表失败:', error) | ||
| 253 | + Toast.fail(error.message || '获取数据失败') | ||
| 254 | + } finally { | ||
| 255 | + loading.value = false | ||
| 256 | + refreshing.value = false | ||
| 257 | + } | ||
| 258 | +} | ||
| 259 | + | ||
| 260 | +/** | ||
| 261 | + * 下拉刷新 | ||
| 262 | + */ | ||
| 263 | +const onRefresh = () => { | ||
| 264 | + refreshing.value = true | ||
| 265 | + getFeedbackList(true) | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +/** | ||
| 269 | + * 加载更多 | ||
| 270 | + */ | ||
| 271 | +const loadMore = () => { | ||
| 272 | + if (!hasMore.value || loading.value) return | ||
| 273 | + getFeedbackList() | ||
| 274 | +} | ||
| 275 | + | ||
| 276 | +/** | ||
| 277 | + * 预览图片 | ||
| 278 | + */ | ||
| 279 | +const previewImage = (images, index) => { | ||
| 280 | + previewImages.value = images.map(src => ({ src })) | ||
| 281 | + previewIndex.value = index | ||
| 282 | + previewVisible.value = true | ||
| 283 | +} | ||
| 284 | + | ||
| 285 | +/** | ||
| 286 | + * 关闭图片预览 | ||
| 287 | + */ | ||
| 288 | +const closePreview = () => { | ||
| 289 | + previewVisible.value = false | ||
| 290 | +} | ||
| 291 | + | ||
| 292 | +/** | ||
| 293 | + * 跳转到反馈页面 | ||
| 294 | + */ | ||
| 295 | +const goToFeedback = () => { | ||
| 296 | + Taro.navigateTo({ | ||
| 297 | + url: '/pages/feedBack/index' | ||
| 298 | + }) | ||
| 299 | +} | ||
| 300 | + | ||
| 301 | +// 页面加载时获取数据 | ||
| 302 | +onMounted(() => { | ||
| 303 | + getFeedbackList(true) | ||
| 304 | +}) | ||
| 305 | +</script> | ||
| 306 | + | ||
| 307 | +<script> | ||
| 308 | +export default { | ||
| 309 | + name: 'FeedbackListPage' | ||
| 310 | +} | ||
| 311 | +</script> |
| 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 10:31:45 | 4 | + * @LastEditTime: 2025-07-17 11:31:47 |
| 5 | * @FilePath: /jgdl/src/pages/myAuthCar/index.vue | 5 | * @FilePath: /jgdl/src/pages/myAuthCar/index.vue |
| 6 | * @Description: 我的认证车页面 | 6 | * @Description: 我的认证车页面 |
| 7 | --> | 7 | --> |
| ... | @@ -42,7 +42,7 @@ | ... | @@ -42,7 +42,7 @@ |
| 42 | <text>{{ getVerificationStatusText(item.verification_status) }}</text> | 42 | <text>{{ getVerificationStatusText(item.verification_status) }}</text> |
| 43 | </view> | 43 | </view> |
| 44 | </view> | 44 | </view> |
| 45 | - <text class="text-sm text-gray-500 mt-1 block">{{ item.manufacture_year }}年|续航{{ item.range_km }}km|最高时速{{ item.max_speed_kmh }}km/h</text> | 45 | + <text class="text-sm text-gray-500 mt-1 block">续航{{ item.range_km }}km | 最高时速{{ item.max_speed_kmh }}km/h</text> |
| 46 | <!-- 认证失败原因 --> | 46 | <!-- 认证失败原因 --> |
| 47 | <view v-if="item.verification_status === 7 && item.verification_reason" class="verification-reason mt-1"> | 47 | <view v-if="item.verification_status === 7 && item.verification_reason" class="verification-reason mt-1"> |
| 48 | <text class="text-xs text-red-500">审核结果:{{ item.verification_reason }}</text> | 48 | <text class="text-xs text-red-500">审核结果:{{ item.verification_reason }}</text> | ... | ... |
-
Please register or login to post a comment