// 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 };