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.
468 lines
15 KiB
468 lines
15 KiB
|
1 month ago
|
Page({
|
||
|
|
data: {
|
||
|
|
productName: '',
|
||
|
|
specifications: [],
|
||
|
|
loading: false,
|
||
|
|
error: ''
|
||
|
|
},
|
||
|
|
onLoad(options) {
|
||
|
|
let productName = '';
|
||
|
|
// 首先检查URL参数
|
||
|
|
if (options.productName) {
|
||
|
|
productName = options.productName;
|
||
|
|
} else {
|
||
|
|
// 然后检查本地存储(用于wx.switchTab导航)
|
||
|
|
productName = wx.getStorageSync('selectedProductName') || '';
|
||
|
|
// 清除本地存储中的商品名称,避免影响下次进入
|
||
|
|
if (productName) {
|
||
|
|
wx.removeStorageSync('selectedProductName');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (productName) {
|
||
|
|
this.setData({ productName: productName });
|
||
|
|
this.loadSpecifications(productName);
|
||
|
|
} else {
|
||
|
|
// 如果没有商品名称参数,跳转到商品列表页面
|
||
|
|
wx.redirectTo({
|
||
|
|
url: '/pages/evaluate2/product-list'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
loadSpecifications(productName) {
|
||
|
|
this.setData({
|
||
|
|
loading: true,
|
||
|
|
specifications: [],
|
||
|
|
error: '' // 清空错误信息,确保加载时只显示加载状态
|
||
|
|
});
|
||
|
|
|
||
|
|
// 尝试从本地存储获取商品规格映射数据
|
||
|
|
const productSpecsMap = wx.getStorageSync('evaluate2ProductSpecsMap') || {};
|
||
|
|
|
||
|
|
if (productSpecsMap && productSpecsMap[productName]) {
|
||
|
|
console.log('从本地存储获取商品规格数据');
|
||
|
|
|
||
|
|
// 提取该商品的规格和价格信息
|
||
|
|
const productSpecs = productSpecsMap[productName];
|
||
|
|
|
||
|
|
// 处理规格数据
|
||
|
|
const specPriceMap = {};
|
||
|
|
productSpecs.forEach(item => {
|
||
|
|
const specStr = item.specification;
|
||
|
|
const price = item.price;
|
||
|
|
|
||
|
|
// 价格为空的不参与计算
|
||
|
|
if (!price || price.trim() === '') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (specStr.length > 0) {
|
||
|
|
// 处理逗号分隔的多个规格
|
||
|
|
let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
|
||
|
|
|
||
|
|
// 进一步处理规格,确保每个规格都是独立的
|
||
|
|
const processedSpecs = [];
|
||
|
|
specs.forEach(spec => {
|
||
|
|
if (spec.includes(',')) {
|
||
|
|
const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
|
||
|
|
processedSpecs.push(...subSpecs);
|
||
|
|
} else {
|
||
|
|
processedSpecs.push(spec);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
specs = processedSpecs;
|
||
|
|
|
||
|
|
// 处理逗号分隔的多个价格
|
||
|
|
const prices = price.split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
|
||
|
|
|
||
|
|
// 价格为空的不参与计算
|
||
|
|
if (prices.length === 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 将规格和价格配对
|
||
|
|
specs.forEach((spec, index) => {
|
||
|
|
if (spec.length > 0) {
|
||
|
|
// 确保价格索引不超出范围
|
||
|
|
const priceIndex = index % prices.length;
|
||
|
|
const matchedPrice = prices[priceIndex] || '';
|
||
|
|
|
||
|
|
// 只有当价格不为空时才添加该规格
|
||
|
|
if (matchedPrice && matchedPrice.trim() !== '') {
|
||
|
|
// 收集相同规格的所有价格,以便计算平均值
|
||
|
|
if (!specPriceMap[spec]) {
|
||
|
|
specPriceMap[spec] = [];
|
||
|
|
}
|
||
|
|
specPriceMap[spec].push(matchedPrice);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// 转换为规格对象数组
|
||
|
|
const specifications = Object.keys(specPriceMap).map(spec => {
|
||
|
|
const prices = specPriceMap[spec];
|
||
|
|
|
||
|
|
// 解析规格
|
||
|
|
const specInfo = this.parseSpecification(spec);
|
||
|
|
|
||
|
|
// 处理每个价格
|
||
|
|
const processedPrices = prices.map(price => {
|
||
|
|
if (!price || price.trim() === '' || isNaN(parseFloat(price))) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const priceValue = parseFloat(price);
|
||
|
|
|
||
|
|
// 价格<10的需要按照公式计算
|
||
|
|
if (priceValue < 10 && specInfo) {
|
||
|
|
if (specInfo.type === '净重') {
|
||
|
|
// 净重:规格平均值 × 价格
|
||
|
|
return specInfo.avg * priceValue;
|
||
|
|
} else if (specInfo.type === '毛重') {
|
||
|
|
// 毛重:(规格平均值 - 5) × 价格
|
||
|
|
return (specInfo.avg - 5) * priceValue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// 价格>=10的直接使用
|
||
|
|
return priceValue;
|
||
|
|
}).filter(price => price > 0); // 过滤掉0值
|
||
|
|
|
||
|
|
// 计算处理后价格的平均值
|
||
|
|
let finalPrice = 0;
|
||
|
|
let finalPriceText = '';
|
||
|
|
|
||
|
|
if (processedPrices.length > 0) {
|
||
|
|
const sum = processedPrices.reduce((acc, price) => acc + price, 0);
|
||
|
|
finalPrice = sum / processedPrices.length;
|
||
|
|
finalPriceText = finalPrice.toFixed(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
const specObj = {
|
||
|
|
name: spec,
|
||
|
|
price: finalPriceText,
|
||
|
|
priceText: finalPriceText,
|
||
|
|
finalPrice: finalPrice,
|
||
|
|
finalPriceText: finalPriceText
|
||
|
|
};
|
||
|
|
|
||
|
|
return specObj;
|
||
|
|
});
|
||
|
|
|
||
|
|
// 对规格进行排序
|
||
|
|
specifications.sort((a, b) => {
|
||
|
|
// 解析两个规格
|
||
|
|
const specA = this.parseSpecification(a.name);
|
||
|
|
const specB = this.parseSpecification(b.name);
|
||
|
|
|
||
|
|
// 如果有一个规格解析失败,保持原顺序
|
||
|
|
if (!specA || !specB) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 1. 按类型排序:净重在前,毛重在后
|
||
|
|
if (specA.type !== specB.type) {
|
||
|
|
return specA.type === '净重' ? -1 : 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. 按规格最小值排序:从小到大
|
||
|
|
return specA.min - specB.min;
|
||
|
|
});
|
||
|
|
|
||
|
|
this.setData({
|
||
|
|
specifications: specifications,
|
||
|
|
error: '', // 清除之前的错误
|
||
|
|
loading: false
|
||
|
|
});
|
||
|
|
|
||
|
|
// 结束下拉刷新
|
||
|
|
wx.stopPullDownRefresh();
|
||
|
|
} else {
|
||
|
|
// 如果本地存储中没有数据,尝试从本地存储获取原始商品数据
|
||
|
|
const allProducts = wx.getStorageSync('allProducts') || [];
|
||
|
|
|
||
|
|
if (allProducts.length > 0) {
|
||
|
|
console.log('从本地存储获取原始商品数据');
|
||
|
|
this.processSpecifications(productName, allProducts);
|
||
|
|
} else {
|
||
|
|
// 如果本地没有数据,再请求服务器
|
||
|
|
console.log('本地存储中没有数据,请求服务器获取商品数据');
|
||
|
|
const api = require('../../utils/api');
|
||
|
|
api.getProducts(1, 1000, 'all', '').then(result => {
|
||
|
|
// 从返回对象中提取products数组
|
||
|
|
const products = result.products || [];
|
||
|
|
this.processSpecifications(productName, products);
|
||
|
|
}).catch(err => {
|
||
|
|
console.error('获取规格失败:', err);
|
||
|
|
this.setData({
|
||
|
|
error: '获取规格失败,请稍后重试',
|
||
|
|
loading: false
|
||
|
|
});
|
||
|
|
|
||
|
|
// 结束下拉刷新
|
||
|
|
wx.stopPullDownRefresh();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
// 解析规格,提取类型(净重/毛重)和数值范围
|
||
|
|
parseSpecification(spec) {
|
||
|
|
const weightMatch = spec.match(/(净重|毛重)(\d+)-(\d+)/);
|
||
|
|
if (weightMatch) {
|
||
|
|
const type = weightMatch[1]; // 净重或毛重
|
||
|
|
const min = parseFloat(weightMatch[2]);
|
||
|
|
const max = parseFloat(weightMatch[3]);
|
||
|
|
const avg = (min + max) / 2;
|
||
|
|
return {
|
||
|
|
type: type,
|
||
|
|
min: min,
|
||
|
|
max: max,
|
||
|
|
avg: avg
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
},
|
||
|
|
|
||
|
|
processSpecifications(productName, products) {
|
||
|
|
console.log('处理的商品数据数量:', products.length);
|
||
|
|
console.log('当前处理的商品名称:', productName);
|
||
|
|
|
||
|
|
// 检查products是否为空
|
||
|
|
if (!products || products.length === 0) {
|
||
|
|
console.error('商品数据为空');
|
||
|
|
this.setData({
|
||
|
|
error: '商品数据为空',
|
||
|
|
loading: false
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 过滤出当前商品名称的所有商品
|
||
|
|
const filteredProducts = products.filter(product => {
|
||
|
|
const match = product.productName === productName;
|
||
|
|
console.log('商品:', product.productName, '规格:', product.specification, '价格:', product.price, '匹配:', match);
|
||
|
|
return match;
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log('过滤后的商品数量:', filteredProducts.length);
|
||
|
|
console.log('过滤后的商品详情:', filteredProducts);
|
||
|
|
|
||
|
|
// 检查filteredProducts是否为空
|
||
|
|
if (filteredProducts.length === 0) {
|
||
|
|
console.error('未找到商品名称为"' + productName + '"的商品');
|
||
|
|
this.setData({
|
||
|
|
error: '未找到对应商品名称的商品',
|
||
|
|
loading: false
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 提取规格和价格,处理可能的空值和空格
|
||
|
|
const specPriceMap = {};
|
||
|
|
filteredProducts.forEach((product, productIndex) => {
|
||
|
|
const specStr = (product.specification || product.spec || '').trim();
|
||
|
|
const price = product.price || '';
|
||
|
|
|
||
|
|
console.log(`处理第${productIndex + 1}个商品: 规格字符串='${specStr}', 价格字符串='${price}'`);
|
||
|
|
|
||
|
|
// 价格为空的不参与计算
|
||
|
|
if (!price || price.trim() === '') {
|
||
|
|
console.log(`商品价格为空,跳过处理`);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (specStr.length > 0) {
|
||
|
|
// 处理逗号分隔的多个规格,确保每个规格都被正确分割
|
||
|
|
// 首先按逗号分割
|
||
|
|
let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
|
||
|
|
|
||
|
|
// 进一步处理规格,确保每个规格都是独立的
|
||
|
|
const processedSpecs = [];
|
||
|
|
specs.forEach(spec => {
|
||
|
|
// 检查规格是否包含多个规格(例如:"净重29-30,净重31-32")
|
||
|
|
if (spec.includes(',')) {
|
||
|
|
// 按中文逗号分割
|
||
|
|
const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
|
||
|
|
processedSpecs.push(...subSpecs);
|
||
|
|
} else {
|
||
|
|
processedSpecs.push(spec);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
specs = processedSpecs;
|
||
|
|
|
||
|
|
// 处理逗号分隔的多个价格
|
||
|
|
const prices = (price || '').split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
|
||
|
|
|
||
|
|
console.log(`规格数组:`, specs);
|
||
|
|
console.log(`价格数组:`, prices);
|
||
|
|
|
||
|
|
// 价格为空的不参与计算
|
||
|
|
if (prices.length === 0) {
|
||
|
|
console.log(`价格数组为空,跳过处理`);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 将规格和价格配对
|
||
|
|
specs.forEach((spec, index) => {
|
||
|
|
if (spec.length > 0) {
|
||
|
|
// 确保价格索引不超出范围
|
||
|
|
const priceIndex = index % prices.length;
|
||
|
|
const matchedPrice = prices[priceIndex] || '';
|
||
|
|
console.log(`规格'${spec}' 配对价格: '${matchedPrice}'`);
|
||
|
|
|
||
|
|
// 只有当价格不为空时才添加该规格
|
||
|
|
if (matchedPrice && matchedPrice.trim() !== '') {
|
||
|
|
// 收集相同规格的所有价格,以便计算平均值
|
||
|
|
if (!specPriceMap[spec]) {
|
||
|
|
specPriceMap[spec] = [];
|
||
|
|
}
|
||
|
|
specPriceMap[spec].push(matchedPrice);
|
||
|
|
} else {
|
||
|
|
console.log(`规格'${spec}' 价格为空,不添加`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// 转换为规格对象数组
|
||
|
|
const specifications = Object.keys(specPriceMap).map(spec => {
|
||
|
|
const prices = specPriceMap[spec];
|
||
|
|
console.log(`规格'${spec}' 的所有原始价格:`, prices);
|
||
|
|
|
||
|
|
// 解析规格
|
||
|
|
const specInfo = this.parseSpecification(spec);
|
||
|
|
|
||
|
|
// 处理每个价格
|
||
|
|
const processedPrices = prices.map(price => {
|
||
|
|
if (!price || price.trim() === '' || isNaN(parseFloat(price))) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const priceValue = parseFloat(price);
|
||
|
|
console.log(`处理价格: ${priceValue}`);
|
||
|
|
|
||
|
|
// 价格<10的需要按照公式计算
|
||
|
|
if (priceValue < 10 && specInfo) {
|
||
|
|
console.log(`价格 ${priceValue} < 10,按照公式计算`);
|
||
|
|
if (specInfo.type === '净重') {
|
||
|
|
// 净重:规格平均值 × 价格
|
||
|
|
return specInfo.avg * priceValue;
|
||
|
|
} else if (specInfo.type === '毛重') {
|
||
|
|
// 毛重:(规格平均值 - 5) × 价格
|
||
|
|
return (specInfo.avg - 5) * priceValue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// 价格>=10的直接使用
|
||
|
|
return priceValue;
|
||
|
|
}).filter(price => price > 0); // 过滤掉0值
|
||
|
|
|
||
|
|
console.log(`规格'${spec}' 处理后的价格:`, processedPrices);
|
||
|
|
|
||
|
|
// 计算处理后价格的平均值
|
||
|
|
let finalPrice = 0;
|
||
|
|
let finalPriceText = '';
|
||
|
|
|
||
|
|
if (processedPrices.length > 0) {
|
||
|
|
const sum = processedPrices.reduce((acc, price) => acc + price, 0);
|
||
|
|
finalPrice = sum / processedPrices.length;
|
||
|
|
finalPriceText = finalPrice.toFixed(2);
|
||
|
|
console.log(`规格'${spec}' 处理后价格的平均值: ${finalPriceText} (基于 ${processedPrices.length} 个价格)`);
|
||
|
|
} else {
|
||
|
|
console.log(`规格'${spec}' 没有有效价格`);
|
||
|
|
}
|
||
|
|
|
||
|
|
const specObj = {
|
||
|
|
name: spec,
|
||
|
|
price: finalPriceText,
|
||
|
|
priceText: finalPriceText,
|
||
|
|
finalPrice: finalPrice,
|
||
|
|
finalPriceText: finalPriceText
|
||
|
|
};
|
||
|
|
|
||
|
|
console.log('创建的规格对象:', specObj);
|
||
|
|
|
||
|
|
return specObj;
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log('提取的规格和价格:', specifications);
|
||
|
|
|
||
|
|
// 对规格进行排序
|
||
|
|
specifications.sort((a, b) => {
|
||
|
|
// 解析两个规格
|
||
|
|
const specA = this.parseSpecification(a.name);
|
||
|
|
const specB = this.parseSpecification(b.name);
|
||
|
|
|
||
|
|
// 如果有一个规格解析失败,保持原顺序
|
||
|
|
if (!specA || !specB) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 1. 按类型排序:净重在前,毛重在后
|
||
|
|
if (specA.type !== specB.type) {
|
||
|
|
return specA.type === '净重' ? -1 : 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. 按规格最小值排序:从小到大
|
||
|
|
return specA.min - specB.min;
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log('排序后的规格:', specifications);
|
||
|
|
|
||
|
|
this.setData({
|
||
|
|
specifications: specifications,
|
||
|
|
error: '', // 清除之前的错误
|
||
|
|
loading: false
|
||
|
|
});
|
||
|
|
|
||
|
|
// 结束下拉刷新
|
||
|
|
wx.stopPullDownRefresh();
|
||
|
|
},
|
||
|
|
|
||
|
|
// 跳转到规格详情页面
|
||
|
|
goToSpecDetail(e) {
|
||
|
|
const specItem = e.currentTarget.dataset.spec;
|
||
|
|
console.log('点击的规格项:', specItem);
|
||
|
|
console.log('传递的价格:', specItem.finalPriceText);
|
||
|
|
wx.navigateTo({
|
||
|
|
url: `/pages/evaluate2/spec-detail?productName=${encodeURIComponent(this.data.productName)}&specification=${encodeURIComponent(specItem.name)}&price=${encodeURIComponent(specItem.finalPriceText)}`
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
// 返回上一页
|
||
|
|
goBack() {
|
||
|
|
wx.navigateBack();
|
||
|
|
},
|
||
|
|
|
||
|
|
// 返回商品列表页面
|
||
|
|
goBackToProductList() {
|
||
|
|
// 从本地存储中获取之前选择的分类
|
||
|
|
const selectedCategory = wx.getStorageSync('selectedCategory') || '';
|
||
|
|
console.log('返回商品列表页面,之前选择的分类:', selectedCategory);
|
||
|
|
|
||
|
|
// 构建跳转URL,如果有分类参数就传递
|
||
|
|
let url = '/pages/evaluate2/product-list';
|
||
|
|
if (selectedCategory) {
|
||
|
|
url += '?category=' + encodeURIComponent(selectedCategory);
|
||
|
|
}
|
||
|
|
|
||
|
|
wx.redirectTo({
|
||
|
|
url: url
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
// 下拉刷新
|
||
|
|
onPullDownRefresh() {
|
||
|
|
console.log('开始下拉刷新');
|
||
|
|
if (this.data.productName) {
|
||
|
|
this.loadSpecifications(this.data.productName);
|
||
|
|
} else {
|
||
|
|
wx.stopPullDownRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|