2 changed files with 208 additions and 2 deletions
@ -0,0 +1,206 @@ |
|||||
|
// utils/internal-goods.js
|
||||
|
// 内部货源管理模块
|
||||
|
const API = require('./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']; |
||||
|
for (const ext of videoExtensions) { |
||||
|
if (lowerUrl.endsWith(ext)) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// 格式化时间
|
||||
|
function formatDateTime(dateString) { |
||||
|
if (!dateString) return '未知时间'; |
||||
|
|
||||
|
// 检查是否已经是格式化好的北京时间字符串(如:2026-01-05 17:30)
|
||||
|
if (typeof dateString === 'string' && /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/.test(dateString)) { |
||||
|
// 直接返回格式化好的字符串,只保留到分钟
|
||||
|
return dateString.slice(0, 16); |
||||
|
} |
||||
|
|
||||
|
// 检查是否是ISO格式的字符串(如:2026-01-05T12:00:00.000Z)
|
||||
|
if (typeof dateString === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/.test(dateString)) { |
||||
|
// 转换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; |
||||
|
} |
||||
|
|
||||
|
// 构建商品对象的辅助方法 - 增强版,确保所有必要字段都有默认值和正确格式
|
||||
|
function buildProductObject(goodsItem) { |
||||
|
const imageUrls = goodsItem.imageUrls || goodsItem.images || []; |
||||
|
const formattedImageUrls = Array.isArray(imageUrls) ? imageUrls : [imageUrls]; |
||||
|
const mediaItems = formattedImageUrls.map(url => ({ |
||||
|
url: url, |
||||
|
type: isVideoUrl(url) ? 'video' : 'image' |
||||
|
})); |
||||
|
|
||||
|
// 确定creatorName
|
||||
|
const sellerNickName = goodsItem.seller?.nickName || goodsItem.seller?.sellerNickName || goodsItem.seller?.name || '未知'; |
||||
|
const creatorName = sellerNickName; |
||||
|
|
||||
|
// 处理商品状态
|
||||
|
let status = goodsItem.status; |
||||
|
const isSoldOut = status === 'sold_out' || |
||||
|
status === 'sold' || |
||||
|
status === 'out_of_stock' || |
||||
|
(goodsItem.supplyStatus && goodsItem.supplyStatus.includes('售空')); |
||||
|
|
||||
|
if (isSoldOut) { |
||||
|
status = 'sold_out'; |
||||
|
} else if (status !== 'published') { |
||||
|
status = 'published'; |
||||
|
} |
||||
|
|
||||
|
// 处理价格
|
||||
|
let processedPrice = goodsItem.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 = goodsItem.productName || goodsItem.name || '未命名商品'; |
||||
|
const displayTime = goodsItem.updated_at || goodsItem.updatedAt || goodsItem.created_at || goodsItem.createTime; |
||||
|
|
||||
|
return { |
||||
|
...goodsItem, |
||||
|
productName: productName, |
||||
|
name: productName, |
||||
|
status: status, |
||||
|
price: processedPrice, |
||||
|
formattedCreatedAt: formatDateTime(displayTime), |
||||
|
creatorName: creatorName, |
||||
|
imageUrls: formattedImageUrls, |
||||
|
mediaItems: mediaItems |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
// 获取商品列表的方法(用于刷新商品信息)- 修复接口路径和请求方式
|
||||
|
function getProducts() { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
// 从本地存储获取openid
|
||||
|
const openid = wx.getStorageSync('openid') || ''; |
||||
|
|
||||
|
// 使用正确的接口路径和POST请求方式
|
||||
|
API.request('/api/product/list', 'POST', { |
||||
|
openid: openid, |
||||
|
status: 'all', // 请求所有状态的商品(除了hidden)
|
||||
|
viewMode: 'buyer', // 使用buyer模式获取所有商品,而非仅当前用户的商品
|
||||
|
page: 1, |
||||
|
pageSize: 100 // 获取足够多的商品
|
||||
|
}).then(res => { |
||||
|
if (res && (res.code === 200 || res.success) && res.products) { |
||||
|
// 将商品列表存储到本地缓存
|
||||
|
wx.setStorageSync('goods', res.products || []); |
||||
|
resolve(res.products); |
||||
|
} else { |
||||
|
reject(new Error('获取商品列表失败')); |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error('获取商品列表失败:', err); |
||||
|
reject(new Error('获取商品列表失败,请稍后重试')); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 加载所有商品数据 - 辅助方法
|
||||
|
async function loadAllGoodsData() { |
||||
|
try { |
||||
|
// 使用getProducts方法获取所有商品数据
|
||||
|
const allGoods = await getProducts(); |
||||
|
|
||||
|
// 对所有商品进行格式化处理
|
||||
|
const formattedGoods = allGoods.map(item => buildProductObject(item)); |
||||
|
|
||||
|
return formattedGoods; |
||||
|
} catch (err) { |
||||
|
console.error('加载所有商品数据失败:', err); |
||||
|
return []; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 搜索商品列表
|
||||
|
function 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); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 根据筛选条件过滤数据
|
||||
|
function filterGoodsList(goodsList, filterConfig, activeFilter) { |
||||
|
if (activeFilter === 'all') { |
||||
|
return goodsList; |
||||
|
} |
||||
|
|
||||
|
const allowedCreators = filterConfig[activeFilter] || []; |
||||
|
return goodsList.filter(item => { |
||||
|
return allowedCreators.includes(item.creatorName); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
getProducts: getProducts, |
||||
|
loadAllGoodsData: loadAllGoodsData, |
||||
|
searchGoodsList: searchGoodsList, |
||||
|
filterGoodsList: filterGoodsList, |
||||
|
buildProductObject: buildProductObject, |
||||
|
formatDateTime: formatDateTime, |
||||
|
isVideoUrl: isVideoUrl |
||||
|
}; |
||||
Loading…
Reference in new issue