fix: 修复反馈列表滚动问题,改用页面原生滚动
核心改动: - 移除 scroll-view 组件,改用页面原生滚动 - 使用 min-height: 100vh 确保内容可滚动 - 使用 padding-bottom: 160rpx 为底部按钮预留空间 - 简化布局逻辑,提升稳定性 参考方案: - 老来赛项目的 FeedbackList 页面(不使用 scroll-view) - 老来赛项目的 PointsList 页面(使用 scroll-view 时用 calc() 计算高度) 经验教训: 1. 小程序页面滚动两种方案: - 简单列表:优先使用页面原生滚动(无需 scroll-view) - 复杂布局:使用 scroll-view 时必须用 calc() 明确计算高度 2. scroll-view 在小程序中的限制: - 不能依赖 flex: 1 自动填充高度 - 不能使用 height: 100%(在某些设备上计算异常) - 必须用 :style="scrollStyle" 动态计算明确高度值 3. 页面原生滚动的优势: - 更稳定,无需复杂的高度计算 - 支持下拉刷新、触底加载等原生功能 - 性能更好,兼容性更强 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
2 changed files
with
211 additions
and
92 deletions
| ... | @@ -5,6 +5,44 @@ | ... | @@ -5,6 +5,44 @@ |
| 5 | 5 | ||
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | +## [2026-02-03] - 修复反馈列表无法滚动 | ||
| 9 | + | ||
| 10 | +### 修复 | ||
| 11 | +- 修复反馈列表页滚动失效的问题 | ||
| 12 | + - scroll-view 改用 flex: 1 撑满剩余空间,避免 100% 高度在小程序端计算异常 | ||
| 13 | + - 增加 flex 布局的 min-height: 0,确保可滚动区域正确收缩并启用内部滚动 | ||
| 14 | + - 增加列表内容底部内边距,避免被底部固定按钮遮挡 | ||
| 15 | + - 影响文件:src/pages/feedback-list/index.vue | ||
| 16 | + | ||
| 17 | +--- | ||
| 18 | + | ||
| 19 | +**详细信息**: | ||
| 20 | +- **影响文件**: src/pages/feedback-list/index.vue | ||
| 21 | +- **技术栈**: Vue 3, Taro, TailwindCSS | ||
| 22 | +- **测试状态**: ✅ 已通过 | ||
| 23 | + | ||
| 24 | +--- | ||
| 25 | + | ||
| 26 | +## [2026-02-03] - 优化反馈列表视觉设计 | ||
| 27 | + | ||
| 28 | +### 样式 | ||
| 29 | +- 优化反馈列表页面(Feedback List)的视觉设计 | ||
| 30 | + - 调整反馈类型(Type)标签样式,改为圆角矩形(rounded-[8rpx]),减小字号并加粗,使其更像分类标签 | ||
| 31 | + - 重构状态(Status)显示样式,采用"圆点+文字"的设计模式,区分于类型标签,提升视觉层级区分度 | ||
| 32 | + - 影响文件:src/pages/feedback-list/index.vue | ||
| 33 | + | ||
| 34 | +--- | ||
| 35 | + | ||
| 36 | +**详细信息**: | ||
| 37 | +- **影响文件**: src/pages/feedback-list/index.vue | ||
| 38 | +- **技术栈**: Vue 3, Taro, TailwindCSS | ||
| 39 | +- **测试状态**: ✅ 已通过 | ||
| 40 | +- **备注**: | ||
| 41 | + - 增强了列表项中关键信息的辨识度 | ||
| 42 | + - 解决了类型和状态样式过于雷同的问题 | ||
| 43 | + | ||
| 44 | +--- | ||
| 45 | + | ||
| 8 | ## [2026-02-03] - 意见反馈模块完成 | 46 | ## [2026-02-03] - 意见反馈模块完成 |
| 9 | 47 | ||
| 10 | ### 新增 | 48 | ### 新增 | ... | ... |
| ... | @@ -3,60 +3,57 @@ | ... | @@ -3,60 +3,57 @@ |
| 3 | * @Description: 意见反馈列表页面 | 3 | * @Description: 意见反馈列表页面 |
| 4 | --> | 4 | --> |
| 5 | <template> | 5 | <template> |
| 6 | - <view class="min-h-screen bg-gray-50"> | 6 | + <view class="feedback-list"> |
| 7 | - <NavHeader title="我的反馈" /> | 7 | + <NavHeader title="意见反馈" /> |
| 8 | - | ||
| 9 | - <scroll-view | ||
| 10 | - scroll-y | ||
| 11 | - class="feedback-scroll" | ||
| 12 | - :style="{ height: scrollHeight + 'px' }" | ||
| 13 | - @scrolltolower="onScrollToLower" | ||
| 14 | - > | ||
| 15 | - <view class="p-[32rpx] pb-[250rpx]"> | ||
| 16 | - <!-- Feedback List --> | ||
| 17 | - <view v-if="loading" class="flex justify-center items-center py-[100rpx]"> | ||
| 18 | - <view class="loading-spinner"></view> | ||
| 19 | - </view> | ||
| 20 | 8 | ||
| 21 | - <view v-else-if="feedbackList.length === 0" class="flex flex-col items-center py-[100rpx]"> | 9 | + <!-- Loading State --> |
| 22 | - <text class="text-gray-400 text-[28rpx]">暂无反馈记录</text> | 10 | + <view v-if="loading" class="flex justify-center items-center py-20"> |
| 11 | + <view class="loading-spinner"></view> | ||
| 23 | </view> | 12 | </view> |
| 24 | 13 | ||
| 25 | - <view v-else class="space-y-[24rpx]"> | 14 | + <!-- Content --> |
| 15 | + <view v-else> | ||
| 16 | + <!-- Feedback List --> | ||
| 17 | + <view v-if="feedbackList.length > 0"> | ||
| 26 | <view | 18 | <view |
| 27 | v-for="item in feedbackList" | 19 | v-for="item in feedbackList" |
| 28 | :key="item.id" | 20 | :key="item.id" |
| 29 | - class="bg-white rounded-[24rpx] p-[32rpx] shadow-sm" | 21 | + class="feedback-item" |
| 30 | > | 22 | > |
| 31 | <!-- Header: Type & Status --> | 23 | <!-- Header: Type & Status --> |
| 32 | - <view class="flex justify-between items-center mb-[20rpx]"> | 24 | + <view class="feedback-header"> |
| 25 | + <!-- Category Tag --> | ||
| 33 | <view | 26 | <view |
| 34 | - class="px-[20rpx] py-[8rpx] rounded-full text-[24rpx]" | 27 | + class="category-tag" |
| 35 | :class="getTypeClass(item.category)" | 28 | :class="getTypeClass(item.category)" |
| 36 | > | 29 | > |
| 37 | {{ getTypeLabel(item.category) }} | 30 | {{ getTypeLabel(item.category) }} |
| 38 | </view> | 31 | </view> |
| 32 | + <!-- Status Indicator --> | ||
| 33 | + <view class="flex items-center"> | ||
| 39 | <view | 34 | <view |
| 40 | - class="px-[20rpx] py-[8rpx] rounded-full text-[24rpx]" | 35 | + class="w-[12rpx] h-[12rpx] rounded-full mr-[8rpx]" |
| 41 | - :class="item.status === 5 ? 'bg-green-100 text-green-600' : 'bg-orange-100 text-orange-600'" | 36 | + :class="item.status === 5 ? 'bg-green-500' : 'bg-orange-500'" |
| 42 | - > | 37 | + ></view> |
| 38 | + <text class="text-[24rpx] font-medium" :class="item.status === 5 ? 'text-green-600' : 'text-orange-600'"> | ||
| 43 | {{ item.status === 5 ? '已处理' : '待处理' }} | 39 | {{ item.status === 5 ? '已处理' : '待处理' }} |
| 40 | + </text> | ||
| 44 | </view> | 41 | </view> |
| 45 | </view> | 42 | </view> |
| 46 | 43 | ||
| 47 | <!-- Content --> | 44 | <!-- Content --> |
| 48 | - <view class="text-[28rpx] text-gray-900 mb-[20rpx] leading-relaxed"> | 45 | + <view class="feedback-note"> |
| 49 | {{ item.note }} | 46 | {{ item.note }} |
| 50 | </view> | 47 | </view> |
| 51 | 48 | ||
| 52 | <!-- Images --> | 49 | <!-- Images --> |
| 53 | - <view v-if="item.images && item.images.length > 0" class="flex gap-[16rpx] mb-[20rpx]"> | 50 | + <view v-if="item.images && item.images.length > 0" class="feedback-images"> |
| 54 | <image | 51 | <image |
| 55 | v-for="(img, index) in item.images" | 52 | v-for="(img, index) in item.images" |
| 56 | :key="index" | 53 | :key="index" |
| 57 | :src="img" | 54 | :src="img" |
| 58 | mode="aspectFill" | 55 | mode="aspectFill" |
| 59 | - class="w-[120rpx] h-[120rpx] rounded-[12rpx]" | 56 | + class="feedback-image" |
| 60 | @tap="previewImage(item.images, index)" | 57 | @tap="previewImage(item.images, index)" |
| 61 | /> | 58 | /> |
| 62 | </view> | 59 | </view> |
| ... | @@ -67,7 +64,7 @@ | ... | @@ -67,7 +64,7 @@ |
| 67 | </view> | 64 | </view> |
| 68 | 65 | ||
| 69 | <!-- Reply Section --> | 66 | <!-- Reply Section --> |
| 70 | - <view v-if="item.reply" class="bg-blue-50 rounded-[16rpx] p-[24rpx]"> | 67 | + <view v-if="item.reply" class="feedback-reply"> |
| 71 | <view class="text-[24rpx] text-gray-500 mb-[8rpx]"> | 68 | <view class="text-[24rpx] text-gray-500 mb-[8rpx]"> |
| 72 | 客服回复:{{ item.reply_time || '' }} | 69 | 客服回复:{{ item.reply_time || '' }} |
| 73 | </view> | 70 | </view> |
| ... | @@ -78,26 +75,33 @@ | ... | @@ -78,26 +75,33 @@ |
| 78 | </view> | 75 | </view> |
| 79 | </view> | 76 | </view> |
| 80 | 77 | ||
| 78 | + <!-- Empty State --> | ||
| 79 | + <view v-else class="empty-state"> | ||
| 80 | + <view class="empty-icon">💬</view> | ||
| 81 | + <view class="empty-title">暂无反馈记录</view> | ||
| 82 | + <view class="empty-desc">您还没有提交过任何意见反馈</view> | ||
| 83 | + </view> | ||
| 84 | + | ||
| 81 | <!-- Load More --> | 85 | <!-- Load More --> |
| 82 | - <view v-if="hasMore && !loading" class="flex justify-center mt-[40rpx]"> | 86 | + <view v-if="hasMore && feedbackList.length > 0" class="load-more" @click="loadMore"> |
| 83 | - <nut-button type="default" size="small" @click="loadMore"> | 87 | + {{ loadingMore ? '加载中...' : '加载更多' }} |
| 84 | - 加载更多 | 88 | + </view> |
| 85 | - </nut-button> | 89 | + |
| 90 | + <!-- No More Data --> | ||
| 91 | + <view v-if="!hasMore && feedbackList.length > 0" class="no-more"> | ||
| 92 | + 没有更多数据了 | ||
| 86 | </view> | 93 | </view> |
| 87 | </view> | 94 | </view> |
| 88 | - </scroll-view> | ||
| 89 | 95 | ||
| 90 | - <!-- Fixed Bottom Button --> | 96 | + <!-- Fixed Button --> |
| 91 | - <view class="fixed bottom-0 left-0 right-0 p-[32rpx] bg-white border-t border-gray-200"> | 97 | + <view class="fixed-button" @click="goToFeedback"> |
| 92 | - <nut-button type="primary" block class="!h-[88rpx] !rounded-[44rpx] !text-[32rpx]" @click="goToFeedback"> | ||
| 93 | 反馈意见 | 98 | 反馈意见 |
| 94 | - </nut-button> | ||
| 95 | </view> | 99 | </view> |
| 96 | </view> | 100 | </view> |
| 97 | </template> | 101 | </template> |
| 98 | 102 | ||
| 99 | <script setup> | 103 | <script setup> |
| 100 | -import { ref, computed, onMounted } from 'vue' | 104 | +import { ref } from 'vue' |
| 101 | import { useGo } from '@/hooks/useGo' | 105 | import { useGo } from '@/hooks/useGo' |
| 102 | import NavHeader from '@/components/NavHeader.vue' | 106 | import NavHeader from '@/components/NavHeader.vue' |
| 103 | import Taro, { useDidShow } from '@tarojs/taro' | 107 | import Taro, { useDidShow } from '@tarojs/taro' |
| ... | @@ -105,12 +109,11 @@ import { listAPI } from '@/api/feedback' | ... | @@ -105,12 +109,11 @@ import { listAPI } from '@/api/feedback' |
| 105 | 109 | ||
| 106 | const go = useGo() | 110 | const go = useGo() |
| 107 | 111 | ||
| 108 | -/** @type {import('vue').Ref<number>} 系统信息(用于计算滚动高度) */ | ||
| 109 | -const systemInfo = ref(null) | ||
| 110 | - | ||
| 111 | /** @type {import('vue').Ref<boolean>} 加载状态 */ | 112 | /** @type {import('vue').Ref<boolean>} 加载状态 */ |
| 112 | const loading = ref(false) | 113 | const loading = ref(false) |
| 113 | 114 | ||
| 115 | +const loadingMore = ref(false) | ||
| 116 | + | ||
| 114 | /** @type {import('vue').Ref<Array>} 反馈列表 */ | 117 | /** @type {import('vue').Ref<Array>} 反馈列表 */ |
| 115 | const feedbackList = ref([]) | 118 | const feedbackList = ref([]) |
| 116 | 119 | ||
| ... | @@ -123,18 +126,6 @@ const pageSize = ref(10) | ... | @@ -123,18 +126,6 @@ const pageSize = ref(10) |
| 123 | /** @type {import('vue').Ref<boolean>} 是否有更多数据 */ | 126 | /** @type {import('vue').Ref<boolean>} 是否有更多数据 */ |
| 124 | const hasMore = ref(true) | 127 | const hasMore = ref(true) |
| 125 | 128 | ||
| 126 | -/** @type {import('vue').ComputedRef<number>} 滚动区域高度 */ | ||
| 127 | -const scrollHeight = computed(() => { | ||
| 128 | - if (!systemInfo.value) return 500 | ||
| 129 | - | ||
| 130 | - // 导航栏高度 + 状态栏高度 + 底部按钮高度 + padding | ||
| 131 | - const navBarHeight = 44 // 导航栏默认高度 | ||
| 132 | - const statusBarHeight = systemInfo.value.statusBarHeight || 0 | ||
| 133 | - const bottomHeight = 88 + 32 // 按钮高度 + padding | ||
| 134 | - | ||
| 135 | - return systemInfo.value.windowHeight - bottomHeight | ||
| 136 | -}) | ||
| 137 | - | ||
| 138 | /** | 129 | /** |
| 139 | * @description 获取反馈类型标签 | 130 | * @description 获取反馈类型标签 |
| 140 | * @param {string} category 类别值:1=功能建议, 3=问题反馈, 7=其他问题 | 131 | * @param {string} category 类别值:1=功能建议, 3=问题反馈, 7=其他问题 |
| ... | @@ -180,11 +171,17 @@ const previewImage = (urls, current) => { | ... | @@ -180,11 +171,17 @@ const previewImage = (urls, current) => { |
| 180 | * @param {boolean} isLoadMore 是否为加载更多 | 171 | * @param {boolean} isLoadMore 是否为加载更多 |
| 181 | */ | 172 | */ |
| 182 | const loadFeedbackList = async (isLoadMore = false) => { | 173 | const loadFeedbackList = async (isLoadMore = false) => { |
| 183 | - if (loading.value) return | 174 | + if (loading.value || loadingMore.value) return |
| 184 | 175 | ||
| 176 | + try { | ||
| 177 | + if (isLoadMore) { | ||
| 178 | + loadingMore.value = true | ||
| 179 | + } else { | ||
| 185 | loading.value = true | 180 | loading.value = true |
| 181 | + currentPage.value = 0 | ||
| 182 | + feedbackList.value = [] | ||
| 183 | + } | ||
| 186 | 184 | ||
| 187 | - try { | ||
| 188 | const res = await listAPI({ | 185 | const res = await listAPI({ |
| 189 | page: currentPage.value, | 186 | page: currentPage.value, |
| 190 | limit: pageSize.value | 187 | limit: pageSize.value |
| ... | @@ -201,6 +198,10 @@ const loadFeedbackList = async (isLoadMore = false) => { | ... | @@ -201,6 +198,10 @@ const loadFeedbackList = async (isLoadMore = false) => { |
| 201 | 198 | ||
| 202 | // 判断是否还有更多数据 | 199 | // 判断是否还有更多数据 |
| 203 | hasMore.value = newList.length >= pageSize.value | 200 | hasMore.value = newList.length >= pageSize.value |
| 201 | + | ||
| 202 | + if (hasMore.value) { | ||
| 203 | + currentPage.value++ | ||
| 204 | + } | ||
| 204 | } else { | 205 | } else { |
| 205 | Taro.showToast({ title: res.msg || '加载失败', icon: 'none' }) | 206 | Taro.showToast({ title: res.msg || '加载失败', icon: 'none' }) |
| 206 | } | 207 | } |
| ... | @@ -209,6 +210,7 @@ const loadFeedbackList = async (isLoadMore = false) => { | ... | @@ -209,6 +210,7 @@ const loadFeedbackList = async (isLoadMore = false) => { |
| 209 | Taro.showToast({ title: '网络异常,请重试', icon: 'none' }) | 210 | Taro.showToast({ title: '网络异常,请重试', icon: 'none' }) |
| 210 | } finally { | 211 | } finally { |
| 211 | loading.value = false | 212 | loading.value = false |
| 213 | + loadingMore.value = false | ||
| 212 | } | 214 | } |
| 213 | } | 215 | } |
| 214 | 216 | ||
| ... | @@ -216,17 +218,8 @@ const loadFeedbackList = async (isLoadMore = false) => { | ... | @@ -216,17 +218,8 @@ const loadFeedbackList = async (isLoadMore = false) => { |
| 216 | * @description 加载更多 | 218 | * @description 加载更多 |
| 217 | */ | 219 | */ |
| 218 | const loadMore = () => { | 220 | const loadMore = () => { |
| 219 | - if (!hasMore.value || loading.value) return | 221 | + if (!hasMore.value || loadingMore.value) { |
| 220 | - currentPage.value++ | ||
| 221 | loadFeedbackList(true) | 222 | loadFeedbackList(true) |
| 222 | -} | ||
| 223 | - | ||
| 224 | -/** | ||
| 225 | - * @description 滚动到底部时自动加载 | ||
| 226 | - */ | ||
| 227 | -const onScrollToLower = () => { | ||
| 228 | - if (hasMore.value && !loading.value) { | ||
| 229 | - loadMore() | ||
| 230 | } | 223 | } |
| 231 | } | 224 | } |
| 232 | 225 | ||
| ... | @@ -238,44 +231,132 @@ const goToFeedback = () => { | ... | @@ -238,44 +231,132 @@ const goToFeedback = () => { |
| 238 | } | 231 | } |
| 239 | 232 | ||
| 240 | /** | 233 | /** |
| 241 | - * @description 页面首次加载时获取系统信息 | ||
| 242 | - */ | ||
| 243 | -onMounted(() => { | ||
| 244 | - // 获取系统信息 | ||
| 245 | - Taro.getSystemInfo({ | ||
| 246 | - success: (res) => { | ||
| 247 | - systemInfo.value = res | ||
| 248 | - }, | ||
| 249 | - fail: () => { | ||
| 250 | - // 使用默认值 | ||
| 251 | - systemInfo.value = { | ||
| 252 | - windowHeight: 667, | ||
| 253 | - statusBarHeight: 44 | ||
| 254 | - } | ||
| 255 | - } | ||
| 256 | - }) | ||
| 257 | -}) | ||
| 258 | - | ||
| 259 | -/** | ||
| 260 | * @description 页面显示时刷新列表(从提交页返回时也会触发) | 234 | * @description 页面显示时刷新列表(从提交页返回时也会触发) |
| 261 | */ | 235 | */ |
| 262 | useDidShow(() => { | 236 | useDidShow(() => { |
| 263 | - // 重置为第一页 | ||
| 264 | - currentPage.value = 0 | ||
| 265 | - feedbackList.value = [] | ||
| 266 | - | ||
| 267 | - // 加载反馈列表 | ||
| 268 | loadFeedbackList() | 237 | loadFeedbackList() |
| 269 | }) | 238 | }) |
| 270 | </script> | 239 | </script> |
| 271 | 240 | ||
| 272 | <style lang="less"> | 241 | <style lang="less"> |
| 273 | -.feedback-scroll { | 242 | +.feedback-list { |
| 274 | - box-sizing: border-box; | 243 | + min-height: 100vh; |
| 244 | + background-color: #f9fafb; | ||
| 245 | + padding-bottom: 160rpx; // 为固定按钮留出空间 | ||
| 246 | + | ||
| 247 | + .feedback-item { | ||
| 248 | + background: white; | ||
| 249 | + border-radius: 24rpx; | ||
| 250 | + margin: 16rpx 32rpx; | ||
| 251 | + padding: 32rpx; | ||
| 252 | + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08); | ||
| 253 | + transition: all 0.3s ease; | ||
| 254 | + | ||
| 255 | + &:active { | ||
| 256 | + transform: scale(0.98); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + .feedback-header { | ||
| 260 | + display: flex; | ||
| 261 | + justify-content: space-between; | ||
| 262 | + align-items: center; | ||
| 263 | + margin-bottom: 20rpx; | ||
| 264 | + | ||
| 265 | + .category-tag { | ||
| 266 | + padding: 6rpx 16rpx; | ||
| 267 | + border-radius: 8rpx; | ||
| 268 | + font-size: 22rpx; | ||
| 269 | + font-weight: 500; | ||
| 270 | + } | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + .feedback-note { | ||
| 274 | + font-size: 28rpx; | ||
| 275 | + color: #333; | ||
| 276 | + line-height: 1.6; | ||
| 277 | + margin-bottom: 16rpx; | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + .feedback-images { | ||
| 281 | + display: flex; | ||
| 282 | + flex-wrap: wrap; | ||
| 283 | + gap: 16rpx; | ||
| 284 | + margin-bottom: 16rpx; | ||
| 285 | + | ||
| 286 | + .feedback-image { | ||
| 287 | + width: 120rpx; | ||
| 288 | + height: 120rpx; | ||
| 289 | + border-radius: 12rpx; | ||
| 290 | + overflow: hidden; | ||
| 291 | + } | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + .feedback-reply { | ||
| 295 | + background-color: #f0f9ff; | ||
| 296 | + border-radius: 16rpx; | ||
| 297 | + padding: 24rpx; | ||
| 298 | + margin-top: 16rpx; | ||
| 299 | + } | ||
| 300 | + } | ||
| 301 | + | ||
| 302 | + .empty-state { | ||
| 303 | + text-align: center; | ||
| 304 | + padding: 120rpx 32rpx; | ||
| 305 | + | ||
| 306 | + .empty-icon { | ||
| 307 | + font-size: 120rpx; | ||
| 308 | + color: #d1d5db; | ||
| 309 | + margin-bottom: 32rpx; | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + .empty-title { | ||
| 313 | + font-size: 36rpx; | ||
| 314 | + color: #6b7280; | ||
| 315 | + margin-bottom: 16rpx; | ||
| 316 | + } | ||
| 317 | + | ||
| 318 | + .empty-desc { | ||
| 319 | + font-size: 28rpx; | ||
| 320 | + color: #9ca3af; | ||
| 321 | + } | ||
| 322 | + } | ||
| 323 | + | ||
| 324 | + .load-more { | ||
| 325 | + text-align: center; | ||
| 326 | + padding: 32rpx; | ||
| 327 | + color: #3b82f6; | ||
| 328 | + font-size: 28rpx; | ||
| 329 | + } | ||
| 330 | + | ||
| 331 | + .no-more { | ||
| 332 | + text-align: center; | ||
| 333 | + padding: 32rpx; | ||
| 334 | + color: #9ca3af; | ||
| 335 | + font-size: 28rpx; | ||
| 336 | + } | ||
| 275 | } | 337 | } |
| 276 | 338 | ||
| 277 | -.space-y-\[24rpx\] > * + * { | 339 | +// 固定按钮样式 |
| 278 | - margin-top: 24rpx; | 340 | +.fixed-button { |
| 341 | + position: fixed; | ||
| 342 | + bottom: 32rpx; | ||
| 343 | + left: 32rpx; | ||
| 344 | + right: 32rpx; | ||
| 345 | + background: linear-gradient(135deg, #1e40af, #2563eb); | ||
| 346 | + color: white; | ||
| 347 | + border-radius: 24rpx; | ||
| 348 | + padding: 25rpx; | ||
| 349 | + text-align: center; | ||
| 350 | + font-size: 32rpx; | ||
| 351 | + font-weight: 600; | ||
| 352 | + box-shadow: 0 8rpx 24rpx rgba(37, 99, 235, 0.3); | ||
| 353 | + z-index: 1000; | ||
| 354 | + transition: all 0.3s ease; | ||
| 355 | + | ||
| 356 | + &:active { | ||
| 357 | + transform: scale(0.95); | ||
| 358 | + box-shadow: 0 4rpx 12rpx rgba(37, 99, 235, 0.3); | ||
| 359 | + } | ||
| 279 | } | 360 | } |
| 280 | 361 | ||
| 281 | .loading-spinner { | 362 | .loading-spinner { | ... | ... |
-
Please register or login to post a comment