diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js index 6d60afe..b0c4eaa 100644 --- a/pages/goods-detail/goods-detail.js +++ b/pages/goods-detail/goods-detail.js @@ -339,7 +339,7 @@ function formatDateTime(dateString) { } // 处理净重、件数、规格和价格数据,将逗号分隔的字符串转换为一一对应的数组 -function processWeightAndQuantityData(weightSpecString, quantityString, specString, priceString, specStatusString) { +function processWeightAndQuantityData(weightSpecString, quantityString, specString, priceString, specStatusString, specPriceChanges = {}) { console.log('===== 处理净重、件数、规格和价格数据 ====='); console.log('输入参数:'); console.log('- weightSpecString:', weightSpecString, '(类型:', typeof weightSpecString, ')'); @@ -450,13 +450,23 @@ function processWeightAndQuantityData(weightSpecString, quantityString, specStri console.log(`第${i}组数据处理结果: weightSpecDisplay=${weightSpecDisplay}, quantity=${quantity}, price=${price}, specStatus=${specStatus}, display=${display}`); + // 检查该规格是否有价格变化 + let priceChangeDirection = null; + for (const spec in specPriceChanges) { + if (weightSpecDisplay.includes(spec)) { + priceChangeDirection = specPriceChanges[spec]; + break; + } + } + result.push({ weightSpec: weightSpecDisplay, quantity: quantity, price: price, specStatus: specStatus, display: display, - isOffShelf: specStatus === '1' + isOffShelf: specStatus === '1', + priceChangeDirection: priceChangeDirection }); } @@ -1286,6 +1296,64 @@ Page({ // 处理grossWeight为null或无效的情况,返回空字符串以支持文字输入 const grossWeightValue = product.grossWeight !== null && product.grossWeight !== undefined ? product.grossWeight : ''; + // 处理价格波动,计算价格变化的方向 + const calculatePriceChangeDirection = (productLog) => { + if (!productLog || !Array.isArray(productLog) || productLog.length === 0) { + return {}; + } + + // 按规格分组日志 + const specLogs = {}; + productLog.forEach(log => { + if (typeof log === 'string') { + // 提取规格信息 + const specMatch = log.match(/将(.+?)规格的销售价格/); + if (specMatch && specMatch[1]) { + const spec = specMatch[1].trim(); + if (!specLogs[spec]) { + specLogs[spec] = []; + } + specLogs[spec].push(log); + } + } + }); + + // 检查每个规格的价格变化 + const specPriceChanges = {}; + for (const spec in specLogs) { + const logs = specLogs[spec]; + if (logs.length >= 2) { + // 提取最近两次的价格 + const latestLog = logs[logs.length - 1]; + const previousLog = logs[logs.length - 2]; + + // 提取价格 + const latestPriceMatch = latestLog.match(/修改为了(.*?)元/); + const previousPriceMatch = previousLog.match(/修改为了(.*?)元/); + + if (latestPriceMatch && previousPriceMatch) { + const latestPrice = parseFloat(latestPriceMatch[1]); + const previousPrice = parseFloat(previousPriceMatch[1]); + + if (!isNaN(latestPrice) && !isNaN(previousPrice)) { + if (latestPrice > previousPrice) { + specPriceChanges[spec] = 'up'; // 价格上升 + } else if (latestPrice < previousPrice) { + specPriceChanges[spec] = 'down'; // 价格下降 + } + } + } + } + } + + return specPriceChanges; // 返回每个规格的价格变化方向 + }; + + // 检查所有可能的产品日志字段名 + const productLog = product.product_log || product.productLog || []; + // 计算每个规格的价格变化方向 + const specPriceChanges = calculatePriceChangeDirection(productLog); + // 处理净重、件数据和规格数据,获取一一对应的显示数组 // 注意:数据库中的规格字段包含净重信息,我们需要与件数数据正确匹配 // 修复:根据用户反馈,数据库中的规格字段内容为:净重46-47,净重44-43,净重47-48 @@ -1415,7 +1483,7 @@ Page({ if (product.spec_status) { specStatusString = String(product.spec_status); } - weightQuantityData = processWeightAndQuantityData(weightSpecString, quantityString, '', priceString, specStatusString); + weightQuantityData = processWeightAndQuantityData(weightSpecString, quantityString, '', priceString, specStatusString, specPriceChanges); console.log('× 非售空分支结果:', weightQuantityData); } @@ -1539,7 +1607,9 @@ Page({ imageUrls: imageUrls || [], mediaItems: mediaItems, // 确保region使用提取后的省份信息,放在最后覆盖所有展开操作 - region: region + region: region, + // 添加价格波动信息 + specPriceChanges: specPriceChanges }; // 调试:打印formattedGoods的imageUrls和mediaItems diff --git a/pages/goods-detail/goods-detail.wxml b/pages/goods-detail/goods-detail.wxml index 2fb8eba..dc4d933 100644 --- a/pages/goods-detail/goods-detail.wxml +++ b/pages/goods-detail/goods-detail.wxml @@ -94,6 +94,8 @@ 价格: {{goodsDetail.displayPrice}} + + (可议价) {{item.display}} + + 已下架 diff --git a/pages/goods-detail/goods-detail.wxss b/pages/goods-detail/goods-detail.wxss index e8db391..801f4fe 100644 --- a/pages/goods-detail/goods-detail.wxss +++ b/pages/goods-detail/goods-detail.wxss @@ -784,6 +784,38 @@ video.slider-media .wx-video-volume-icon { margin-left: 10rpx; } +/* 价格变化箭头样式 */ +.price-change-arrow { + margin-left: 8rpx; + font-size: 32rpx; + font-weight: bold; +} + +.price-change-arrow.up { + color: #ff4d4f; + animation: pulse 2s infinite; +} + +.price-change-arrow.down { + color: #52c41a; + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0% { + opacity: 1; + transform: scale(1); + } + 50% { + opacity: 0.8; + transform: scale(1.1); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + /* 对比价格弹窗样式 */ .compare-modal-overlay { position: fixed; diff --git a/pages/index/index.js b/pages/index/index.js index 0da2f96..9af08e0 100644 --- a/pages/index/index.js +++ b/pages/index/index.js @@ -1073,6 +1073,50 @@ Page({ // 格式化规格显示 const formattedSpec = this.formatSpecification(product.specification || product.spec || '', product.yolk || ''); + // 处理价格波动 + const processPriceChange = (productLog) => { + if (!productLog || !Array.isArray(productLog) || productLog.length === 0) { + return { + hasPriceChange: false, + priceChangeDirection: null + }; + } + + // 检查是否有同规格的第二次日志 + const specLogs = {}; + productLog.forEach(log => { + if (typeof log === 'string') { + // 提取规格信息 + const specMatch = log.match(/将(.+?)规格的销售价格/); + if (specMatch && specMatch[1]) { + const spec = specMatch[1].trim(); + if (!specLogs[spec]) { + specLogs[spec] = []; + } + specLogs[spec].push(log); + } + } + }); + + // 检查是否有规格有多次价格调整 + let hasPriceChange = false; + for (const spec in specLogs) { + if (specLogs[spec].length >= 2) { + hasPriceChange = true; + break; + } + } + + return { + hasPriceChange, + priceChangeDirection: null // 默认为null,在商品详情页中计算具体方向 + }; + }; + + // 检查所有可能的产品日志字段名 + const productLog = product.product_log || product.productLog || []; + const priceChangeInfo = processPriceChange(productLog); + return { ...product, id: productId, // 统一使用id字段 @@ -1102,7 +1146,10 @@ Page({ originalTotalStock: totalStock, // 保留原始计算值用于调试 displaySpecification: formattedSpec.displaySpec, // 格式化后的规格 displayYolk: formattedSpec.displayYolk, // 格式化后的蛋黄 - price: product.price !== undefined ? product.price : '' // 确保price字段存在 + price: product.price !== undefined ? product.price : '', // 确保price字段存在 + // 添加价格波动信息 + hasPriceChange: priceChangeInfo.hasPriceChange, + priceChangeDirection: priceChangeInfo.priceChangeDirection } }) diff --git a/pages/index/index.wxml b/pages/index/index.wxml index 31f4bc9..51e4cfd 100644 --- a/pages/index/index.wxml +++ b/pages/index/index.wxml @@ -323,6 +323,7 @@ 库存:{{item.totalStock && item.totalStock !== '充足' ? item.totalStock + '件' : (item.totalStock || '充足')}} 已售:{{item.originalTotalStock || 0}}件 + 价格有波动 已有{{item.frequency || 0}}人浏览 diff --git a/pages/index/index.wxss b/pages/index/index.wxss index 54d9d52..2eca8fb 100644 --- a/pages/index/index.wxss +++ b/pages/index/index.wxss @@ -1279,6 +1279,29 @@ wx-button:not([size=mini]) { border: 1rpx solid rgba(82, 196, 26, 0.5); } +.status-tag.price-change { + background: transparent; + color: #ff4d4f; + border: none; + font-weight: bold; + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0% { + opacity: 1; + transform: scale(1); + } + 50% { + opacity: 0.7; + transform: scale(1.05); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + /* product-status-row 容器样式 */ .product-status-row { display: flex; diff --git a/pages/order/detail/index.wxml b/pages/order/detail/index.wxml index 0ee08c0..8ca6460 100644 --- a/pages/order/detail/index.wxml +++ b/pages/order/detail/index.wxml @@ -100,11 +100,11 @@ - 二维码 + 产品合格证 - 二维码暂无 + 暂无产品合格证 QR_code: {{orderDetail.QR_code}} diff --git a/project.private.config.json b/project.private.config.json index 073179c..67dfd8e 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -1,6 +1,6 @@ { "libVersion": "3.10.3", - "projectname": "wechatapp", + "projectname": "Mini-Program", "setting": { "urlCheck": false, "coverView": true, diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js index 85e0252..4123481 100644 --- a/server-example/server-mysql.js +++ b/server-example/server-mysql.js @@ -3420,6 +3420,7 @@ app.post('/api/product/list', async (req, res) => { 'producting', 'description', 'frequency', + 'product_log', 'spec_status' ], order: [['created_at', 'DESC']], @@ -3548,6 +3549,35 @@ app.post('/api/product/list', async (req, res) => { productJSON.created_at = getBeijingTimeISOString(); } + // 处理产品日志字段,确保返回数组格式 + if (productJSON.product_log) { + console.log('【产品日志】原始product_log:', productJSON.product_log, '类型:', typeof productJSON.product_log); + if (typeof productJSON.product_log === 'string') { + try { + productJSON.product_log = JSON.parse(productJSON.product_log); + console.log('【产品日志】反序列化后的product_log:', productJSON.product_log, '类型:', typeof productJSON.product_log); + // 确保是数组格式 + if (!Array.isArray(productJSON.product_log)) { + productJSON.product_log = [productJSON.product_log]; + console.log('【产品日志】转换为数组:', productJSON.product_log); + } + } catch (parseError) { + console.error('【产品日志】反序列化失败:', parseError); + // 如果解析失败,将字符串作为单个日志条目 + productJSON.product_log = [productJSON.product_log]; + console.log('【产品日志】转换为单条日志:', productJSON.product_log); + } + } else if (!Array.isArray(productJSON.product_log)) { + // 如果不是字符串也不是数组,转换为数组 + productJSON.product_log = [productJSON.product_log]; + console.log('【产品日志】转换为数组:', productJSON.product_log); + } + } else { + // 如果没有日志,返回空数组 + productJSON.product_log = []; + console.log('【产品日志】没有日志,返回空数组'); + } + // 记录第一个商品的转换信息用于调试 if (products.indexOf(product) === 0) { console.log('商品列表 - 第一个商品毛重字段处理:'); @@ -3555,6 +3585,7 @@ app.post('/api/product/list', async (req, res) => { console.log('- 转换后的值:', productJSON.grossWeight, '类型:', typeof productJSON.grossWeight); console.log('- reservedCount值:', productJSON.reservedCount, '类型:', typeof productJSON.reservedCount); console.log('- seller信息:', JSON.stringify(productJSON.seller)); + console.log('- product_log信息:', JSON.stringify(productJSON.product_log)); } return productJSON;