Browse Source

update

main
Default User 1 day ago
parent
commit
43b350a60f
  1. 305
      pages/freight-calculator/index.js
  2. 9
      pages/freight-calculator/index.wxml
  3. 21
      pages/freight-calculator/index.wxss
  4. 8
      pages/goods-detail/goods-detail.js
  5. 43
      server-example/server-mysql.js

305
pages/freight-calculator/index.js

@ -73,7 +73,7 @@ Page({
destination: [0, 0, 0]
},
// 运输模式
transportModes: ['货拉拉', '运满满', '零担拼车'],
transportModes: ['整车运输', '零担拼车'],
transportModeIndex: 0,
// 包装类型
@ -116,6 +116,7 @@ Page({
complianceStatus: '',
isCompliant: true,
detailText: '',
showDetail: false,
// 车型和车长对应关系
vehicleLengthMap: {
@ -156,9 +157,6 @@ Page({
// 页面加载时的初始化逻辑
console.log('物流运费估算页面加载,options:', options);
// 加载历史记录
this.loadHistoryRecords();
// 初始化地址选择器数据
this.initRegionData();
@ -206,18 +204,26 @@ Page({
});
// 设置出发地为商品所在地
if (goodsData.region) {
const regionInfo = this.parseRegion(goodsData.region);
const regionToUse = goodsData.fullRegion || goodsData.region;
if (regionToUse) {
console.log('商品所在地原始地址:', regionToUse);
const regionInfo = this.parseRegion(regionToUse);
console.log('解析后的地址:', regionInfo);
this.setData({
'origin.province': regionInfo.province || '',
'origin.city': regionInfo.city || '',
'origin.district': regionInfo.district || ''
'origin.district': regionInfo.district || '',
'origin.detail': regionInfo.detail || ''
});
console.log('已设置出发地为商品所在地:', regionInfo);
}
} catch (e) {
console.error('解析货源信息失败:', e);
}
}
// 加载历史记录(在设置完 selectedGoods 后)
this.loadHistoryRecords();
},
// 初始化地址选择器数据
@ -248,12 +254,16 @@ Page({
// 设置出发地为商品所在地
if (goodsItem.region) {
console.log('商品所在地原始地址:', goodsItem.region);
const regionInfo = this.parseRegion(goodsItem.region);
console.log('解析后的地址:', regionInfo);
this.setData({
'origin.province': regionInfo.province || '',
'origin.city': regionInfo.city || '',
'origin.district': regionInfo.district || ''
'origin.district': regionInfo.district || '',
'origin.detail': regionInfo.detail || ''
});
console.log('已设置出发地为商品所在地:', regionInfo);
}
// 设置货物重量(如果有)
@ -269,12 +279,35 @@ Page({
parseRegion: function (region) {
if (!region) return {};
// 简单的地区解析逻辑,实际项目中可能需要更复杂的解析
const parts = region.split(' ');
// 尝试多种分隔符解析地址
let parts = region.split(' ');
if (parts.length === 1) {
// 尝试使用其他分隔符
parts = region.split('\n');
if (parts.length === 1) {
parts = region.split(',');
}
}
console.log('地址解析 - 原始地址:', region);
console.log('地址解析 - 分割后:', parts);
// 提取省份、城市、区县
const province = parts[0] || '';
const city = parts[1] || '';
const district = parts[2] || '';
// 收集区级后面的详细地址信息
let detail = '';
if (parts.length > 3) {
detail = parts.slice(3).join(' ');
}
return {
province: parts[0] || '',
city: parts[1] || '',
district: parts[2] || ''
province: province,
city: city,
district: district,
detail: detail
};
},
@ -282,20 +315,22 @@ Page({
loadHistoryRecords: function () {
this.setData({ loading: true });
const productId = this.data.selectedGoods ? (this.data.selectedGoods.productId || this.data.selectedGoods.id) : undefined;
API.getFreightHistory({
productId: this.data.selectedGoods.productId || this.data.selectedGoods.id
productId: productId
}).then(res => {
this.setData({ loading: false });
if (res.success) {
this.setData({
historyRecords: res.data.records || []
historyRecords: (res.data.records || []).slice(0, 3) // 只显示最近3条记录
});
} else {
console.error('获取历史记录失败:', res.message);
// 失败时使用本地存储作为 fallback
const history = wx.getStorageSync('freightCalculatorHistory') || [];
this.setData({
historyRecords: history.slice(0, 10) // 只显示最近10条记录
historyRecords: history.slice(0, 3) // 只显示最近3条记录
});
}
}).catch(err => {
@ -304,7 +339,7 @@ Page({
// 失败时使用本地存储作为 fallback
const history = wx.getStorageSync('freightCalculatorHistory') || [];
this.setData({
historyRecords: history.slice(0, 10) // 只显示最近10条记录
historyRecords: history.slice(0, 3) // 只显示最近3条记录
});
});
},
@ -331,7 +366,7 @@ Page({
// 更新页面数据
this.setData({
historyRecords: newHistory.slice(0, 10)
historyRecords: newHistory.slice(0, 3)
});
},
@ -907,13 +942,14 @@ Page({
volume: '',
vehicleInfo: '面包车(1.4米): 0-500kg, 0-5m³',
// 计算结果
showResult: false,
feeRange: '',
marketPrice: '',
complianceStatus: '',
isCompliant: true,
detailText: '',
calculationResult: null
showResult: false,
feeRange: '',
marketPrice: '',
complianceStatus: '',
isCompliant: true,
detailText: '',
calculationResult: null,
showDetail: false
});
},
@ -978,6 +1014,109 @@ Page({
}
},
// 将地址转换为经纬度
convertAddressToCoordinates: function (origin, destination) {
return new Promise((resolve, reject) => {
// 转换出发地地址
const convertOrigin = new Promise((resolveOrigin) => {
// 如果出发地已经有经纬度,直接返回
if (origin.latitude && origin.longitude) {
resolveOrigin(origin);
return;
}
// 构建出发地完整地址
const originAddress = `${origin.province}${origin.city}${origin.district}${origin.detail}`;
if (!originAddress) {
resolveOrigin(origin);
return;
}
// 使用腾讯地图地理编码API
wx.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/',
data: {
address: originAddress,
key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77'
},
success: function (res) {
if (res.data.status === 0) {
const location = res.data.result.location;
resolveOrigin({
...origin,
latitude: location.lat,
longitude: location.lng
});
} else {
console.error('出发地地址转换失败:', res.data);
resolveOrigin(origin);
}
},
fail: function (err) {
console.error('出发地地址转换失败:', err);
resolveOrigin(origin);
}
});
});
// 转换目的地地址
const convertDestination = new Promise((resolveDestination) => {
// 如果目的地已经有经纬度,直接返回
if (destination.latitude && destination.longitude) {
resolveDestination(destination);
return;
}
// 构建目的地完整地址
const destinationAddress = `${destination.province}${destination.city}${destination.district}${destination.detail}`;
if (!destinationAddress) {
resolveDestination(destination);
return;
}
// 使用腾讯地图地理编码API
wx.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/',
data: {
address: destinationAddress,
key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77'
},
success: function (res) {
if (res.data.status === 0) {
const location = res.data.result.location;
resolveDestination({
...destination,
latitude: location.lat,
longitude: location.lng
});
} else {
console.error('目的地地址转换失败:', res.data);
resolveDestination(destination);
}
},
fail: function (err) {
console.error('目的地地址转换失败:', err);
resolveDestination(destination);
}
});
});
// 等待两个地址转换完成
Promise.all([convertOrigin, convertDestination]).then(([originWithCoords, destinationWithCoords]) => {
resolve({ originWithCoords, destinationWithCoords });
}).catch(err => {
reject(err);
});
});
},
// 切换费用明细显示/隐藏
toggleDetail: function () {
this.setData({
showDetail: !this.data.showDetail
});
},
// 运输模式选择
bindTransportModeChange: function(e) {
this.setData({
@ -1099,52 +1238,69 @@ Page({
packagingType: packagingType
};
// 调用API计算运费,获取距离信息
API.calculateFreight(params).then(res => {
this.setData({ loading: false });
if (res.success) {
// 使用API返回的距离
const distance = res.data.distance || 100;
// 自动获取当前时间、天气情况和是否节假日
const { weather, holiday, timePeriod } = this.getAutoData();
// 调用计算函数(使用默认等候时间40分钟)
const result = this.calculateEggShippingFee(
transportMode, distance, weight, volume, packagingType, vehicleType, truckLength, 40, weather, holiday, timePeriod
);
// 更新结果
this.setData({
showResult: true,
feeRange: `${result.feeMin} - ${result.feeMax}`,
marketPrice: `${result.marketPrice}`,
complianceStatus: result.compliance.isCompliant ? '✓ 运输方案合规' : '✗ 运输方案不合规',
isCompliant: result.compliance.isCompliant,
detailText: this.generateDetailText(result, transportMode, weight, volume, packagingType, 40),
calculationResult: res.data // 保存API返回的结果
});
// 保存历史记录
this.saveHistoryRecord({
freight: (result.feeMin + result.feeMax) / 2,
distance: distance,
deliveryTime: Math.ceil(distance / 80), // 简单估算,假设平均速度80km/h
feeRange: `${result.feeMin} - ${result.feeMax}`,
marketPrice: result.marketPrice,
complianceStatus: result.compliance.isCompliant ? '合规' : '不合规'
});
} else {
// 先将手写地址转换为经纬度
this.convertAddressToCoordinates(this.data.origin, this.data.destination).then(({ originWithCoords, destinationWithCoords }) => {
// 更新参数中的地址信息,包含经纬度
const paramsWithCoords = {
...params,
origin: originWithCoords,
destination: destinationWithCoords
};
// 调用API计算运费,获取距离信息
API.calculateFreight(paramsWithCoords).then(res => {
this.setData({ loading: false });
if (res.success) {
// 使用API返回的距离
const distance = res.data.distance || 100;
// 自动获取当前时间、天气情况和是否节假日
const { weather, holiday, timePeriod } = this.getAutoData();
// 调用计算函数(使用默认等候时间40分钟)
const result = this.calculateEggShippingFee(
transportMode, distance, weight, volume, packagingType, vehicleType, truckLength, 40, weather, holiday, timePeriod
);
// 更新结果
this.setData({
showResult: true,
feeRange: `${result.feeMin} - ${result.feeMax}元/车`,
marketPrice: `${result.marketPrice}`,
complianceStatus: result.compliance.isCompliant ? '✓ 运输方案合规' : '✗ 运输方案不合规',
isCompliant: result.compliance.isCompliant,
detailText: this.generateDetailText(result, transportMode, weight, volume, packagingType, 40),
calculationResult: res.data // 保存API返回的结果
});
// 保存历史记录
this.saveHistoryRecord({
freight: (result.feeMin + result.feeMax) / 2,
distance: distance,
deliveryTime: Math.ceil(distance / 80), // 简单估算,假设平均速度80km/h
feeRange: `${result.feeMin} - ${result.feeMax}元/车`,
marketPrice: result.marketPrice,
complianceStatus: result.compliance.isCompliant ? '合规' : '不合规'
});
} else {
wx.showToast({
title: res.message || '计算失败,请稍后重试',
icon: 'none'
});
}
}).catch(err => {
this.setData({ loading: false });
console.error('计算运费失败:', err);
wx.showToast({
title: res.message || '计算失败,请稍后重试',
title: '网络错误,请稍后重试',
icon: 'none'
});
}
});
}).catch(err => {
this.setData({ loading: false });
console.error('计算运费失败:', err);
console.error('地址转换失败:', err);
wx.showToast({
title: '网络错误,请稍后重试',
title: '地址转换失败,请稍后重试',
icon: 'none'
});
});
@ -1369,7 +1525,8 @@ Page({
// 检查车型载重
if (complianceParams.maxWeightPerVehicle[vehicleType]) {
if (chargeWeight > complianceParams.maxWeightPerVehicle[vehicleType]) {
// 对于轻泡货物,使用实际重量进行合规性检查,而不是体积重量
if (weight > complianceParams.maxWeightPerVehicle[vehicleType]) {
compliance.isCompliant = false;
compliance.issues.push(`${vehicleType}载重不能超过${complianceParams.maxWeightPerVehicle[vehicleType]}公斤`);
}
@ -1385,9 +1542,9 @@ Page({
// 检查包装要求
const estimatedPackages = Math.max(weight / complianceParams.weightPerPackage, volume / complianceParams.volumePerPackage);
if (estimatedPackages > 100) {
if (estimatedPackages > 300) {
compliance.isCompliant = false;
compliance.issues.push('包装数量过多,建议分批运输');
compliance.issues.push('包装数量较多,建议考虑多车运输');
}
// 检查是否合规
@ -1398,8 +1555,8 @@ Page({
if (transportMode === '货拉拉') {
// 货拉拉收费标准
[feeMin, feeMax, breakdown] = this.calculateHuolalaFee(distance, vehicleType, truckLength, waitTime, packagingType);
} else if (transportMode === '运满满') {
// 运满满收费标准
} else if (transportMode === '整车运输') {
// 整车运输收费标准
[feeMin, feeMax, breakdown] = this.calculateYunmanmanFee(distance, weight, volume, vehicleType, truckLength);
} else {
// 零担拼车收费标准
@ -1693,7 +1850,7 @@ Page({
return [feeMin, feeMax, breakdown];
},
// 运满满运费计算
// 整车运输运费计算
calculateYunmanmanFee: function(distance, weight, volume, vehicleType, truckLength) {
// 车长系数计算
const getTruckLengthFactor = (truckLength) => {
@ -1721,7 +1878,7 @@ Page({
}
};
// 运满满收费标准
// 整车运输收费标准
const rates = {
'面包车': {
startFee: 80,
@ -1966,8 +2123,8 @@ Page({
marketPrice = rates[vehicleType] || rates['面包车'];
// 应用车长系数
marketPrice *= truckLengthFactor;
} else if (transportMode === '运满满') {
// 基于运满满真实收费标准
} else if (transportMode === '整车运输') {
// 基于整车运输真实收费标准
const rates = {
'面包车': {
startFee: 80,

9
pages/freight-calculator/index.wxml

@ -166,8 +166,13 @@
</view>
</view>
<view class="detail-section" wx:if="{{showResult && detailText}}">
<text class="section-title">费用明细</text>
<text class="detail-text">{{detailText}}</text>
<view style="display: flex; justify-content: space-between; align-items: center;">
<text class="section-title">费用明细</text>
<button class="toggle-btn" bindtap="toggleDetail">
<text>{{showDetail ? '收起' : '展开'}}</text>
</button>
</view>
<text class="detail-text" wx:if="{{showDetail}}">{{detailText}}</text>
</view>
</view>

21
pages/freight-calculator/index.wxss

@ -683,6 +683,27 @@
word-break: break-all;
}
/* 切换按钮样式 */
.toggle-btn {
background: none;
border: none;
font-size: 20rpx;
color: #1989fa;
padding: 8rpx 16rpx;
border-radius: 4rpx;
display: flex;
align-items: center;
justify-content: center;
}
.toggle-btn:hover {
background-color: rgba(25, 137, 250, 0.1);
}
.toggle-btn:active {
background-color: rgba(25, 137, 250, 0.2);
}
/* 动画效果 */
@keyframes fadeInUp {
from {

8
pages/goods-detail/goods-detail.js

@ -1526,6 +1526,8 @@ Page({
id: goodsDetail.id || goodsDetail.productId,
name: goodsDetail.name || '未命名商品',
region: goodsDetail.region || '',
// 尝试获取原始的完整地区信息,而不是处理过的省份信息
fullRegion: goodsDetail.originalRegion || goodsDetail.region || '',
specification: goodsDetail.specification || goodsDetail.spec || '',
quantity: goodsDetail.quantity || goodsDetail.minOrder || '',
price: goodsDetail.price || '',
@ -1535,6 +1537,7 @@ Page({
weightQuantityData: goodsDetail.weightQuantityData || [],
imageUrl: (goodsDetail.imageUrls && goodsDetail.imageUrls.length > 0) ? goodsDetail.imageUrls[0] : ''
};
console.log('构建的selectedGoods:', selectedGoods);
// 导航到运费计算器页面
this.navigateLock(() => {
@ -2348,6 +2351,9 @@ Page({
}
}
// 保存原始的完整地区信息
const originalRegion = product.region || '';
// 转换商品数据格式
const formattedGoods = {
// 优先设置售空状态标记,放在最前面确保不被覆盖
@ -2387,6 +2393,8 @@ Page({
// 确保imageUrls和mediaItems被正确设置
imageUrls: imageUrls || [],
mediaItems: mediaItems,
// 保存原始的完整地区信息
originalRegion: originalRegion,
// 确保region使用提取后的省份信息,放在最后覆盖所有展开操作
region: region,
// 添加价格波动信息

43
server-example/server-mysql.js

@ -393,17 +393,20 @@ app.post('/api/freight/calculate', (req, res) => {
data: result
});
} catch (error) {
console.error('处理腾讯地图API响应时出错:', error);
// 如果处理响应时出错,使用固定距离作为fallback
const distance = 200; // 示例距离:200公里
const freight = Math.floor(distance * baseRate * weight);
const deliveryTime = Math.ceil(distance / 200); // 公路:200公里/天
const result = {
freight: freight,
distance: distance,
deliveryTime: deliveryTime
};
console.error('处理腾讯地图API响应时出错:', error);
// 如果处理响应时出错,使用固定距离作为fallback
const distance = 200; // 示例距离:200公里
// 计算运费区间
const [feeMin, feeMax] = calculateYunmanmanFee(distance, goodsInfo.weight || 1, goodsInfo.volume || 0, vehicleType || '平板', truckLength || '5米');
const deliveryTime = Math.ceil(distance / 80); // 公路:80公里/天
const result = {
freight: Math.floor((feeMin + feeMax) / 2), // 中间值
feeMin: feeMin,
feeMax: feeMax,
distance: distance,
deliveryTime: deliveryTime
};
// 保存运费估算历史记录
if (userId && phoneNumber) {
@ -436,11 +439,14 @@ app.post('/api/freight/calculate', (req, res) => {
console.error('腾讯地图API调用失败:', error);
// 如果API调用失败,使用固定距离作为fallback
const distance = 200; // 示例距离:200公里
const freight = Math.floor(distance * baseRate * weight);
const deliveryTime = Math.ceil(distance / 200); // 公路:200公里/天
// 计算运费区间
const [feeMin, feeMax] = calculateYunmanmanFee(distance, goodsInfo.weight || 1, goodsInfo.volume || 0, vehicleType || '平板', truckLength || '5米');
const deliveryTime = Math.ceil(distance / 80); // 公路:80公里/天
const result = {
freight: freight,
freight: Math.floor((feeMin + feeMax) / 2), // 中间值
feeMin: feeMin,
feeMax: feeMax,
distance: distance,
deliveryTime: deliveryTime
};
@ -474,11 +480,14 @@ app.post('/api/freight/calculate', (req, res) => {
} else {
// 没有经纬度信息,使用固定距离作为fallback
const distance = 200; // 示例距离:200公里
const freight = Math.floor(distance * baseRate * weight);
const deliveryTime = Math.ceil(distance / 200); // 公路:200公里/天
// 计算运费区间
const [feeMin, feeMax] = calculateYunmanmanFee(distance, goodsInfo.weight || 1, goodsInfo.volume || 0, vehicleType || '平板', truckLength || '5米');
const deliveryTime = Math.ceil(distance / 80); // 公路:80公里/天
const result = {
freight: freight,
freight: Math.floor((feeMin + feeMax) / 2), // 中间值
feeMin: feeMin,
feeMax: feeMax,
distance: distance,
deliveryTime: deliveryTime
};

Loading…
Cancel
Save