You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

767 lines
24 KiB

// pages/goods/index.js
const API = require('../../utils/api.js')
// 媒体类型判断函数
function isVideoUrl(url) {
if (!url || typeof url !== 'string') {
return false;
}
const lowerUrl = url.toLowerCase();
const videoExtensions = ['.mp4', '.mov', '.avi', '.wmv', '.flv', '.webm', '.m4v', '.3gp'];
return videoExtensions.some(ext => lowerUrl.endsWith(ext));
}
Page({
// 分享给朋友/群聊
onShareAppMessage() {
return {
title: '内部货源管理 - 鸡蛋贸易平台',
path: '/pages/goods/index',
imageUrl: '/images/你有好蛋.png'
}
},
// 分享到朋友圈
onShareTimeline() {
return {
title: '内部货源管理 - 鸡蛋贸易平台',
query: '',
imageUrl: '/images/你有好蛋.png'
}
},
/**
* 页面的初始数据
*/
data: {
goodsList: [],
isLoading: false,
isRefreshing: false, // 下拉刷新状态
searchKeyword: '',
activeFilter: 'all', // 当前筛选条件:all, small, large
filterConfig: {
small: ['何佳芹', '李真音'], // 小品种创建者
large: ['吴海燕', '陈骏', '刘琴', '杨率','汤敏'] // 大贸易创建者
},
total: 0, // 总数据条数
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 // 售空货源是否加载完成
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.loadGoodsList()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
// 这里的onPullDownRefresh是页面级的,但我们使用的是scroll-view内置的下拉刷新,所以不需要实现这个方法
},
/**
* scroll-view下拉刷新事件处理
*/
onRefresherRefresh() {
if (this.data.isLoading) return
// 清除缓存,确保获取最新数据
this.setData({
isRefreshing: true,
goodsList: [],
isLoading: false,
'cache.publishedGoods': [],
'cache.soldOutGoods': [],
'cache.timestamp': 0
})
this.loadGoodsList()
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
// 检查是否还有更多数据需要加载
const hasMore = this.data.publishedHasMore || this.data.soldOutHasMore
if (hasMore && !this.data.isLoading) {
this.loadGoodsList(true) // 传入true表示加载更多
}
},
/**
* 处理搜索输入 - 添加防抖功能
*/
onSearchInput(e) {
const keyword = e.detail.value;
this.setData({
searchKeyword: keyword
});
// 清除之前的定时器
if (this.data.searchTimer) {
clearTimeout(this.data.searchTimer);
}
// 设置新的定时器,300ms后执行搜索
const searchTimer = setTimeout(() => {
this.searchGoods();
}, 300);
this.setData({
searchTimer: searchTimer
});
},
/**
* 执行搜索
*/
searchGoods() {
if (this.data.isLoading) return
this.setData({
goodsList: [],
// 清除缓存
'cache.publishedGoods': [],
'cache.soldOutGoods': [],
'cache.timestamp': 0
})
this.loadGoodsList()
},
/**
* 清除搜索
*/
clearSearch() {
this.setData({
searchKeyword: '',
goodsList: [],
// 清除缓存
'cache.publishedGoods': [],
'cache.soldOutGoods': [],
'cache.timestamp': 0
})
this.loadGoodsList()
},
/**
* 筛选条件改变
*/
onFilterChange(e) {
if (this.data.isLoading) return
const filter = e.currentTarget.dataset.filter
this.setData({
activeFilter: filter,
goodsList: [],
// 清除缓存
'cache.publishedGoods': [],
'cache.soldOutGoods': [],
'cache.timestamp': 0
})
this.loadGoodsList()
},
/**
* 根据搜索关键词过滤数据 - 确保能搜索到creatorName字段
*/
searchGoodsList(goodsList, keyword) {
if (!keyword || keyword.trim() === '') {
return goodsList
}
const searchTerm = keyword.toLowerCase().trim()
return goodsList.filter(item => {
// 确保creatorName字段存在
const creatorName = item.creatorName || '';
// 检查多个字段是否包含搜索关键词,包括creatorName
const fieldsToCheck = [
// 产品基本信息
item.productName || item.name || '', // 产品名称
item.specification || item.spec || '', // 规格
item.description || item.remark || '', // 描述
item.region || item.area || '', // 地区
item.yolk || item.variety || '', // 蛋黄
item.price || '', // 价格
item.costprice || '', // 采购价格
item.grossWeight || item.weight || '', // 重量
item.category || '', // 种类
item.minOrder || item.quantity || '', // 最小起订量
// 创建人信息
creatorName, // 已处理的创建人名称,确保能搜索到
// 创建/更新时间
item.formattedCreatedAt || item.updated_at || item.updatedAt || item.created_at || item.createdAt || '' // 创建/更新时间
]
// 检查是否有任何字段包含搜索关键词
return fieldsToCheck.some(field => {
return field.toLowerCase().includes(searchTerm)
})
})
},
/**
* 根据筛选条件过滤数据
*/
filterGoodsList(goodsList) {
const { activeFilter, filterConfig } = this.data
if (activeFilter === 'all') {
return goodsList
}
const allowedCreators = filterConfig[activeFilter] || []
return goodsList.filter(item => {
return allowedCreators.includes(item.creatorName)
})
},
/**
* 格式化时间
*/
formatDateTime(dateString) {
if (!dateString) return '未知时间'
// 检查是否已经是格式化好的北京时间字符串(如:2026-01-05 17:30)
if (typeof dateString === 'string') {
if (dateString.includes(' ')) {
// 直接返回格式化好的字符串,只保留到分钟
return dateString.slice(0, 16)
} else if (dateString.includes('T')) {
// 转换ISO格式为本地时间
const date = new Date(dateString)
if (isNaN(date.getTime())) {
return '未知时间'
}
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
const hours = date.getHours().toString().padStart(2, '0')
const minutes = date.getMinutes().toString().padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}`
}
}
// 对于其他格式的字符串,直接返回,不进行转换
return dateString
},
/**
* 点击货源项跳转
*/
onGoodsItemClick(e) {
const goodsItem = e.currentTarget.dataset.item;
// 跳转到货源详情页面(goods-update)
wx.navigateTo({
url: `/pages/goods-update/goods-update?productId=${goodsItem.id || goodsItem.productId}&goodsData=${encodeURIComponent(JSON.stringify(goodsItem))}`
});
},
/**
* 加载商品数据 - 支持分页
*/
async loadGoodsData(page = 1, pageSize = this.data.pageSize, status = 'all', keyword = '') {
try {
// 使用getProducts方法获取商品数据,支持分页和搜索
const result = await API.getProducts(page, pageSize, status, keyword)
console.log('API返回原始数据:', result)
console.log('API返回商品数量:', result.products.length)
console.log('当前分页参数:', { page, pageSize, status, keyword })
// 对商品进行格式化处理
const formattedGoods = result.products.map(item => {
// 确定creatorName
console.log('商品原始数据:', item)
console.log('商品seller字段:', item.seller)
const sellerNickName = item.seller?.nickName || item.seller?.sellerNickName || item.seller?.name || '未知';
const creatorName = sellerNickName;
// 处理媒体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 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'
}
// 处理价格
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];
}
}
const productName = item.productName || item.name || '未命名商品';
const displayTime = item.updated_at || item.updatedAt || item.created_at || item.createTime;
return {
...item,
productName: productName,
name: productName,
status: status,
price: processedPrice,
formattedCreatedAt: this.formatDateTime(displayTime),
creatorName: creatorName,
imageUrls: formattedImageUrls,
mediaItems: mediaItems
}
})
console.log('格式化后的商品数据:', formattedGoods)
return {
goods: formattedGoods,
total: result.total,
hasMore: result.hasMore
}
} catch (err) {
console.error('加载商品数据失败:', err)
return {
goods: [],
total: 0,
hasMore: false
}
}
},
/**
* 加载已上架(published)状态的货源 - 支持分页
*/
async loadPublishedGoods(page = 1, pageSize = this.data.pageSize) {
if (this.data.isLoadingPublished) return { goods: [], hasMore: true }
this.setData({
isLoadingPublished: true,
currentLoadingType: 'published'
})
console.log('开始加载已上架货源,分页参数:', {
page,
pageSize,
keyword: this.data.searchKeyword
})
try {
// 先获取所有商品数据
const allGoods = await this.loadAllGoodsData()
// 过滤出已上架状态的商品
let publishedGoods = allGoods.filter(item => item.status === 'published')
// 应用筛选和搜索
if (this.data.searchKeyword && this.data.searchKeyword.trim() !== '') {
publishedGoods = this.searchGoodsList(publishedGoods, this.data.searchKeyword)
} else {
publishedGoods = this.filterGoodsList(publishedGoods)
}
// 排序逻辑:没有销售价格的商品排在最前面,然后按时间倒序排序
publishedGoods.sort((a, b) => {
// 检查是否有销售价格
const hasPriceA = !!(a.price && a.price.trim() !== '');
const hasPriceB = !!(b.price && b.price.trim() !== '');
// 没有销售价格的排在前面
if (hasPriceA !== hasPriceB) {
return hasPriceA ? 1 : -1;
}
// 都有或都没有销售价格时,按时间倒序排序
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 startIndex = (page - 1) * pageSize
const endIndex = startIndex + pageSize
const paginatedGoods = publishedGoods.slice(startIndex, endIndex)
const hasMore = endIndex < publishedGoods.length
console.log('已上架货源加载完成,数量:', paginatedGoods.length, ',是否有更多:', hasMore)
return { goods: paginatedGoods, hasMore: hasMore }
} 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 allGoods = await this.loadAllGoodsData()
// 过滤出售空状态的商品
let soldOutGoods = allGoods.filter(item => item.status === 'sold_out')
// 应用筛选和搜索
if (this.data.searchKeyword && this.data.searchKeyword.trim() !== '') {
soldOutGoods = this.searchGoodsList(soldOutGoods, this.data.searchKeyword)
} else {
soldOutGoods = this.filterGoodsList(soldOutGoods)
}
// 排序逻辑:没有销售价格的商品排在最前面,然后按时间倒序排序
soldOutGoods.sort((a, b) => {
// 检查是否有销售价格
const hasPriceA = !!(a.price && a.price.trim() !== '');
const hasPriceB = !!(b.price && b.price.trim() !== '');
// 没有销售价格的排在前面
if (hasPriceA !== hasPriceB) {
return hasPriceA ? 1 : -1;
}
// 都有或都没有销售价格时,按时间倒序排序
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 startIndex = (page - 1) * pageSize
const endIndex = startIndex + pageSize
const paginatedGoods = soldOutGoods.slice(startIndex, endIndex)
const hasMore = endIndex < soldOutGoods.length
console.log('售空货源加载完成,数量:', paginatedGoods.length, ',是否有更多:', hasMore)
return { goods: paginatedGoods, hasMore: hasMore }
} 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
})
}
try {
// 检查缓存是否有效
if (!isLoadMore && this.isCacheValid()) {
console.log('使用缓存数据')
const cache = this.data.cache
// 重新应用当前筛选条件到缓存数据
const allCachedGoods = [...cache.publishedGoods, ...cache.soldOutGoods]
const filteredGoods = this.filterGoodsList(allCachedGoods)
console.log('缓存商品数量:', allCachedGoods.length)
console.log('筛选后缓存商品数量:', filteredGoods.length)
this.setData({
goodsList: filteredGoods,
publishedLoaded: true,
soldOutLoaded: true,
publishedHasMore: false,
soldOutHasMore: false,
total: filteredGoods.length
})
return
}
// 1. 处理已上架商品 - 持续加载直到找到足够的符合条件的商品
if (this.data.publishedHasMore) {
let accumulatedFilteredGoods = []
let currentPage = this.data.publishedCurrentPage
let hasMore = true
// 持续加载,直到找到至少20条符合条件的商品或者没有更多数据
while (hasMore && accumulatedFilteredGoods.length < this.data.pageSize) {
// 从服务器获取已上架商品数据,支持分页和搜索
const result = await this.loadGoodsData(
currentPage,
this.data.pageSize,
'published',
this.data.searchKeyword
)
console.log('原始商品数据:', result.goods)
console.log('当前筛选条件:', this.data.activeFilter)
console.log('筛选配置:', this.data.filterConfig)
console.log('分页参数:', { page: currentPage, pageSize: this.data.pageSize })
console.log('hasMore:', result.hasMore)
// 应用筛选逻辑
const filteredGoods = this.filterGoodsList(result.goods)
console.log('筛选后商品数据:', filteredGoods)
console.log('筛选后商品数量:', filteredGoods.length)
// 累积符合条件的商品
accumulatedFilteredGoods = [...accumulatedFilteredGoods, ...filteredGoods]
// 更新状态
hasMore = result.hasMore
currentPage++
// 如果已经找到足够的商品,跳出循环
if (accumulatedFilteredGoods.length >= this.data.pageSize) {
break
}
}
console.log('累积筛选后商品数量:', accumulatedFilteredGoods.length)
// 如果是加载更多,追加数据;否则替换数据
if (accumulatedFilteredGoods.length > 0) {
this.setData({
goodsList: isLoadMore ? [...this.data.goodsList, ...accumulatedFilteredGoods] : accumulatedFilteredGoods
})
}
// 更新页码和hasMore状态
this.setData({
publishedCurrentPage: currentPage,
publishedHasMore: hasMore
})
console.log('已上架商品加载完成,更新页码为:', currentPage, ',是否有更多:', hasMore)
// 如果没有更多数据,标记为加载完成
if (!hasMore) {
this.setData({
publishedLoaded: true
})
console.log('已上架商品加载完成')
}
}
// 2. 处理售空商品 - 持续加载直到找到足够的符合条件的商品
// 对于初始加载,即使已上架商品还有更多,也尝试加载售空商品
// 这样可以确保用户能看到所有类型的商品
if ((!isLoadMore || !this.data.publishedHasMore) && this.data.soldOutHasMore) {
let accumulatedFilteredGoods = []
let currentPage = this.data.soldOutCurrentPage
let hasMore = true
// 持续加载,直到找到至少20条符合条件的商品或者没有更多数据
while (hasMore && accumulatedFilteredGoods.length < this.data.pageSize) {
// 从服务器获取售空商品数据,支持分页和搜索
const result = await this.loadGoodsData(
currentPage,
this.data.pageSize,
'sold_out',
this.data.searchKeyword
)
console.log('售空商品数据:', result.goods)
console.log('售空商品分页参数:', { page: currentPage, pageSize: this.data.pageSize })
console.log('售空商品hasMore:', result.hasMore)
console.log('当前筛选条件:', this.data.activeFilter)
// 应用筛选逻辑
const filteredGoods = this.filterGoodsList(result.goods)
console.log('筛选后售空商品数据:', filteredGoods)
console.log('筛选后售空商品数量:', filteredGoods.length)
// 累积符合条件的商品
accumulatedFilteredGoods = [...accumulatedFilteredGoods, ...filteredGoods]
// 更新状态
hasMore = result.hasMore
currentPage++
// 如果已经找到足够的商品,跳出循环
if (accumulatedFilteredGoods.length >= this.data.pageSize) {
break
}
}
console.log('累积筛选后售空商品数量:', accumulatedFilteredGoods.length)
// 追加售空商品数据
if (accumulatedFilteredGoods.length > 0) {
this.setData({
goodsList: isLoadMore ? [...this.data.goodsList, ...accumulatedFilteredGoods] : [...this.data.goodsList, ...accumulatedFilteredGoods]
})
}
// 更新页码和hasMore状态
this.setData({
soldOutCurrentPage: currentPage,
soldOutHasMore: hasMore
})
console.log('售空商品加载完成,更新页码为:', currentPage, ',是否有更多:', hasMore)
// 如果没有更多数据,标记为加载完成
if (!hasMore) {
this.setData({
soldOutLoaded: true
})
console.log('售空商品加载完成')
}
}
console.log('加载完成后状态:', {
publishedHasMore: this.data.publishedHasMore,
soldOutHasMore: this.data.soldOutHasMore,
publishedCurrentPage: this.data.publishedCurrentPage,
soldOutCurrentPage: this.data.soldOutCurrentPage,
goodsListLength: this.data.goodsList.length
})
// 如果是初始加载且所有数据加载完成,更新缓存
if (!isLoadMore && !this.data.publishedHasMore && !this.data.soldOutHasMore) {
// 由于现在采用分页加载,缓存逻辑需要调整
// 暂时禁用缓存更新,确保每次都从服务器获取最新数据
console.log('分页加载模式,跳过缓存更新')
}
} catch (err) {
wx.showToast({
title: '获取货源列表失败: ' + err.message,
icon: 'none'
})
// 加载失败时,如果是初始加载,尝试使用缓存数据
if (!isLoadMore && (this.data.cache.publishedGoods.length > 0 || this.data.cache.soldOutGoods.length > 0)) {
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({
isLoading: false,
isRefreshing: false
})
}
}
})