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.

846 lines
24 KiB

// pages/freight-calculator/index.js
const API = require('../../utils/api.js');
Page({
data: {
// 出发地信息
origin: {
province: '',
city: '',
district: '',
detail: ''
},
// 目的地信息
destination: {
province: '',
city: '',
district: '',
detail: ''
},
// 货物信息
goodsInfo: {
weight: '', // 重量(kg)
volume: '', // 体积(m³)
quantity: 1, // 数量
type: 'egg' // 货物类型,默认为鸡蛋
},
// 物流车辆信息
vehicleInfo: {
type: '', // 车辆类型
capacity: '', // 载重能力(吨)
number: '', // 车辆编号
driver: '', // 司机姓名
phone: '' // 联系电话
},
// 物流人员信息
logisticsPersonnel: [
{
id: 1,
name: '张三',
position: '物流经理',
experience: 5,
phone: '13800138000'
},
{
id: 2,
name: '李四',
position: '配送专员',
experience: 3,
phone: '13900139000'
},
{
id: 3,
name: '王五',
position: '调度员',
experience: 2,
phone: '13700137000'
}
],
// 车辆类型列表
vehicleTypes: ['厢式货车', '冷藏车', '平板车', '高栏车', '自卸车'],
// 选中的车辆类型索引
selectedVehicleTypeIndex: 0,
// 选中的货源信息
selectedGoods: {},
// 选中的规格索引
selectedSpecIndex: 0,
// 计算结果
calculationResult: null,
// 地址选择器状态
showOriginPicker: false,
showDestinationPicker: false,
// 加载状态
loading: false,
// 历史记录
historyRecords: [],
// 地址选择器数据
regionList: {
provinces: [],
cities: [],
districts: []
},
// 地址选择器当前选中
pickerValues: {
origin: [0, 0, 0],
destination: [0, 0, 0]
}
},
onLoad: function (options) {
// 页面加载时的初始化逻辑
console.log('物流运费估算页面加载,options:', options);
// 加载历史记录
this.loadHistoryRecords();
// 初始化地址选择器数据
this.initRegionData();
// 如果从商品详情页跳转过来,获取商品信息
if (options.goodsId) {
this.loadGoodsInfo(options.goodsId);
}
// 如果直接传递了货源信息 (goodsInfo)
if (options.goodsInfo) {
try {
const goodsInfo = JSON.parse(options.goodsInfo);
this.setData({
selectedGoods: goodsInfo,
'goodsInfo.weight': goodsInfo.grossWeight || '',
'goodsInfo.quantity': 1
});
} catch (e) {
console.error('解析货源信息失败:', e);
}
}
// 如果直接传递了货源信息 (goodsData)
if (options.goodsData) {
try {
// 尝试直接解析
let goodsData;
try {
goodsData = JSON.parse(options.goodsData);
} catch (e1) {
// 如果直接解析失败,尝试解码后再解析
try {
const decodedGoodsData = decodeURIComponent(options.goodsData);
goodsData = JSON.parse(decodedGoodsData);
} catch (e2) {
console.error('解析货源信息失败 (已尝试解码):', e2);
throw e2;
}
}
this.setData({
selectedGoods: goodsData,
'goodsInfo.weight': goodsData.grossWeight || '',
'goodsInfo.quantity': 1
});
// 设置出发地为商品所在地
if (goodsData.region) {
const regionInfo = this.parseRegion(goodsData.region);
this.setData({
'origin.province': regionInfo.province || '',
'origin.city': regionInfo.city || '',
'origin.district': regionInfo.district || ''
});
}
} catch (e) {
console.error('解析货源信息失败:', e);
}
}
},
// 初始化地址选择器数据
initRegionData: function () {
// 这里可以从API获取地址数据,或者使用本地数据
const provinces = [
'北京市', '上海市', '广东省', '江苏省', '浙江省', '山东省', '河南省', '四川省', '湖北省', '福建省',
'湖南省', '安徽省', '河北省', '辽宁省', '陕西省', '江西省', '云南省', '黑龙江省', '山西省', '广西壮族自治区',
'内蒙古自治区', '吉林省', '贵州省', '新疆维吾尔自治区', '甘肃省', '重庆市', '宁夏回族自治区', '青海省', '西藏自治区', '海南省'
];
this.setData({
'regionList.provinces': provinces
});
},
// 加载商品信息
loadGoodsInfo: function (goodsId) {
// 从本地存储获取商品信息
const goods = wx.getStorageSync('goods') || [];
const goodsItem = goods.find(item => item.id === goodsId || item.productId === goodsId);
if (goodsItem) {
// 设置选中的货源信息
this.setData({
selectedGoods: goodsItem
});
// 设置出发地为商品所在地
if (goodsItem.region) {
const regionInfo = this.parseRegion(goodsItem.region);
this.setData({
'origin.province': regionInfo.province || '',
'origin.city': regionInfo.city || '',
'origin.district': regionInfo.district || ''
});
}
// 设置货物重量(如果有)
if (goodsItem.grossWeight) {
this.setData({
'goodsInfo.weight': goodsItem.grossWeight
});
}
}
},
// 解析地区信息
parseRegion: function (region) {
if (!region) return {};
// 简单的地区解析逻辑,实际项目中可能需要更复杂的解析
const parts = region.split(' ');
return {
province: parts[0] || '',
city: parts[1] || '',
district: parts[2] || ''
};
},
// 加载历史记录
loadHistoryRecords: function () {
const history = wx.getStorageSync('freightCalculatorHistory') || [];
this.setData({
historyRecords: history.slice(0, 10) // 只显示最近10条记录
});
},
// 保存历史记录
saveHistoryRecord: function (result) {
const history = wx.getStorageSync('freightCalculatorHistory') || [];
const record = {
id: Date.now(),
origin: this.data.origin,
destination: this.data.destination,
goodsInfo: this.data.goodsInfo,
vehicleInfo: this.data.vehicleInfo,
transportMode: this.data.transportMode,
result: result,
timestamp: new Date().toISOString()
};
// 添加到历史记录开头
history.unshift(record);
// 只保留最近20条记录
const newHistory = history.slice(0, 20);
wx.setStorageSync('freightCalculatorHistory', newHistory);
// 更新页面数据
this.setData({
historyRecords: newHistory.slice(0, 10)
});
},
// 输入出发地
bindOriginInput: function (e) {
const { key } = e.currentTarget.dataset;
this.setData({
[`origin.${key}`]: e.detail.value
});
},
// 输入目的地
bindDestinationInput: function (e) {
const { key } = e.currentTarget.dataset;
this.setData({
[`destination.${key}`]: e.detail.value
});
},
// 输入货物信息
bindGoodsInfoInput: function (e) {
const { key } = e.currentTarget.dataset;
this.setData({
[`goodsInfo.${key}`]: e.detail.value
});
},
// 选择规格组合
bindSpecChange: function (e) {
const index = e.detail.value;
this.setData({
selectedSpecIndex: index
});
},
// 选择车辆类型
bindVehicleTypeChange: function (e) {
const index = e.detail.value;
this.setData({
selectedVehicleTypeIndex: index,
'vehicleInfo.type': this.data.vehicleTypes[index]
});
},
// 输入车辆信息
bindVehicleInfoInput: function (e) {
const { key } = e.currentTarget.dataset;
this.setData({
[`vehicleInfo.${key}`]: e.detail.value
});
},
// 地址选择器值变化
bindRegionChange: function (e) {
const { type } = e.currentTarget.dataset;
const values = e.detail.value;
// 更新地址信息
if (type === 'origin') {
this.setData({
'origin.province': values[0],
'origin.city': values[1],
'origin.district': values[2]
});
} else if (type === 'destination') {
this.setData({
'destination.province': values[0],
'destination.city': values[1],
'destination.district': values[2]
});
}
},
// 打开出发地选择器
openOriginPicker: function () {
this.setData({
showOriginPicker: true
});
},
// 打开目的地选择器
openDestinationPicker: function () {
this.setData({
showDestinationPicker: true
});
},
// 关闭地址选择器
closePicker: function () {
this.setData({
showOriginPicker: false,
showDestinationPicker: false
});
},
// 选择地址
selectAddress: function (e) {
const { type, address } = e.detail;
if (type === 'origin') {
this.setData({
origin: address,
showOriginPicker: false
});
} else if (type === 'destination') {
this.setData({
destination: address,
showDestinationPicker: false
});
}
},
// 使用当前位置作为出发地
useCurrentLocation: function () {
const that = this;
wx.getLocation({
type: 'wgs84',
success: function (res) {
// 显示加载提示
wx.showLoading({
title: '获取地址中...',
mask: true
});
// 使用微信的地址解析服务获取详细地址
wx.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/',
data: {
location: `${res.latitude},${res.longitude}`,
key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77' // 这里使用腾讯地图API密钥,实际项目中应该替换为自己的密钥
},
success: function (response) {
wx.hideLoading();
if (response.data.status === 0) {
const result = response.data.result;
that.setData({
destination: {
province: result.address_component.province || '',
city: result.address_component.city || '',
district: result.address_component.district || '',
detail: result.address || '',
latitude: res.latitude,
longitude: res.longitude
}
});
wx.showToast({
title: '地址获取成功',
icon: 'success'
});
} else {
wx.showToast({
title: '地址解析失败,请手动输入',
icon: 'none'
});
}
},
fail: function (err) {
wx.hideLoading();
console.error('地址解析失败:', err);
wx.showToast({
title: '地址解析失败,请手动输入',
icon: 'none'
});
}
});
},
fail: function (err) {
console.error('获取位置失败:', err);
wx.showToast({
title: '获取位置失败,请手动输入',
icon: 'none'
});
}
});
},
// 手动选择出发地位置
chooseOriginLocation: function () {
const that = this;
wx.chooseLocation({
success(res) {
console.log('用户选择的出发地位置信息:', res);
const name = res.name;
const address = res.address;
const latitude = res.latitude;
const longitude = res.longitude;
// 使用腾讯地图API进行逆地理编码,获取详细地址信息
wx.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/',
data: {
location: `${latitude},${longitude}`,
key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77'
},
success: function (response) {
if (response.data.status === 0) {
const result = response.data.result;
that.setData({
origin: {
province: result.address_component.province || '',
city: result.address_component.city || '',
district: result.address_component.district || '',
detail: `${name} ${address}`,
latitude: latitude,
longitude: longitude
}
});
wx.showToast({
title: '出发地选择成功',
icon: 'success'
});
} else {
wx.showToast({
title: '地址解析失败,请手动输入',
icon: 'none'
});
}
},
fail: function (err) {
console.error('地址解析失败:', err);
wx.showToast({
title: '地址解析失败,请手动输入',
icon: 'none'
});
}
});
},
fail(err) {
console.error('选择出发地位置失败:', err);
if (err.errMsg === 'chooseLocation:fail auth deny') {
wx.showToast({
title: '需要位置授权才能选择地点',
icon: 'none',
duration: 2000
});
// 引导用户重新授权
that.requestLocationAuth();
} else {
wx.showToast({
title: '选择位置失败',
icon: 'none',
duration: 2000
});
}
}
});
},
// 手动选择目的地位置
chooseDestinationLocation: function () {
const that = this;
wx.chooseLocation({
success(res) {
console.log('用户选择的目的地位置信息:', res);
const name = res.name;
const address = res.address;
const latitude = res.latitude;
const longitude = res.longitude;
// 使用腾讯地图API进行逆地理编码,获取详细地址信息
wx.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/',
data: {
location: `${latitude},${longitude}`,
key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77'
},
success: function (response) {
if (response.data.status === 0) {
const result = response.data.result;
that.setData({
destination: {
province: result.address_component.province || '',
city: result.address_component.city || '',
district: result.address_component.district || '',
detail: `${name} ${address}`,
latitude: latitude,
longitude: longitude
}
});
wx.showToast({
title: '目的地选择成功',
icon: 'success'
});
} else {
wx.showToast({
title: '地址解析失败,请手动输入',
icon: 'none'
});
}
},
fail: function (err) {
console.error('地址解析失败:', err);
wx.showToast({
title: '地址解析失败,请手动输入',
icon: 'none'
});
}
});
},
fail(err) {
console.error('选择目的地位置失败:', err);
if (err.errMsg === 'chooseLocation:fail auth deny') {
wx.showToast({
title: '需要位置授权才能选择地点',
icon: 'none',
duration: 2000
});
// 引导用户重新授权
that.requestLocationAuth();
} else {
wx.showToast({
title: '选择位置失败',
icon: 'none',
duration: 2000
});
}
}
});
},
// 请求位置授权
requestLocationAuth: function () {
const that = this;
console.log('开始请求位置授权');
wx.showLoading({
title: '请求授权中...',
mask: true
});
// 检查用户是否已经拒绝过授权
wx.getSetting({
success(res) {
wx.hideLoading();
if (res.authSetting['scope.userLocation'] === false) {
// 用户已经拒绝过授权,直接引导到设置页面
wx.showModal({
title: '需要位置授权',
content: '请在设置中开启位置授权,以便我们为您提供相关服务',
showCancel: true,
cancelText: '取消',
confirmText: '去授权',
success: (res) => {
if (res.confirm) {
// 打开设置页面让用户手动开启授权
wx.openSetting({
success: (settingRes) => {
console.log('设置页面返回结果:', settingRes);
if (settingRes.authSetting['scope.userLocation']) {
// 用户在设置中开启了位置授权
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1500
});
} else {
// 用户在设置中仍未开启位置授权
wx.showToast({
title: '您已拒绝位置授权',
icon: 'none'
});
}
},
fail: (err) => {
console.error('打开设置失败:', err);
wx.showToast({
title: '打开设置失败',
icon: 'none'
});
}
});
}
}
});
} else {
// 用户未拒绝过授权,调用 authorize
wx.authorize({
scope: 'scope.userLocation',
success() {
console.log('位置授权成功');
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1500
});
},
fail(err) {
console.log('位置授权失败:', err);
// 授权失败,弹出模态框引导用户重新授权
wx.showModal({
title: '需要位置授权',
content: '请在设置中开启位置授权,以便我们为您提供相关服务',
showCancel: true,
cancelText: '取消',
confirmText: '去授权',
success: (res) => {
if (res.confirm) {
// 打开设置页面让用户手动开启授权
wx.openSetting({
success: (settingRes) => {
console.log('设置页面返回结果:', settingRes);
if (settingRes.authSetting['scope.userLocation']) {
// 用户在设置中开启了位置授权
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1500
});
} else {
// 用户在设置中仍未开启位置授权
wx.showToast({
title: '您已拒绝位置授权',
icon: 'none'
});
}
},
fail: (err) => {
console.error('打开设置失败:', err);
wx.showToast({
title: '打开设置失败',
icon: 'none'
});
}
});
}
}
});
}
});
}
},
fail(err) {
wx.hideLoading();
console.error('获取设置失败:', err);
wx.showToast({
title: '获取设置失败',
icon: 'none'
});
}
});
},
// 计算运费
calculateFreight: function () {
// 验证输入
if (!this.data.origin.province || !this.data.destination.province) {
wx.showToast({
title: '请填写完整的出发地和目的地',
icon: 'none'
});
return;
}
// 如果没有重量和体积,使用默认值 1
if (!this.data.goodsInfo.weight && !this.data.goodsInfo.volume) {
this.setData({
'goodsInfo.weight': 1
});
}
this.setData({ loading: true });
// 构建请求参数
const params = {
origin: this.data.origin,
destination: this.data.destination,
goodsInfo: this.data.goodsInfo,
vehicleInfo: this.data.vehicleInfo
};
// 调用API计算运费
API.calculateFreight(params).then(res => {
this.setData({ loading: false });
if (res.success) {
this.setData({ calculationResult: res.data });
// 保存历史记录
this.saveHistoryRecord(res.data);
} else {
wx.showToast({
title: res.message || '计算失败,请稍后重试',
icon: 'none'
});
}
}).catch(err => {
this.setData({ loading: false });
console.error('计算运费失败:', err);
wx.showToast({
title: '网络错误,请稍后重试',
icon: 'none'
});
});
},
// 清空输入
clearInput: function () {
this.setData({
origin: {
province: '',
city: '',
district: '',
detail: ''
},
destination: {
province: '',
city: '',
district: '',
detail: ''
},
goodsInfo: {
weight: '',
volume: '',
quantity: 1
},
vehicleInfo: {
type: '',
capacity: '',
number: '',
driver: '',
phone: ''
},
selectedVehicleTypeIndex: 0,
calculationResult: null
});
},
// 使用历史记录
useHistoryRecord: function (e) {
const index = e.currentTarget.dataset.index;
const record = this.data.historyRecords[index];
this.setData({
origin: record.origin,
destination: record.destination,
goodsInfo: record.goodsInfo,
vehicleInfo: record.vehicleInfo || {},
transportMode: record.transportMode,
calculationResult: record.result
});
// 恢复车辆类型选择
if (record.vehicleInfo && record.vehicleInfo.type) {
const vehicleTypeIndex = this.data.vehicleTypes.indexOf(record.vehicleInfo.type);
if (vehicleTypeIndex !== -1) {
this.setData({ selectedVehicleTypeIndex: vehicleTypeIndex });
}
}
},
// 删除历史记录
deleteHistoryRecord: function (e) {
const index = e.currentTarget.dataset.index;
const history = wx.getStorageSync('freightCalculatorHistory') || [];
history.splice(index, 1);
wx.setStorageSync('freightCalculatorHistory', history);
this.setData({
historyRecords: history.slice(0, 10)
});
},
// 清空历史记录
clearHistory: function () {
wx.setStorageSync('freightCalculatorHistory', []);
this.setData({
historyRecords: []
});
},
// 返回上一页
navigateBack: function () {
wx.navigateBack({
delta: 1
});
},
// 拨打电话
makePhoneCall: function (e) {
const phone = e.currentTarget.dataset.phone;
if (phone) {
wx.makePhoneCall({
phoneNumber: phone,
success: function () {
console.log('拨打电话成功');
},
fail: function (err) {
console.error('拨打电话失败:', err);
wx.showToast({
title: '拨打电话失败',
icon: 'none'
});
}
});
}
},
});