From d194442971e2bc3535672bb8083a1e419d5314d2 Mon Sep 17 00:00:00 2001 From: Default User Date: Sat, 10 Jan 2026 16:24:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96goods=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=EF=BC=9A=E6=B7=BB=E5=8A=A0=E5=88=86=E9=A1=B5=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=EF=BC=8C=E5=85=88=E5=8A=A0=E8=BD=BD=E5=B7=B2=E4=B8=8A=E6=9E=B6?= =?UTF-8?q?=E5=95=86=E5=93=81=E5=86=8D=E5=8A=A0=E8=BD=BD=E5=94=AE=E7=A9=BA?= =?UTF-8?q?=E5=95=86=E5=93=81=EF=BC=8C=E5=8A=A0=E5=85=A5=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/goods/index.js | 509 +++++++++++++++++++++++++++++------------ pages/goods/index.wxml | 2 +- 2 files changed, 366 insertions(+), 145 deletions(-) diff --git a/pages/goods/index.js b/pages/goods/index.js index ab84a17..828b9c2 100644 --- a/pages/goods/index.js +++ b/pages/goods/index.js @@ -42,9 +42,6 @@ Page({ goodsList: [], isLoading: false, isRefreshing: false, // 下拉刷新状态 - currentPage: 1, - pageSize: 20, - hasMore: true, searchKeyword: '', activeFilter: 'all', // 当前筛选条件:all, small, large filterConfig: { @@ -52,7 +49,25 @@ Page({ large: ['吴海燕', '陈骏', '刘琴', '汤敏'] // 大贸易创建者 }, total: 0, // 总数据条数 - searchTimer: null // 搜索防抖定时器 + searchTimer: null, // 搜索防抖定时器 + // 分页相关字段 + pageSize: 20, // 每页数量 + publishedCurrentPage: 1, // 已上架商品当前页码 + publishedHasMore: true, // 已上架商品是否有更多 + soldOutCurrentPage: 1, // 售空商品当前页码 + soldOutHasMore: true, // 售空商品是否有更多 + currentLoadingType: '', // 当前加载类型:published, soldOut + // 缓存相关字段 + cache: { + publishedGoods: [], // 已上架货源缓存 + soldOutGoods: [], // 售空货源缓存 + timestamp: 0, // 缓存时间戳 + expiry: 5 * 60 * 1000 // 缓存有效期:5分钟 + }, + isLoadingPublished: false, // 正在加载已上架货源 + isLoadingSoldOut: false, // 正在加载售空货源 + publishedLoaded: false, // 已上架货源是否加载完成 + soldOutLoaded: false // 售空货源是否加载完成 }, /** @@ -105,9 +120,7 @@ Page({ this.setData({ isRefreshing: true, - currentPage: 1, goodsList: [], - hasMore: true, isLoading: false }) this.loadGoodsList() @@ -117,11 +130,10 @@ Page({ * 页面上拉触底事件的处理函数 */ onReachBottom() { - if (this.data.hasMore && !this.data.isLoading) { - this.setData({ - currentPage: this.data.currentPage + 1 - }) - this.loadGoodsList() + // 检查是否还有更多数据需要加载 + const hasMore = this.data.publishedHasMore || this.data.soldOutHasMore + if (hasMore && !this.data.isLoading) { + this.loadGoodsList(true) // 传入true表示加载更多 } }, @@ -156,9 +168,11 @@ Page({ if (this.data.isLoading) return this.setData({ - currentPage: 1, goodsList: [], - hasMore: true + // 清除缓存 + 'cache.publishedGoods': [], + 'cache.soldOutGoods': [], + 'cache.timestamp': 0 }) this.loadGoodsList() }, @@ -169,9 +183,11 @@ Page({ clearSearch() { this.setData({ searchKeyword: '', - currentPage: 1, goodsList: [], - hasMore: true + // 清除缓存 + 'cache.publishedGoods': [], + 'cache.soldOutGoods': [], + 'cache.timestamp': 0 }) this.loadGoodsList() }, @@ -185,9 +201,11 @@ Page({ const filter = e.currentTarget.dataset.filter this.setData({ activeFilter: filter, - currentPage: 1, goodsList: [], - hasMore: true + // 清除缓存 + 'cache.publishedGoods': [], + 'cache.soldOutGoods': [], + 'cache.timestamp': 0 }) this.loadGoodsList() }, @@ -297,68 +315,39 @@ Page({ }, /** - * 加载货源列表 - 优化搜索功能,支持搜索创建人信息 + * 加载已上架(published)状态的货源 - 支持分页 */ - async loadGoodsList() { - if (this.data.isLoading) return + async loadPublishedGoods(page = 1, pageSize = this.data.pageSize) { + if (this.data.isLoadingPublished) return { goods: [], hasMore: true } this.setData({ - isLoading: true + isLoadingPublished: true, + currentLoadingType: 'published' }) - console.log('开始加载货源列表,参数:', { - page: this.data.currentPage, - pageSize: this.data.pageSize, - keyword: this.data.searchKeyword, - activeFilter: this.data.activeFilter + console.log('开始加载已上架货源,分页参数:', { + page, + pageSize, + keyword: this.data.searchKeyword }) - // 调用API获取货源列表 try { const res = await API.getGoodsList({ - page: this.data.currentPage, - pageSize: this.data.pageSize, + page: page, + pageSize: pageSize, keyword: this.data.searchKeyword }) - console.log('API返回结果:', res) - - // 检查API返回的状态 if (res.success) { - console.log('API调用成功,products:', res.products) - console.log('products长度:', res.products.length) - console.log('API返回total:', res.total) - - // 更新总数据条数 - const total = res.total || 0 + let publishedGoods = res.products || [] - if (res.products && res.products.length > 0) { - // 显示第一个产品的详细信息 - console.log('第一个产品:', res.products[0]) - console.log('第一个产品的seller:', res.products[0].seller) - console.log('第一个产品的seller.nickName:', res.products[0].seller?.nickName) - console.log('第一个产品的seller.name:', res.products[0].seller?.name) - console.log('第一个产品的seller完整结构:', JSON.stringify(res.products[0].seller)) - - let newGoodsList = res.products || [] - - // 格式化创建时间并处理创建者信息 - newGoodsList = newGoodsList.map((item, index) => { - // 详细日志,查看每个产品的seller信息 - console.log(`产品${index}的seller信息:`) - console.log(`- seller对象:`, item.seller) - console.log(`- seller.nickName:`, item.seller?.nickName) - console.log(`- seller.sellerNickName:`, item.seller?.sellerNickName) - console.log(`- seller.name:`, item.seller?.name) - console.log(`- seller完整结构:`, JSON.stringify(item.seller)) - - // 确定creatorName - 支持多种字段,确保能获取到创建人信息 - // 从seller对象中获取创建人信息,优先使用nickName,其次使用sellerNickName,最后使用name + // 数据格式化处理 + publishedGoods = publishedGoods.map(item => { + // 确定creatorName const sellerNickName = item.seller?.nickName || item.seller?.sellerNickName || item.seller?.name || '未知'; const creatorName = sellerNickName; - console.log('creatorName获取结果:', creatorName) - // 处理媒体URL,添加类型信息 + // 处理媒体URL const imageUrls = item.imageUrls || item.images || [] const formattedImageUrls = Array.isArray(imageUrls) ? imageUrls : [imageUrls] const mediaItems = formattedImageUrls.map(url => ({ @@ -366,140 +355,372 @@ Page({ type: isVideoUrl(url) ? 'video' : 'image' })) - // 处理商品状态,将已下架的商品标记为售空 + // 处理商品状态 let status = item.status - // 检查是否为售空状态 const isSoldOut = status === 'sold_out' || status === 'sold' || status === 'out_of_stock' || (item.supplyStatus && item.supplyStatus.includes('售空')); - - // 如果商品是售空状态,则标记为sold_out + if (isSoldOut) { status = 'sold_out' } else if (status !== 'published') { - // 如果不是已上架状态且不是售空状态,仍然标记为已上架,确保预售和现货商品能正常显示 status = 'published' } - // 处理价格,只显示第一个规格的价格 + // 只保留published状态的商品 + if (status !== 'published') { + return null + } + + // 处理价格 let processedPrice = item.price; if (processedPrice && typeof processedPrice === 'string') { - // 支持多种逗号分隔符:英文逗号、中文逗号、全角逗号 const priceArray = processedPrice.split(/[,,、]/).map(p => p.trim()).filter(p => p); if (priceArray.length > 0) { processedPrice = priceArray[0]; } } - // 确保productName字段存在,优先使用productName,其次使用name const productName = item.productName || item.name || '未命名商品'; - - // 确定显示时间:优先使用更新时间,其次使用创建时间 const displayTime = item.updated_at || item.updatedAt || item.created_at || item.createTime; return { ...item, - productName: productName, // 确保productName字段存在 - name: productName, // 确保name字段存在 - status: status, // 更新商品状态 - price: processedPrice, // 更新为第一个规格的价格 + productName: productName, + name: productName, + status: status, + price: processedPrice, formattedCreatedAt: this.formatDateTime(displayTime), - creatorName: creatorName, // 已处理的创建人名称 + creatorName: creatorName, imageUrls: formattedImageUrls, mediaItems: mediaItems } + }).filter(Boolean) // 过滤掉null值 + + // 应用筛选和搜索 + let filteredGoods = publishedGoods + if (this.data.searchKeyword && this.data.searchKeyword.trim() !== '') { + filteredGoods = this.searchGoodsList(filteredGoods, this.data.searchKeyword) + } else { + filteredGoods = this.filterGoodsList(filteredGoods) + } + + // 按时间倒序排序 + filteredGoods.sort((a, b) => { + const timeA = new Date(a.updated_at || a.updatedAt || a.created_at || a.createTime).getTime() + const timeB = new Date(b.updated_at || b.updatedAt || b.created_at || b.createTime).getTime() + return timeB - timeA }) + + // 判断是否有更多数据 + const hasMore = publishedGoods.length >= pageSize + + console.log('已上架货源加载完成,数量:', filteredGoods.length, ',是否有更多:', hasMore) + + return { goods: filteredGoods, hasMore: hasMore } + } else { + console.error('加载已上架货源失败:', res.message) + return { goods: [], hasMore: false } + } + } catch (err) { + console.error('加载已上架货源失败:', err) + return { goods: [], hasMore: false } + } finally { + this.setData({ + isLoadingPublished: false, + currentLoadingType: '' + }) + } + }, + + /** + * 加载售空(sold_out)状态的货源 - 支持分页 + */ + async loadSoldOutGoods(page = 1, pageSize = this.data.pageSize) { + if (this.data.isLoadingSoldOut) return { goods: [], hasMore: true } + + this.setData({ + isLoadingSoldOut: true, + currentLoadingType: 'soldOut' + }) + + console.log('开始加载售空货源,分页参数:', { + page, + pageSize, + keyword: this.data.searchKeyword + }) + + try { + const res = await API.getGoodsList({ + page: page, + pageSize: pageSize, + keyword: this.data.searchKeyword + }) + + if (res.success) { + let soldOutGoods = res.products || [] + + // 数据格式化处理 + soldOutGoods = soldOutGoods.map(item => { + // 确定creatorName + const sellerNickName = item.seller?.nickName || item.seller?.sellerNickName || item.seller?.name || '未知'; + const creatorName = sellerNickName; - // 应用筛选条件和搜索过滤 - const originalList = [...newGoodsList] + // 处理媒体URL + const imageUrls = item.imageUrls || item.images || [] + const formattedImageUrls = Array.isArray(imageUrls) ? imageUrls : [imageUrls] + const mediaItems = formattedImageUrls.map(url => ({ + url: url, + type: isVideoUrl(url) ? 'video' : 'image' + })) - // 搜索逻辑:如果有搜索关键词,只应用搜索过滤,不应用筛选条件 - // 这样搜索时能找到所有匹配的商品,不受筛选条件限制 - let filteredList; - if (this.data.searchKeyword && this.data.searchKeyword.trim() !== '') { - // 有搜索关键词时,只应用搜索过滤 - filteredList = this.searchGoodsList(newGoodsList, this.data.searchKeyword) - } else { - // 没有搜索关键词时,应用筛选条件 - filteredList = this.filterGoodsList(newGoodsList) + // 处理商品状态 + let status = item.status + const isSoldOut = status === 'sold_out' || + status === 'sold' || + status === 'out_of_stock' || + (item.supplyStatus && item.supplyStatus.includes('售空')); + + if (isSoldOut) { + status = 'sold_out' + } else if (status !== 'published') { + status = 'published' } - // 排序:已上架商品排在前面,售空商品排在后面 - filteredList.sort((a, b) => { - if (a.status === 'published' && b.status === 'sold_out') { - return -1 // 已上架排在前面 - } else if (a.status === 'sold_out' && b.status === 'published') { - return 1 // 售空排在后面 - } else { - // 相同状态下,按显示时间(优先更新时间)倒序排序 - const timeA = new Date(a.updated_at || a.updatedAt || a.created_at || a.createTime).getTime() - const timeB = new Date(b.updated_at || b.updatedAt || b.created_at || b.createTime).getTime() - return timeB - timeA - } - }) - - console.log('处理并筛选后的产品列表:', filteredList) - console.log('筛选前后数量对比:', originalList.length, '->', filteredList.length) - - // 处理分页逻辑 - let updatedGoodsList = this.data.currentPage === 1 ? filteredList : [...this.data.goodsList, ...filteredList] + // 只保留sold_out状态的商品 + if (status !== 'sold_out') { + return null + } - // 对整个列表进行排序,确保已上架商品始终在前面,售空商品在后面 - updatedGoodsList.sort((a, b) => { - if (a.status === 'published' && b.status === 'sold_out') { - return -1 // 已上架排在前面 - } else if (a.status === 'sold_out' && b.status === 'published') { - return 1 // 售空排在后面 - } else { - // 相同状态下,按创建时间倒序排序 - const timeA = new Date(a.created_at || a.createTime).getTime() - const timeB = new Date(b.created_at || b.createTime).getTime() - return timeB - timeA + // 处理价格 + let processedPrice = item.price; + if (processedPrice && typeof processedPrice === 'string') { + const priceArray = processedPrice.split(/[,,、]/).map(p => p.trim()).filter(p => p); + if (priceArray.length > 0) { + processedPrice = priceArray[0]; } - }) + } - // 判断是否还有更多数据 - // 正确逻辑:如果API返回的原始数据数量小于pageSize,说明没有更多数据 - // 即使筛选后的数据量小于pageSize,只要API返回的原始数据数量等于pageSize,就应该继续尝试加载更多数据 - const hasMore = res.products.length >= this.data.pageSize + const productName = item.productName || item.name || '未命名商品'; + const displayTime = item.updated_at || item.updatedAt || item.created_at || item.createTime; - console.log('分页判断:', { - updatedGoodsListLength: updatedGoodsList.length, - originalDataLength: res.products.length, - pageSize: this.data.pageSize, - hasMore: hasMore + return { + ...item, + productName: productName, + name: productName, + status: status, + price: processedPrice, + formattedCreatedAt: this.formatDateTime(displayTime), + creatorName: creatorName, + imageUrls: formattedImageUrls, + mediaItems: mediaItems + } + }).filter(Boolean) // 过滤掉null值 + + // 应用筛选和搜索 + let filteredGoods = soldOutGoods + if (this.data.searchKeyword && this.data.searchKeyword.trim() !== '') { + filteredGoods = this.searchGoodsList(filteredGoods, this.data.searchKeyword) + } else { + filteredGoods = this.filterGoodsList(filteredGoods) + } + + // 按时间倒序排序 + filteredGoods.sort((a, b) => { + const timeA = new Date(a.updated_at || a.updatedAt || a.created_at || a.createTime).getTime() + const timeB = new Date(b.updated_at || b.updatedAt || b.created_at || b.createTime).getTime() + return timeB - timeA + }) + + // 判断是否有更多数据 + const hasMore = soldOutGoods.length >= pageSize + + console.log('售空货源加载完成,数量:', filteredGoods.length, ',是否有更多:', hasMore) + + return { goods: filteredGoods, hasMore: hasMore } + } else { + console.error('加载售空货源失败:', res.message) + return { goods: [], hasMore: false } + } + } catch (err) { + console.error('加载售空货源失败:', err) + return { goods: [], hasMore: false } + } finally { + this.setData({ + isLoadingSoldOut: false, + currentLoadingType: '' + }) + } + }, + + /** + * 检查缓存是否有效 + */ + isCacheValid() { + const now = Date.now() + const cache = this.data.cache + return cache.timestamp > 0 && now - cache.timestamp < cache.expiry + }, + + /** + * 加载货源列表 - 先加载已上架,再加载售空,支持分页和缓存 + */ + async loadGoodsList(isLoadMore = false) { + if (this.data.isLoading) return + + // 如果是初始加载,重置分页状态 + if (!isLoadMore) { + this.setData({ + isLoading: true, + publishedLoaded: false, + soldOutLoaded: false, + goodsList: [], + publishedCurrentPage: 1, + publishedHasMore: true, + soldOutCurrentPage: 1, + soldOutHasMore: true + }) + } else { + this.setData({ + isLoading: true + }) + } + + console.log('开始加载货源列表,参数:', { + keyword: this.data.searchKeyword, + activeFilter: this.data.activeFilter, + useCache: this.isCacheValid(), + isLoadMore: isLoadMore, + publishedCurrentPage: this.data.publishedCurrentPage, + publishedHasMore: this.data.publishedHasMore, + soldOutCurrentPage: this.data.soldOutCurrentPage, + soldOutHasMore: this.data.soldOutHasMore + }) + + try { + // 如果是初始加载,检查缓存是否有效 + if (!isLoadMore && this.isCacheValid()) { + console.log('使用缓存数据') + const cache = this.data.cache + + this.setData({ + goodsList: [...cache.publishedGoods, ...cache.soldOutGoods], + publishedLoaded: true, + soldOutLoaded: true, + publishedHasMore: false, + soldOutHasMore: false, + total: cache.publishedGoods.length + cache.soldOutGoods.length + }) + + return + } + + console.log('缓存无效或加载更多,从服务器获取数据') + + let newGoods = [] + let updatedPublishedHasMore = this.data.publishedHasMore + let updatedSoldOutHasMore = this.data.soldOutHasMore + + // 1. 如果已上架商品还有更多,继续加载已上架商品 + if (this.data.publishedHasMore) { + console.log('加载已上架商品第', this.data.publishedCurrentPage, '页') + const publishedResult = await this.loadPublishedGoods( + this.data.publishedCurrentPage, + this.data.pageSize + ) + + newGoods = publishedResult.goods + updatedPublishedHasMore = publishedResult.hasMore + + // 如果是加载更多,追加数据;否则替换数据 + this.setData({ + goodsList: isLoadMore ? [...this.data.goodsList, ...newGoods] : newGoods, + publishedHasMore: updatedPublishedHasMore + }) + + // 如果已上架商品还有更多,更新页码,返回等待下一次加载 + if (updatedPublishedHasMore) { + this.setData({ + publishedCurrentPage: this.data.publishedCurrentPage + 1 }) - + return + } else { + // 已上架商品加载完成 this.setData({ - goodsList: updatedGoodsList, - hasMore: hasMore, - total: total + publishedLoaded: true + }) + } + + // 添加缓冲,避免请求太快 + await new Promise(resolve => setTimeout(resolve, 500)) + } + + // 2. 如果已上架商品加载完,开始加载售空商品 + if (!this.data.publishedHasMore && this.data.soldOutHasMore) { + console.log('加载售空商品第', this.data.soldOutCurrentPage, '页') + const soldOutResult = await this.loadSoldOutGoods( + this.data.soldOutCurrentPage, + this.data.pageSize + ) + + newGoods = soldOutResult.goods + updatedSoldOutHasMore = soldOutResult.hasMore + + // 追加售空商品数据 + this.setData({ + goodsList: [...this.data.goodsList, ...newGoods], + soldOutHasMore: updatedSoldOutHasMore + }) + + // 如果售空商品还有更多,更新页码 + if (updatedSoldOutHasMore) { + this.setData({ + soldOutCurrentPage: this.data.soldOutCurrentPage + 1 }) - - // 移除递归调用逻辑,避免无限递归风险 - // 用户可以通过正常的上拉加载获取更多数据 } else { - console.log('没有产品数据返回') + // 售空商品加载完成 this.setData({ - goodsList: [], - hasMore: false, - total: 0 + soldOutLoaded: true }) } - } else { - console.error('API调用失败:', res.message) - wx.showToast({ - title: res.message || '获取货源列表失败', - icon: 'none' + } + + console.log('货源列表加载完成,当前总数:', this.data.goodsList.length) + + // 如果是初始加载且所有数据加载完成,更新缓存 + if (!isLoadMore && !this.data.publishedHasMore && !this.data.soldOutHasMore) { + // 分离已上架和售空商品 + const publishedGoods = this.data.goodsList.filter(item => item.status === 'published') + const soldOutGoods = this.data.goodsList.filter(item => item.status === 'sold_out') + + this.setData({ + 'cache.publishedGoods': publishedGoods, + 'cache.soldOutGoods': soldOutGoods, + 'cache.timestamp': Date.now() }) } + } catch (err) { console.error('获取货源列表失败:', err) wx.showToast({ title: '获取货源列表失败: ' + err.message, icon: 'none' }) + + // 加载失败时,如果是初始加载,尝试使用缓存数据 + if (!isLoadMore && (this.data.cache.publishedGoods.length > 0 || this.data.cache.soldOutGoods.length > 0)) { + console.log('使用缓存数据作为 fallback') + const cache = this.data.cache + this.setData({ + goodsList: [...cache.publishedGoods, ...cache.soldOutGoods], + publishedLoaded: true, + soldOutLoaded: true, + publishedHasMore: false, + soldOutHasMore: false, + total: cache.publishedGoods.length + cache.soldOutGoods.length + }) + } } finally { // 结束下拉刷新和加载状态 this.setData({ diff --git a/pages/goods/index.wxml b/pages/goods/index.wxml index 6fd4009..a49906a 100644 --- a/pages/goods/index.wxml +++ b/pages/goods/index.wxml @@ -135,7 +135,7 @@ - + 货源正在快马加鞭的赶来