fix(material): 修复滚动加载无法触发的问题
移除 h-screen flex-col 布局,改用页面级滚动 - NavHeader 和搜索栏使用 sticky top-0 固定 - 列表容器使用页面级滚动(移除 overflow-y-auto) - 删除 mock 数据相关代码 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
4 changed files
with
83 additions
and
269 deletions
| 1 | +/* | ||
| 2 | + * @Date: 2026-02-06 18:10:17 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2026-02-06 18:12:50 | ||
| 5 | + * @FilePath: /manulife-weapp/src/api/file.js | ||
| 6 | + * @Description: 文件相关 API | ||
| 7 | + */ | ||
| 1 | import { fn, fetch } from '@/api/fn'; | 8 | import { fn, fetch } from '@/api/fn'; |
| 2 | 9 | ||
| 3 | const Api = { | 10 | const Api = { |
| ... | @@ -7,11 +14,11 @@ const Api = { | ... | @@ -7,11 +14,11 @@ const Api = { |
| 7 | 14 | ||
| 8 | /** | 15 | /** |
| 9 | * @description 文档列表 | 16 | * @description 文档列表 |
| 10 | - * @remark | 17 | + * @remark |
| 11 | * @param {Object} params 请求参数 | 18 | * @param {Object} params 请求参数 |
| 12 | * @param {string} params.client_id (可选) 主体id | 19 | * @param {string} params.client_id (可选) 主体id |
| 13 | - * @param {string} params.limit (可选) | 20 | + * @param {string} params.limit (可选) |
| 14 | - * @param {string} params.page (可选) | 21 | + * @param {string} params.page (可选) |
| 15 | * @param {string} params.cid (可选) 分类id | 22 | * @param {string} params.cid (可选) 分类id |
| 16 | * @param {string} params.child_id (可选) 只有一层分类时,筛选数据用 | 23 | * @param {string} params.child_id (可选) 只有一层分类时,筛选数据用 |
| 17 | * @param {string} params.keyword (可选) 搜索关键词 | 24 | * @param {string} params.keyword (可选) 搜索关键词 |
| ... | @@ -49,7 +56,7 @@ const Api = { | ... | @@ -49,7 +56,7 @@ const Api = { |
| 49 | }>; | 56 | }>; |
| 50 | }>; | 57 | }>; |
| 51 | list: Array<{ | 58 | list: Array<{ |
| 52 | - id: integer; // | 59 | + id: integer; // |
| 53 | name: string; // 附件名称 | 60 | name: string; // 附件名称 |
| 54 | value: string; // 附件地址 | 61 | value: string; // 附件地址 |
| 55 | extension: string; // 后缀名 | 62 | extension: string; // 后缀名 |
| ... | @@ -62,7 +69,9 @@ const Api = { | ... | @@ -62,7 +69,9 @@ const Api = { |
| 62 | * }; | 69 | * }; |
| 63 | * }>} | 70 | * }>} |
| 64 | */ | 71 | */ |
| 65 | -export const fileListAPI = (params) => fn(fetch.get(Api.FileList, params)); | 72 | +export const fileListAPI = (params) => { |
| 73 | + return fn(fetch.get(Api.FileList, params)); | ||
| 74 | +}; | ||
| 66 | 75 | ||
| 67 | /** | 76 | /** |
| 68 | * @description 本周热门资料 | 77 | * @description 本周热门资料 |
| ... | @@ -81,9 +90,11 @@ export const fileListAPI = (params) => fn(fetch.get(Api.FileList, params)); | ... | @@ -81,9 +90,11 @@ export const fileListAPI = (params) => fn(fetch.get(Api.FileList, params)); |
| 81 | size: string; // 文件大小 | 90 | size: string; // 文件大小 |
| 82 | read_people_count: integer; // 学习人数 | 91 | read_people_count: integer; // 学习人数 |
| 83 | read_people_percent: number; // 学习人数比例 | 92 | read_people_percent: number; // 学习人数比例 |
| 84 | - is_favorite: string; // | 93 | + is_favorite: string; // |
| 85 | }>; | 94 | }>; |
| 86 | * }; | 95 | * }; |
| 87 | * }>} | 96 | * }>} |
| 88 | */ | 97 | */ |
| 89 | -export const weekHotAPI = (params) => fn(fetch.get(Api.WeekHot, params)); | 98 | +export const weekHotAPI = (params) => { |
| 99 | + return fn(fetch.get(Api.WeekHot, params)); | ||
| 100 | +}; | ... | ... |
| 1 | import { fn, fetch } from '@/api/fn'; | 1 | import { fn, fetch } from '@/api/fn'; |
| 2 | -import { mockListAPI, mockDetailAPI } from './mock/product'; | ||
| 3 | - | ||
| 4 | -// ⚠️ Mock 数据开关 - 设置为 true 使用 mock 数据,false 使用真实 API | ||
| 5 | -const USE_MOCK_DATA = false; | ||
| 6 | 2 | ||
| 7 | const Api = { | 3 | const Api = { |
| 8 | Detail: '/srv/?a=get_product&t=detail', | 4 | Detail: '/srv/?a=get_product&t=detail', |
| ... | @@ -50,10 +46,6 @@ const Api = { | ... | @@ -50,10 +46,6 @@ const Api = { |
| 50 | * }>} | 46 | * }>} |
| 51 | */ | 47 | */ |
| 52 | export const detailAPI = (params) => { | 48 | export const detailAPI = (params) => { |
| 53 | - // 如果开启 Mock 数据,返回 mock 数据 | ||
| 54 | - if (USE_MOCK_DATA) { | ||
| 55 | - return mockDetailAPI(params); | ||
| 56 | - } | ||
| 57 | return fn(fetch.get(Api.Detail, params)); | 49 | return fn(fetch.get(Api.Detail, params)); |
| 58 | }; | 50 | }; |
| 59 | 51 | ||
| ... | @@ -98,9 +90,5 @@ export const detailAPI = (params) => { | ... | @@ -98,9 +90,5 @@ export const detailAPI = (params) => { |
| 98 | * }>} | 90 | * }>} |
| 99 | */ | 91 | */ |
| 100 | export const listAPI = (params) => { | 92 | export const listAPI = (params) => { |
| 101 | - // 如果开启 Mock 数据,返回 mock 数据 | ||
| 102 | - if (USE_MOCK_DATA) { | ||
| 103 | - return mockListAPI(params); | ||
| 104 | - } | ||
| 105 | return fn(fetch.get(Api.List, params)); | 93 | return fn(fetch.get(Api.List, params)); |
| 106 | }; | 94 | }; | ... | ... |
src/api/mock/product.js
deleted
100644 → 0
| 1 | -/** | ||
| 2 | - * @description Mock 数据 - 产品中心 | ||
| 3 | - * @note 用于测试滚动加载更多功能 | ||
| 4 | - */ | ||
| 5 | - | ||
| 6 | -// Mock 分类数据 | ||
| 7 | -export const mockCategories = [ | ||
| 8 | - { id: 1, name: '寿险' }, | ||
| 9 | - { id: 2, name: '健康险' }, | ||
| 10 | - { id: 3, name: '意外险' }, | ||
| 11 | - { id: 4, name: '年金险' }, | ||
| 12 | - { id: 5, name: '重疾险' } | ||
| 13 | -] | ||
| 14 | - | ||
| 15 | -// Mock 标签数据 | ||
| 16 | -const mockTags = [ | ||
| 17 | - { id: 1, name: '热销', bg_color: '#FEF3C7', text_color: '#92400E' }, | ||
| 18 | - { id: 2, name: '新品', bg_color: '#DBEAFE', text_color: '#1E40AF' }, | ||
| 19 | - { id: 3, name: '推荐', bg_color: '#D1FAE5', text_color: '#065F46' }, | ||
| 20 | - { id: 4, name: '限时', bg_color: '#FEE2E2', text_color: '#991B1B' } | ||
| 21 | -] | ||
| 22 | - | ||
| 23 | -// 生成单个产品数据 | ||
| 24 | -const generateProduct = (id) => { | ||
| 25 | - const recommendTypes = ['normal', 'hot'] | ||
| 26 | - const recommend = recommendTypes[Math.floor(Math.random() * recommendTypes.length)] | ||
| 27 | - | ||
| 28 | - // 随机选择 1-2 个标签 | ||
| 29 | - const tagCount = Math.floor(Math.random() * 2) + 1 | ||
| 30 | - const tags = [] | ||
| 31 | - for (let i = 0; i < tagCount; i++) { | ||
| 32 | - const tag = mockTags[Math.floor(Math.random() * mockTags.length)] | ||
| 33 | - if (!tags.find(t => t.id === tag.id)) { | ||
| 34 | - tags.push(tag) | ||
| 35 | - } | ||
| 36 | - } | ||
| 37 | - | ||
| 38 | - // 随机选择 1-2 个分类 | ||
| 39 | - const categoryCount = Math.floor(Math.random() * 2) + 1 | ||
| 40 | - const categories = [] | ||
| 41 | - for (let i = 0; i < categoryCount; i++) { | ||
| 42 | - const category = mockCategories[Math.floor(Math.random() * mockCategories.length)] | ||
| 43 | - if (!categories.find(c => c.id === category.id)) { | ||
| 44 | - categories.push(category) | ||
| 45 | - } | ||
| 46 | - } | ||
| 47 | - | ||
| 48 | - return { | ||
| 49 | - id: id, | ||
| 50 | - product_name: `测试产品 ${id} - ${categories.map(c => c.name).join('+')}`, | ||
| 51 | - recommend: recommend, | ||
| 52 | - form_sn: `product_form_${id}`, | ||
| 53 | - created_time: '2025-12-01 12:00:00', | ||
| 54 | - categories: categories, | ||
| 55 | - tags: tags, | ||
| 56 | - // 使用 Lorem Picsum 随机图片服务(基于产品 ID 确保图片固定) | ||
| 57 | - cover_image: `https://picsum.photos/300/200?random=${id}` | ||
| 58 | - } | ||
| 59 | -} | ||
| 60 | - | ||
| 61 | -// 生成产品列表 | ||
| 62 | -const generateProductList = (page, limit, cid = null) => { | ||
| 63 | - const start = page * limit | ||
| 64 | - const end = start + limit | ||
| 65 | - | ||
| 66 | - // 如果指定了分类,只返回该分类的产品 | ||
| 67 | - let filteredProducts = [] | ||
| 68 | - if (cid) { | ||
| 69 | - // 为每个分类生成固定数量的产品 | ||
| 70 | - const categoryProducts = [] | ||
| 71 | - for (let i = 1; i <= 50; i++) { | ||
| 72 | - const product = generateProduct(i) | ||
| 73 | - // 强制该产品属于指定分类 | ||
| 74 | - product.categories = mockCategories.find(c => String(c.id) === String(cid)) | ||
| 75 | - ? [mockCategories.find(c => String(c.id) === String(cid))] | ||
| 76 | - : [{ id: parseInt(cid), name: '测试分类' }] | ||
| 77 | - categoryProducts.push(product) | ||
| 78 | - } | ||
| 79 | - filteredProducts = categoryProducts | ||
| 80 | - } else { | ||
| 81 | - // 全部产品 | ||
| 82 | - for (let i = 1; i <= 100; i++) { | ||
| 83 | - filteredProducts.push(generateProduct(i)) | ||
| 84 | - } | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - const total = filteredProducts.length | ||
| 88 | - const list = filteredProducts.slice(start, end) | ||
| 89 | - | ||
| 90 | - return { | ||
| 91 | - list, | ||
| 92 | - total, | ||
| 93 | - hasMore: end < total | ||
| 94 | - } | ||
| 95 | -} | ||
| 96 | - | ||
| 97 | -/** | ||
| 98 | - * Mock 产品列表 API | ||
| 99 | - * @param {Object} params 请求参数 | ||
| 100 | - * @param {string} params.page 页码(从 0 开始) | ||
| 101 | - * @param {string} params.limit 每页数量 | ||
| 102 | - * @param {string} params.cid 分类 ID(可选) | ||
| 103 | - * @param {string} params.keyword 搜索关键词(可选) | ||
| 104 | - * @returns {Promise} 模拟 API 响应 | ||
| 105 | - */ | ||
| 106 | -export const mockListAPI = (params) => { | ||
| 107 | - return new Promise((resolve) => { | ||
| 108 | - // 模拟网络延迟(300-800ms) | ||
| 109 | - const delay = Math.floor(Math.random() * 500) + 300 | ||
| 110 | - | ||
| 111 | - setTimeout(() => { | ||
| 112 | - const page = parseInt(params.page) || 0 | ||
| 113 | - const limit = parseInt(params.limit) || 10 | ||
| 114 | - const cid = params.cid || null | ||
| 115 | - const keyword = params.keyword || '' | ||
| 116 | - | ||
| 117 | - let result = generateProductList(page, limit, cid) | ||
| 118 | - | ||
| 119 | - // 如果有搜索关键词,过滤产品 | ||
| 120 | - if (keyword) { | ||
| 121 | - result.list = result.list.filter(p => | ||
| 122 | - p.product_name.includes(keyword) | ||
| 123 | - ) | ||
| 124 | - // 搜索时重新计算总数 | ||
| 125 | - result.total = result.list.length + Math.floor(Math.random() * 20) | ||
| 126 | - } | ||
| 127 | - | ||
| 128 | - resolve({ | ||
| 129 | - code: 1, | ||
| 130 | - msg: 'success', | ||
| 131 | - data: { | ||
| 132 | - categories: mockCategories, | ||
| 133 | - list: result.list, | ||
| 134 | - total: result.total | ||
| 135 | - } | ||
| 136 | - }) | ||
| 137 | - }, delay) | ||
| 138 | - }) | ||
| 139 | -} | ||
| 140 | - | ||
| 141 | -/** | ||
| 142 | - * Mock 产品详情 API | ||
| 143 | - * @param {Object} params 请求参数 | ||
| 144 | - * @param {string} params.i 产品 ID | ||
| 145 | - * @returns {Promise} 模拟 API 响应 | ||
| 146 | - */ | ||
| 147 | -export const mockDetailAPI = (params) => { | ||
| 148 | - return new Promise((resolve) => { | ||
| 149 | - const delay = Math.floor(Math.random() * 500) + 300 | ||
| 150 | - | ||
| 151 | - setTimeout(() => { | ||
| 152 | - const id = parseInt(params.i) || 1 | ||
| 153 | - const product = generateProduct(id) | ||
| 154 | - | ||
| 155 | - // 添加额外的详情字段 | ||
| 156 | - product.product_description = `这是产品 ${id} 的详细描述。\n\n产品特点:\n1. 保障全面\n2. 灵活配置\n3. 理赔便捷` | ||
| 157 | - product.documents = [ | ||
| 158 | - { | ||
| 159 | - file_url: 'https://example.com/file1.pdf', | ||
| 160 | - file_name: '产品条款.pdf', | ||
| 161 | - file_size: '1024000', | ||
| 162 | - file_size_formatted: '1.0 MB' | ||
| 163 | - }, | ||
| 164 | - { | ||
| 165 | - file_url: 'https://example.com/file2.pdf', | ||
| 166 | - file_name: '产品说明.pdf', | ||
| 167 | - file_size: '512000', | ||
| 168 | - file_size_formatted: '512 KB' | ||
| 169 | - } | ||
| 170 | - ] | ||
| 171 | - product.status = 'active' | ||
| 172 | - product.created_by = 1 | ||
| 173 | - product.updated_by = 1 | ||
| 174 | - product.updated_time = '2025-12-01 12:00:00' | ||
| 175 | - | ||
| 176 | - resolve({ | ||
| 177 | - code: 1, | ||
| 178 | - msg: 'success', | ||
| 179 | - data: product | ||
| 180 | - }) | ||
| 181 | - }, delay) | ||
| 182 | - }) | ||
| 183 | -} |
| ... | @@ -3,8 +3,9 @@ | ... | @@ -3,8 +3,9 @@ |
| 3 | * @Description: 资料列表页 - 已改造为 NutTabs 版本 | 3 | * @Description: 资料列表页 - 已改造为 NutTabs 版本 |
| 4 | --> | 4 | --> |
| 5 | <template> | 5 | <template> |
| 6 | - <view class="h-screen bg-[#F9FAFB] flex flex-col"> | 6 | + <view class="bg-[#F9FAFB]"> |
| 7 | - <view class="bg-[#F9FAFB] z-10"> | 7 | + <!-- 固定在顶部的导航和搜索 --> |
| 8 | + <view class="bg-[#F9FAFB] sticky top-0 z-10"> | ||
| 8 | <NavHeader :title="pageTitle" /> | 9 | <NavHeader :title="pageTitle" /> |
| 9 | 10 | ||
| 10 | <view class="px-[32rpx] mt-[32rpx] mb-[24rpx]"> | 11 | <view class="px-[32rpx] mt-[32rpx] mb-[24rpx]"> |
| ... | @@ -18,10 +19,7 @@ | ... | @@ -18,10 +19,7 @@ |
| 18 | :show-clear="true" | 19 | :show-clear="true" |
| 19 | /> | 20 | /> |
| 20 | </view> | 21 | </view> |
| 21 | - </view> | ||
| 22 | 22 | ||
| 23 | - <!-- Tabs Container --> | ||
| 24 | - <view class="flex-1 min-h-0 flex flex-col"> | ||
| 25 | <!-- 动态显示 Tabs(仅在有分类时显示) --> | 23 | <!-- 动态显示 Tabs(仅在有分类时显示) --> |
| 26 | <nut-tabs v-if="hasCategories" v-model="activeTabId"> | 24 | <nut-tabs v-if="hasCategories" v-model="activeTabId"> |
| 27 | <!-- 自定义标签栏 --> | 25 | <!-- 自定义标签栏 --> |
| ... | @@ -41,73 +39,73 @@ | ... | @@ -41,73 +39,73 @@ |
| 41 | </view> | 39 | </view> |
| 42 | </template> | 40 | </template> |
| 43 | </nut-tabs> | 41 | </nut-tabs> |
| 42 | + </view> | ||
| 44 | 43 | ||
| 45 | - <!-- 列表容器(独立于 nut-tab-pane) --> | 44 | + <!-- 列表容器 - 页面级滚动 --> |
| 46 | - <view | 45 | + <view |
| 47 | - v-if="listVisible" | 46 | + v-if="listVisible" |
| 48 | - :key="listRenderKey" | 47 | + :key="listRenderKey" |
| 49 | - class="flex-1 min-h-0 overflow-y-auto px-[32rpx] pb-[calc(160rpx+env(safe-area-inset-bottom))] box-border" | 48 | + class="px-[32rpx] pb-[calc(160rpx+env(safe-area-inset-bottom))] box-border" |
| 50 | - > | 49 | + > |
| 51 | - <view class="flex flex-col gap-[24rpx]"> | 50 | + <view class="flex flex-col gap-[24rpx]"> |
| 52 | - <view v-for="(item, index) in currentList" :key="index" | 51 | + <view v-for="(item, index) in currentList" :key="index" |
| 53 | - class="material-item bg-white rounded-[24rpx] p-[24rpx] shadow-sm transition-all duration-200 border border-gray-50 flex flex-row" | 52 | + class="material-item bg-white rounded-[24rpx] p-[24rpx] shadow-sm transition-all duration-200 border border-gray-50 flex flex-row" |
| 54 | - :style="{ animationDelay: `${index * 50}ms` }"> | 53 | + :style="{ animationDelay: `${index * 50}ms` }"> |
| 55 | - | 54 | + |
| 56 | - <view | 55 | + <view |
| 57 | - class="w-[88rpx] h-[88rpx] mr-[24rpx] flex-shrink-0 flex items-center justify-center bg-gradient-to-br from-blue-50 to-blue-100 rounded-[20rpx] shadow-inner self-start"> | 56 | + class="w-[88rpx] h-[88rpx] mr-[24rpx] flex-shrink-0 flex items-center justify-center bg-gradient-to-br from-blue-50 to-blue-100 rounded-[20rpx] shadow-inner self-start"> |
| 58 | - <image | 57 | + <image |
| 59 | - :src="getDocumentIcon(item.extension ? `file.${item.extension}` : item.fileName)" | 58 | + :src="getDocumentIcon(item.extension ? `file.${item.extension}` : item.fileName)" |
| 60 | - class="w-[48rpx] h-[48rpx]" | 59 | + class="w-[48rpx] h-[48rpx]" |
| 61 | - mode="aspectFit" | 60 | + mode="aspectFit" |
| 62 | - /> | 61 | + /> |
| 63 | - </view> | 62 | + </view> |
| 64 | 63 | ||
| 65 | - <view class="flex-1 min-w-0"> | 64 | + <view class="flex-1 min-w-0"> |
| 66 | - <h3 class="text-[#1F2937] text-[30rpx] font-bold leading-[1.4] line-clamp-2 mb-[8rpx]"> | 65 | + <h3 class="text-[#1F2937] text-[30rpx] font-bold leading-[1.4] line-clamp-2 mb-[8rpx]"> |
| 67 | - {{ item.title }} | 66 | + {{ item.title }} |
| 68 | - </h3> | 67 | + </h3> |
| 69 | - <p class="text-[#6B7280] text-[24rpx] leading-[1.4] line-clamp-1 mb-[16rpx]"> | 68 | + <p class="text-[#6B7280] text-[24rpx] leading-[1.4] line-clamp-1 mb-[16rpx]"> |
| 70 | - {{ item.desc }} | 69 | + {{ item.desc }} |
| 71 | - </p> | 70 | + </p> |
| 72 | - | 71 | + |
| 73 | - <view class="flex items-center gap-[12rpx] mb-[20rpx]"> | 72 | + <view class="flex items-center gap-[12rpx] mb-[20rpx]"> |
| 74 | - <view | 73 | + <view |
| 75 | - class="inline-flex items-center justify-center px-[12rpx] py-[4rpx] bg-gray-100 text-gray-500 text-[20rpx] font-medium rounded-[8rpx]"> | 74 | + class="inline-flex items-center justify-center px-[12rpx] py-[4rpx] bg-gray-100 text-gray-500 text-[20rpx] font-medium rounded-[8rpx]"> |
| 76 | - {{ getDocumentLabel(item.extension ? `file.${item.extension}` : item.fileName) }} | 75 | + {{ getDocumentLabel(item.extension ? `file.${item.extension}` : item.fileName) }} |
| 77 | - </view> | 76 | + </view> |
| 78 | - <view class="text-[#9CA3AF] text-[22rpx]"> | 77 | + <view class="text-[#9CA3AF] text-[22rpx]"> |
| 79 | - {{ item.size }} | 78 | + {{ item.size }} |
| 80 | - </view> | ||
| 81 | </view> | 79 | </view> |
| 82 | - | ||
| 83 | - <view class="h-[1rpx] bg-gray-100 my-[20rpx]"></view> | ||
| 84 | - | ||
| 85 | - <ListItemActions | ||
| 86 | - :viewable="true" | ||
| 87 | - :collectable="true" | ||
| 88 | - :collected="item.collected" | ||
| 89 | - :item-id="String(item.meta_id || item.id)" | ||
| 90 | - @view="onView(item)" | ||
| 91 | - @collect="toggleCollect(item)" | ||
| 92 | - @delete="onDelete(item)" | ||
| 93 | - /> | ||
| 94 | </view> | 80 | </view> |
| 95 | - </view> | ||
| 96 | 81 | ||
| 97 | - <!-- 空状态 --> | 82 | + <view class="h-[1rpx] bg-gray-100 my-[20rpx]"></view> |
| 98 | - <view v-if="currentList.length === 0 && !loading"> | 83 | + |
| 99 | - <nut-empty description="暂无相关资料" image="empty" /> | 84 | + <ListItemActions |
| 85 | + :viewable="true" | ||
| 86 | + :collectable="true" | ||
| 87 | + :collected="item.collected" | ||
| 88 | + :item-id="String(item.meta_id || item.id)" | ||
| 89 | + @view="onView(item)" | ||
| 90 | + @collect="toggleCollect(item)" | ||
| 91 | + @delete="onDelete(item)" | ||
| 92 | + /> | ||
| 100 | </view> | 93 | </view> |
| 94 | + </view> | ||
| 101 | 95 | ||
| 102 | - <!-- 加载更多状态 --> | 96 | + <!-- 空状态 --> |
| 103 | - <view v-if="currentList.length > 0" class="load-more-container"> | 97 | + <view v-if="currentList.length === 0 && !loading"> |
| 104 | - <view v-if="loadingMore" class="load-more-loading"> | 98 | + <nut-empty description="暂无相关资料" image="empty" /> |
| 105 | - <view class="loading-spinner"></view> | 99 | + </view> |
| 106 | - <text class="ml-[16rpx] text-[#9CA3AF] text-[24rpx]">加载中...</text> | 100 | + |
| 107 | - </view> | 101 | + <!-- 加载更多状态 --> |
| 108 | - <view v-else-if="!hasMore" class="load-more-finished"> | 102 | + <view v-if="currentList.length > 0" class="load-more-container"> |
| 109 | - <text class="text-[#9CA3AF] text-[24rpx]">没有更多了</text> | 103 | + <view v-if="loadingMore" class="load-more-loading"> |
| 110 | - </view> | 104 | + <view class="loading-spinner"></view> |
| 105 | + <text class="ml-[16rpx] text-[#9CA3AF] text-[24rpx]">加载中...</text> | ||
| 106 | + </view> | ||
| 107 | + <view v-else-if="!hasMore" class="load-more-finished"> | ||
| 108 | + <text class="text-[#9CA3AF] text-[24rpx]">没有更多了</text> | ||
| 111 | </view> | 109 | </view> |
| 112 | </view> | 110 | </view> |
| 113 | </view> | 111 | </view> |
| ... | @@ -282,9 +280,9 @@ const fetchMaterialList = async (params = {}, isLoadMore = false) => { | ... | @@ -282,9 +280,9 @@ const fetchMaterialList = async (params = {}, isLoadMore = false) => { |
| 282 | loading.value = true | 280 | loading.value = true |
| 283 | } | 281 | } |
| 284 | 282 | ||
| 285 | - // console.log('[Material List] 请求参数:', params) | 283 | + console.log('[Material List] 请求参数:', params) |
| 286 | 284 | ||
| 287 | - // 调用接口(直接调用,不使用 fn() 包装) | 285 | + // 调用接口 |
| 288 | const res = await fileListAPI(params) | 286 | const res = await fileListAPI(params) |
| 289 | 287 | ||
| 290 | if (res.code === 1 && res.data) { | 288 | if (res.code === 1 && res.data) { | ... | ... |
-
Please register or login to post a comment