402 lines
9.3 KiB
JavaScript
402 lines
9.3 KiB
JavaScript
const formatTime = date => {
|
|
const year = date.getFullYear()
|
|
const month = date.getMonth() + 1
|
|
const day = date.getDate()
|
|
const hour = date.getHours()
|
|
const minute = date.getMinutes()
|
|
const second = date.getSeconds()
|
|
|
|
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
|
|
}
|
|
|
|
const formatNumber = n => {
|
|
n = n.toString()
|
|
return n[1] ? n : `0${n}`
|
|
}
|
|
|
|
/**
|
|
* 格式化价格显示
|
|
* @param {number} price - 价格
|
|
* @returns {string} 格式化后的价格
|
|
*/
|
|
export function formatPrice(price) {
|
|
if (!price) return '0';
|
|
return price.toFixed(1);
|
|
}
|
|
|
|
/**
|
|
* 计算优惠金额
|
|
* @param {number} originalPrice - 原价
|
|
* @param {number} currentPrice - 现价
|
|
* @returns {number} 优惠金额
|
|
*/
|
|
export function calculateDiscount(originalPrice, currentPrice) {
|
|
if (!originalPrice || !currentPrice) return 0;
|
|
return Math.max(0, originalPrice - currentPrice);
|
|
}
|
|
|
|
/**
|
|
* 车龄计算
|
|
* @param {string} year - 年份
|
|
* @returns {string} 车龄描述
|
|
*/
|
|
export function calculateCarAge(year) {
|
|
if (!year) return '未知';
|
|
const currentYear = new Date().getFullYear();
|
|
const age = currentYear - parseInt(year);
|
|
|
|
if (age <= 0) return '新车';
|
|
if (age === 1) return '1年';
|
|
return `${age}年`;
|
|
}
|
|
|
|
/**
|
|
* 里程数格式化
|
|
* @param {number} mileage - 里程数(公里)
|
|
* @returns {string} 格式化后的里程数
|
|
*/
|
|
export function formatMileage(mileage) {
|
|
if (!mileage) return '0公里';
|
|
|
|
if (mileage < 1000) {
|
|
return `${mileage}公里`;
|
|
} else if (mileage < 10000) {
|
|
return `${(mileage / 1000).toFixed(1)}千公里`;
|
|
} else {
|
|
return `${(mileage / 10000).toFixed(1)}万公里`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 验证手机号
|
|
* @param {string} phone - 手机号
|
|
* @returns {boolean} 是否有效
|
|
*/
|
|
export function validatePhone(phone) {
|
|
const phoneReg = /^1[3-9]\d{9}$/;
|
|
return phoneReg.test(phone);
|
|
}
|
|
|
|
/**
|
|
* 图片加载错误处理
|
|
* @param {string} src - 图片源
|
|
* @param {string} fallback - 备用图片
|
|
* @returns {string} 处理后的图片源
|
|
*/
|
|
export function handleImageError(src, fallback = '/images/car-placeholder.png') {
|
|
return src || fallback;
|
|
}
|
|
|
|
/**
|
|
* 分享配置生成
|
|
* @param {Object} carDetail - 车辆详情
|
|
* @param {string} carId - 车辆ID
|
|
* @returns {Object} 分享配置
|
|
*/
|
|
export function generateShareConfig(carDetail, carId) {
|
|
return {
|
|
title: carDetail.title || '精品二手车',
|
|
desc: `${carDetail.desc || '车况优良'} - 仅售${formatPrice(carDetail.price)}万`,
|
|
path: `/pages/car-detail/car-detail?id=${carId}`,
|
|
imageUrl: carDetail.cover_image?.[0] || '/images/share-default.png'
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 本地存储操作
|
|
*/
|
|
export const storage = {
|
|
/**
|
|
* 保存浏览记录
|
|
* @param {Object} carInfo - 车辆信息
|
|
*/
|
|
saveBrowseHistory(carInfo) {
|
|
try {
|
|
const history = this.getBrowseHistory();
|
|
const existingIndex = history.findIndex(item => item.id === carInfo.id);
|
|
|
|
if (existingIndex !== -1) {
|
|
history.splice(existingIndex, 1);
|
|
}
|
|
|
|
history.unshift({
|
|
id: carInfo.id,
|
|
title: carInfo.title,
|
|
price: carInfo.price,
|
|
cover_image: carInfo.cover_image?.[0],
|
|
browse_time: Date.now()
|
|
});
|
|
|
|
// 只保留最近50条记录
|
|
if (history.length > 50) {
|
|
history.splice(50);
|
|
}
|
|
|
|
wx.setStorageSync('browse_history', history);
|
|
} catch (error) {
|
|
console.error('保存浏览记录失败:', error);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 获取浏览记录
|
|
* @returns {Array} 浏览记录列表
|
|
*/
|
|
getBrowseHistory() {
|
|
try {
|
|
return wx.getStorageSync('browse_history') || [];
|
|
} catch (error) {
|
|
console.error('获取浏览记录失败:', error);
|
|
return [];
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 保存收藏
|
|
* @param {Object} carInfo - 车辆信息
|
|
*/
|
|
saveFavorite(carInfo) {
|
|
try {
|
|
const favorites = this.getFavorites();
|
|
const existingIndex = favorites.findIndex(item => item.id === carInfo.id);
|
|
|
|
if (existingIndex === -1) {
|
|
favorites.unshift({
|
|
id: carInfo.id,
|
|
title: carInfo.title,
|
|
price: carInfo.price,
|
|
cover_image: carInfo.cover_image?.[0],
|
|
favorite_time: Date.now()
|
|
});
|
|
|
|
wx.setStorageSync('favorites', favorites);
|
|
return true;
|
|
}
|
|
return false;
|
|
} catch (error) {
|
|
console.error('保存收藏失败:', error);
|
|
return false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 取消收藏
|
|
* @param {string} carId - 车辆ID
|
|
*/
|
|
removeFavorite(carId) {
|
|
try {
|
|
const favorites = this.getFavorites();
|
|
const filteredFavorites = favorites.filter(item => item.id !== carId);
|
|
wx.setStorageSync('favorites', filteredFavorites);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('取消收藏失败:', error);
|
|
return false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 获取收藏列表
|
|
* @returns {Array} 收藏列表
|
|
*/
|
|
getFavorites() {
|
|
try {
|
|
return wx.getStorageSync('favorites') || [];
|
|
} catch (error) {
|
|
console.error('获取收藏列表失败:', error);
|
|
return [];
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 检查是否已收藏
|
|
* @param {string} carId - 车辆ID
|
|
* @returns {boolean} 是否已收藏
|
|
*/
|
|
isFavorite(carId) {
|
|
const favorites = this.getFavorites();
|
|
return favorites.some(item => item.id === carId);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* API 请求封装
|
|
*/
|
|
export const api = {
|
|
/**
|
|
* 获取车辆详情
|
|
* @param {string} carId - 车辆ID
|
|
* @returns {Promise} API响应
|
|
*/
|
|
getCarDetail(carId) {
|
|
return new Promise((resolve, reject) => {
|
|
wx.request({
|
|
url: `${getApp().globalData.apiUrl}/cars/${carId}`,
|
|
method: 'GET',
|
|
header: {
|
|
'Authorization': getApp().globalData.token
|
|
},
|
|
success: (res) => {
|
|
if (res.statusCode === 200) {
|
|
resolve(res.data);
|
|
} else {
|
|
reject(new Error(res.data.message || '获取车辆详情失败'));
|
|
}
|
|
},
|
|
fail: (error) => {
|
|
reject(error);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* 提交举报
|
|
* @param {string} carId - 车辆ID
|
|
* @param {string} reason - 举报原因
|
|
* @returns {Promise} API响应
|
|
*/
|
|
submitReport(carId, reason) {
|
|
return new Promise((resolve, reject) => {
|
|
wx.request({
|
|
url: `${getApp().globalData.apiUrl}/reports`,
|
|
method: 'POST',
|
|
header: {
|
|
'Authorization': getApp().globalData.token,
|
|
'Content-Type': 'application/json'
|
|
},
|
|
data: {
|
|
car_id: carId,
|
|
reason: reason,
|
|
report_time: Date.now()
|
|
},
|
|
success: (res) => {
|
|
if (res.statusCode === 200) {
|
|
resolve(res.data);
|
|
} else {
|
|
reject(new Error(res.data.message || '举报提交失败'));
|
|
}
|
|
},
|
|
fail: (error) => {
|
|
reject(error);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* 预约看车
|
|
* @param {Object} bookingData - 预约数据
|
|
* @returns {Promise} API响应
|
|
*/
|
|
bookViewing(bookingData) {
|
|
return new Promise((resolve, reject) => {
|
|
wx.request({
|
|
url: `${getApp().globalData.apiUrl}/bookings`,
|
|
method: 'POST',
|
|
header: {
|
|
'Authorization': getApp().globalData.token,
|
|
'Content-Type': 'application/json'
|
|
},
|
|
data: bookingData,
|
|
success: (res) => {
|
|
if (res.statusCode === 200) {
|
|
resolve(res.data);
|
|
} else {
|
|
reject(new Error(res.data.message || '预约失败'));
|
|
}
|
|
},
|
|
fail: (error) => {
|
|
reject(error);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 用户行为追踪
|
|
*/
|
|
export const analytics = {
|
|
/**
|
|
* 记录页面访问
|
|
* @param {string} carId - 车辆ID
|
|
* @param {string} source - 访问来源
|
|
*/
|
|
trackPageView(carId, source = 'direct') {
|
|
try {
|
|
// 这里可以接入第三方统计服务
|
|
console.log('页面访问:', { carId, source, timestamp: Date.now() });
|
|
} catch (error) {
|
|
console.error('统计记录失败:', error);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 记录用户操作
|
|
* @param {string} action - 操作类型
|
|
* @param {Object} params - 操作参数
|
|
*/
|
|
trackUserAction(action, params = {}) {
|
|
try {
|
|
console.log('用户操作:', { action, params, timestamp: Date.now() });
|
|
} catch (error) {
|
|
console.error('操作记录失败:', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 错误处理
|
|
*/
|
|
export const errorHandler = {
|
|
/**
|
|
* 显示错误提示
|
|
* @param {string} message - 错误信息
|
|
* @param {string} type - 错误类型
|
|
*/
|
|
showError(message, type = 'toast') {
|
|
switch (type) {
|
|
case 'toast':
|
|
wx.showToast({
|
|
title: message,
|
|
icon: 'none',
|
|
duration: 2000
|
|
});
|
|
break;
|
|
case 'modal':
|
|
wx.showModal({
|
|
title: '提示',
|
|
content: message,
|
|
showCancel: false
|
|
});
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 处理网络错误
|
|
* @param {Error} error - 错误对象
|
|
*/
|
|
handleNetworkError(error) {
|
|
let message = '网络错误,请稍后重试';
|
|
|
|
if (error.errMsg) {
|
|
if (error.errMsg.includes('timeout')) {
|
|
message = '请求超时,请检查网络连接';
|
|
} else if (error.errMsg.includes('fail')) {
|
|
message = '网络连接失败,请检查网络设置';
|
|
}
|
|
}
|
|
|
|
this.showError(message);
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
formatTime
|
|
}
|
|
|
|
|
|
|