const app = getApp() Page({ data: { activeTab: 'in_progress', // in_progress, completed, all inProgressPlans: [], // 进行中行程数据 completedPlans: [], // 已完成行程数据 allPlans: [], // 全部行程数据 completedCurrentPage: 1, // 已完成行程当前页码 completedTotalPages: 1, // 已完成行程总页数 allCurrentPage: 1, // 全部行程当前页码 allTotalPages: 1, // 全部行程总页数 isLoading: false, // 是否正在加载 isLogin: false, // 登录状态 showSpotModal: false, // 是否显示景点详情弹窗 currentSpot: {}, // 当前显示的景点 currentDayIndex: 0, // 当前景点的天数索引 currentSpotIndex: 0, // 当前景点的索引 showCheckinModal: false, // 是否显示打卡弹窗 checkinImage: '', // 打卡图片 checkinNote: '', // 打卡文案 isUploading: false, // 是否正在上传图片 tempCheckinData: {}, // 临时存储打卡数据 latestPlanMapData: { // 地图数据 showMap: false, markers: [], polylines: [], includePoints: [], longitude: 116.4074, latitude: 39.9042, scale: 14 }, currentMapDay: -1, // 当前显示的地图天数 cityOptions: [] // 城市选项 }, onLoad() { const token = wx.getStorageSync('token') const userInfo = wx.getStorageSync('userInfo') if (token && userInfo) { app.globalData.token = token app.globalData.userInfo = userInfo this.setData({ isLogin: true }) this.loadInProgressPlans() } else { this.checkLoginStatus() } }, onShow() { if (this.data.isLogin) { if (this.data.activeTab === 'in_progress') { this.loadInProgressPlans() } else if (this.data.activeTab === 'completed') { this.loadCompletedPlans(this.data.completedCurrentPage) } else if (this.data.activeTab === 'all') { this.loadAllPlans(this.data.allCurrentPage) } } }, checkLoginStatus() { const token = app.globalData.token if (!token) { wx.showModal({ title: '未登录', content: '请先登录查看行程', confirmText: '去登录', success: (res) => { if (res.confirm) { wx.navigateTo({ url: '/pages/login/login' }) } else { wx.switchTab({ url: '/pages/index/index' }) } } }) return } this.setData({ isLogin: true }) this.loadInProgressPlans() }, // 切换选项卡 switchTab(e) { const tab = e.currentTarget.dataset.tab; if (this.data.activeTab === tab) return; this.setData({ activeTab: tab }); if (tab === 'in_progress') { this.loadInProgressPlans(); } else if (tab === 'completed') { this.loadCompletedPlans(1); } else if (tab === 'all') { this.loadAllPlans(1); } }, // 加载进行中行程 loadInProgressPlans() { if (!app.globalData.token) return this.setData({ isLoading: true }); wx.request({ url: app.globalData.apiBaseUrl + '/api/user/plans/', method: 'GET', data: { status: 'in_progress', limit: 1, timestamp: new Date().getTime() }, header: { 'Authorization': 'Token ' + app.globalData.token, 'Content-Type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data.status === 'success') { this.setData({ inProgressPlans: res.data.data.plans, }); if (res.data.data.plans.length > 0) { this.processPlanMapData(res.data.data.plans[0]); } } else { this.handleErrorResponse(res); } }, fail: (err) => { this.handleRequestError(err); }, complete: () => { this.setData({ isLoading: false }); } }); }, // 加载已完成行程 loadCompletedPlans(page = 1) { if (!app.globalData.token) return; this.setData({ isLoading: true }); wx.request({ url: app.globalData.apiBaseUrl + '/api/user/plans/', method: 'GET', data: { status: 'completed', page: page, page_size: 5 }, header: { 'Authorization': 'Token ' + app.globalData.token, 'Content-Type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data.status === 'success') { this.setData({ completedPlans: res.data.data.plans, completedCurrentPage: page, completedTotalPages: res.data.data.pagination.total_pages || 1 }); } else { this.handleErrorResponse(res); } }, fail: (err) => { this.handleRequestError(err); }, complete: () => { this.setData({ isLoading: false }); } }); }, // 加载全部行程 loadAllPlans(page = 1) { if (!app.globalData.token) return; this.setData({ isLoading: true }); wx.request({ url: app.globalData.apiBaseUrl + '/api/user/plans/', method: 'GET', data: { status: 'in_progress', page: page, page_size: 5 }, header: { 'Authorization': 'Token ' + app.globalData.token, 'Content-Type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data.status === 'success') { this.setData({ allPlans: res.data.data.plans, allCurrentPage: page, allTotalPages: res.data.data.pagination.total_pages || 1 }); } else { this.handleErrorResponse(res); } }, fail: (err) => { this.handleRequestError(err); }, complete: () => { this.setData({ isLoading: false }); } }); }, // 已完成行程翻页 changeCompletedPage(e) { const page = e.currentTarget.dataset.page if (page < 1 || page > this.data.completedTotalPages) return this.loadCompletedPlans(page) }, // 全部行程翻页 changeAllPage(e) { const page = e.currentTarget.dataset.page if (page < 1 || page > this.data.allTotalPages) return this.loadAllPlans(page) }, // 开始行程 startPlan(e) { const planId = e.currentTarget.dataset.id // 切换到进行中选项卡并加载该行程 this.setData({ activeTab: 'in_progress' }, () => { // 加载特定行程数据 this.loadSpecificPlan(planId) }) }, // 加载特定行程 loadSpecificPlan(planId) { if (!app.globalData.token) return this.setData({ isLoading: true }); wx.request({ url: app.globalData.apiBaseUrl + '/api/user/plans/' + planId + '/', method: 'GET', header: { 'Authorization': 'Token ' + app.globalData.token, 'Content-Type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data.status === 'success') { this.setData({ inProgressPlans: [res.data.data.plan], }); this.processPlanMapData(res.data.data.plan); } else { this.handleErrorResponse(res); } }, fail: (err) => { this.handleRequestError(err); }, complete: () => { this.setData({ isLoading: false }); } }); }, // 完成行程 completePlan(e) { const planId = e.currentTarget.dataset.id wx.showModal({ title: '确认完成', content: '确定要结束并保存此行程吗?', success: (res) => { if (res.confirm) { this.markPlanAsCompleted(planId) } } }) }, // 标记行程为已完成 markPlanAsCompleted(planId) { wx.request({ url: app.globalData.apiBaseUrl + '/api/user/plans/' + planId + '/complete/', method: 'POST', header: { 'Authorization': 'Token ' + app.globalData.token, 'Content-Type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data.status === 'success') { wx.showToast({ title: '行程已完成', icon: 'success' }) // 重新加载数据 this.loadInProgressPlans() this.loadCompletedPlans(1) this.loadAllPlans(1) } else { this.handleErrorResponse(res) } }, fail: (err) => { this.handleRequestError(err) } }) }, // 处理单个行程的地图数据 processPlanMapData(plan) { if (!plan || !Array.isArray(plan.day_plans) || plan.day_plans.length === 0) { console.warn('无效的行程数据或没有天数数据', plan); this.setData({ latestPlanMapData: { showMap: false, markers: [], polylines: [], includePoints: [] } }); return; } const markers = []; const polylines = []; const includePoints = []; const dayColors = ['#e54d42', '#f37b1d', '#1cbbb4', '#0081ff', '#6739b6', '#9c26b0', '#e03997']; try { // 处理每一天的景点 plan.day_plans.forEach((day, dayIndex) => { if (!day || !Array.isArray(day.spots)) { console.warn('无效的天数据或没有景点数据', day); return; } const dayColor = dayColors[dayIndex % dayColors.length]; const dayPoints = []; // 处理当天景点 day.spots.forEach((spot, spotIndex) => { if (!spot || spot.latitude === undefined || spot.longitude === undefined) { console.warn('景点缺少位置信息', spot); return; } const markerId = dayIndex * 100 + spotIndex; markers.push({ id: markerId, latitude: spot.latitude, longitude: spot.longitude, iconPath: spot.has_checked ? '/images/marker.png' : '/images/marker-default.png', width: 24, height: 24, callout: { content: `第${day.day_number}天 ${spotIndex + 1}. ${spot.name}`, color: '#333', fontSize: 14, borderRadius: 4, display: 'BYCLICK' }, customData: { dayIndex, spotIndex, spotId: spot.id, dayNumber: day.day_number }, label: { content: `${dayIndex + 1}-${spotIndex + 1}`, color: dayColor, fontSize: 12, bgColor: '#ffffff', padding: 4, borderRadius: 4, borderWidth: 1, borderColor: dayColor } }); dayPoints.push({ latitude: spot.latitude, longitude: spot.longitude }); }); // 添加当天路线 if (dayPoints.length > 1) { polylines.push({ points: dayPoints, color: dayColor, width: 4, arrowLine: true, dottedLine: false }); } includePoints.push(...dayPoints); }); // 计算地图中心点和缩放级别 const { center, scale } = this.calculateMapViewport(includePoints); // 更新地图数据 this.setData({ latestPlanMapData: { markers, polylines, latitude: center.latitude, longitude: center.longitude, scale: scale, showMap: markers.length > 0, includePoints, dayColors } }); // 播放路线动画 this.playRouteAnimation(polylines); } catch (error) { console.error('处理地图数据时出错:', error); this.setData({ latestPlanMapData: { showMap: false, markers: [], polylines: [], includePoints: [] } }); } }, // 计算地图视野 calculateMapViewport(points) { if (!points || points.length === 0) { return { center: { latitude: 39.9042, longitude: 116.4074 }, scale: 12 }; } // 计算所有点的边界 const lats = points.map(p => p.latitude); const lngs = points.map(p => p.longitude); const minLat = Math.min(...lats); const maxLat = Math.max(...lats); const minLng = Math.min(...lngs); const maxLng = Math.max(...lngs); // 计算中心点 const center = { latitude: (minLat + maxLat) / 2, longitude: (minLng + maxLng) / 2 }; // 计算缩放级别 const latRange = maxLat - minLat; const lngRange = maxLng - minLng; const maxRange = Math.max(latRange, lngRange); // 根据范围大小调整缩放级别 let scale = 15 - Math.floor(maxRange * 15); scale = Math.max(10, Math.min(scale, 17)); return { center, scale }; }, // 播放路线动画 playRouteAnimation(polylines) { if (!polylines || polylines.length === 0) return; // 初始状态:所有路线半透明 const transparentPolylines = polylines.map(line => ({ ...line, color: line.color + '80' // 添加透明度 })); this.setData({ 'latestPlanMapData.polylines': transparentPolylines }); // 逐个显示路线 let i = 0; const timer = setInterval(() => { if (i >= polylines.length) { clearInterval(timer); return; } const updatedPolylines = [...polylines]; updatedPolylines[i] = { ...updatedPolylines[i], color: polylines[i].color.replace('80', '') // 移除透明度 }; this.setData({ 'latestPlanMapData.polylines': updatedPolylines }); i++; }, 500); }, // 切换显示指定天数的路线 switchMapDay(e) { const dayIndex = e.currentTarget.dataset.day; const dayColors = ['#e54d42', '#f37b1d', '#1cbbb4', '#0081ff', '#6739b6', '#9c26b0', '#e03997']; this.setData({ currentMapDay: dayIndex }); if (!this.data.inProgressPlans.length) return; const plan = this.data.inProgressPlans[0]; const day = plan.day_plans[dayIndex]; const dayColor = dayColors[dayIndex % dayColors.length]; // 1. 准备当天的景点数据 const markers = []; const includePoints = []; day.spots.forEach((spot, spotIndex) => { if (!spot || !spot.latitude || !spot.longitude) return; const markerId = dayIndex * 100 + spotIndex; markers.push({ id: markerId, latitude: spot.latitude, longitude: spot.longitude, iconPath: spot.has_checked ? '/images/marker.png' : '/images/marker-default.png', width: 24, height: 24, callout: { content: `第${day.day_number}天 ${spotIndex + 1}. ${spot.name}`, color: '#333', fontSize: 14, borderRadius: 4, display: 'BYCLICK' }, customData: { dayIndex, spotIndex, spotId: spot.id, dayNumber: day.day_number }, label: { content: `${dayIndex + 1}-${spotIndex + 1}`, color: dayColor, fontSize: 12, bgColor: '#ffffff', padding: 4, borderRadius: 4, borderWidth: 1, borderColor: dayColor } }); includePoints.push({ latitude: spot.latitude, longitude: spot.longitude }); }); // 2. 生成当天路线 const polylines = []; if (day.spots.length > 1) { const points = day.spots .filter(spot => spot.latitude && spot.longitude) .map(spot => ({ latitude: spot.latitude, longitude: spot.longitude })); if (points.length > 1) { polylines.push({ points: points, color: dayColor, // 使用当天专属颜色 width: 4, arrowLine: true, dottedLine: false }); } } // 3. 计算地图视野 const { center, scale } = this.calculateMapViewport(includePoints); // 4. 更新地图数据 this.setData({ latestPlanMapData: { markers, polylines, latitude: center.latitude, longitude: center.longitude, scale, showMap: markers.length > 0, includePoints, dayColors: [dayColor] // 只保留当前天的颜色 } }); // 5. 播放路线动画 this.playRouteAnimation(polylines); }, // 重新定位到所有景点 resetToAllAttractions() { this.setData({ currentMapDay: -1 }); // 重新处理地图数据,显示所有景点 if (this.data.inProgressPlans.length > 0) { this.processPlanMapData(this.data.inProgressPlans[0]); } }, // 地图缩放控制 handleZoomIn() { this.setData({ 'latestPlanMapData.scale': Math.min(this.data.latestPlanMapData.scale + 1, 18) }); }, handleZoomOut() { this.setData({ 'latestPlanMapData.scale': Math.max(this.data.latestPlanMapData.scale - 1, 10) }); }, // 处理标记点点击 handleMarkerTap(e) { const markerId = e.detail.markerId; const marker = this.data.latestPlanMapData.markers.find(m => m.id === markerId); if (!marker || !this.data.inProgressPlans || this.data.inProgressPlans.length === 0) { console.error('无法找到标记或行程数据'); return; } const { dayIndex, spotIndex, spotId } = marker.customData || {}; const spot = this.data.inProgressPlans[0].day_plans[dayIndex].spots[spotIndex]; if (!spot) { console.error('无法找到景点数据'); return; } // 显示加载状态 this.setData({ showSpotModal: true, currentSpot: { ...spot, isLoadingImage: true // 添加加载状态 }, currentDayIndex: dayIndex, currentSpotIndex: spotIndex }); // 获取景点图片 this.fetchAttractionImage(spot).then(imageUrl => { this.setData({ 'currentSpot.image': imageUrl, 'currentSpot.isLoadingImage': false }); }).catch(err => { console.error('获取景点图片失败:', err); this.setData({ 'currentSpot.isLoadingImage': false }); }); }, // 从API获取景点图片 fetchAttractionImage(spot) { return new Promise((resolve, reject) => { // 如果已经有有效图片,直接返回 if (spot.image && !spot.image.includes('default')) { resolve(spot.image); return; } // 获取城市名称 let cityName = '济南'; // 默认值 if (spot.city_id && this.data.cityOptions) { const city = this.data.cityOptions.find(c => c.value === spot.city_id); if (city) cityName = city.label.replace(/市$/, ''); } wx.request({ url: `${app.globalData.apiBaseUrl}/api/attractions/image/`, method: 'GET', data: { name: spot.name, city: cityName }, success: (res) => { if (res.data.status === 'success' && res.data.image_url) { // 检查URL是否完整,如果不完整则补全 const imageUrl = res.data.image_url.startsWith('http') ? res.data.image_url : `${app.globalData.mediaBaseUrl}${res.data.image_url}`; resolve(imageUrl); } else { reject(new Error('未获取到有效图片')); } }, fail: (err) => { reject(err); } }); }); }, // 显示景点详情 showSpotDetail(e) { const dayIndex = e.currentTarget.dataset.day; const spotIndex = e.currentTarget.dataset.spot; const spotId = e.currentTarget.dataset.spotid; const spot = this.data.inProgressPlans[0].day_plans[dayIndex].spots[spotIndex]; // 显示加载状态 this.setData({ showSpotModal: true, currentSpot: { ...spot, isLoadingImage: true // 添加加载状态 }, currentDayIndex: dayIndex, currentSpotIndex: spotIndex }); // 获取景点图片 this.fetchAttractionImage(spot).then(imageUrl => { this.setData({ 'currentSpot.image': imageUrl, 'currentSpot.isLoadingImage': false }); }).catch(err => { console.error('获取景点图片失败:', err); this.setData({ 'currentSpot.isLoadingImage': false, 'currentSpot.image': '/images/default-spot.png' // 设置默认图片 }); }); }, // 隐藏景点详情 hideSpotModal() { this.setData({ showSpotModal: false }); }, // 打卡景点 checkInSpot(e) { const dayIndex = e.currentTarget.dataset.day; const spotIndex = e.currentTarget.dataset.spot; const spotId = e.currentTarget.dataset.spotid; const planId = this.data.inProgressPlans[0]?.id; // 获取当前景点数据 const spot = this.data.inProgressPlans[0].day_plans[dayIndex].spots[spotIndex]; // 获取该景点的所有打卡记录 this.getSpotCheckinRecords(spotId, planId).then(records => { // 如果有打卡记录,使用最后一条记录的数据 const lastRecord = records.length > 0 ? records[0] : null; this.setData({ tempCheckinData: { dayIndex, spotIndex, spotId, planId, isEdit: spot.has_checked // 标记是否为编辑模式 }, showCheckinModal: true, checkinImage: lastRecord?.image_url || spot.checkin_images?.[0] || '', checkinNote: lastRecord?.note || spot.checkin_note || '' }); }).catch(err => { console.error('获取打卡记录失败:', err); // 失败时仍显示基本数据 this.setData({ tempCheckinData: { dayIndex, spotIndex, spotId, planId, isEdit: spot.has_checked }, showCheckinModal: true, checkinImage: spot.checkin_images?.[0] || '', checkinNote: spot.checkin_note || '' }); }); }, // 获取景点的打卡记录 getSpotCheckinRecords(spotId, planId) { return new Promise((resolve, reject) => { wx.request({ url: `${app.globalData.apiBaseUrl}/api/user/checkins/`, method: 'GET', data: { spot_id: spotId, plan_id: planId }, header: { 'Authorization': 'Token ' + app.globalData.token }, success: (res) => { if (res.statusCode === 200) { // 确保返回的数据是当前景点的打卡记录 const filteredRecords = res.data.data?.checkins.filter(record => record.spot_id.toString() === spotId.toString() ) || []; resolve(filteredRecords); } else { reject(new Error(res.data.message || '获取打卡记录失败')); } }, fail: (err) => { reject(err); } }); }); }, chooseCheckinImage() { wx.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'], success: (res) => { this.setData({ checkinImage: res.tempFilePaths[0], isUploading: true }); // 上传图片 this.uploadCheckinImage(res.tempFilePaths[0]); } }); }, // 上传打卡图片 uploadCheckinImage(tempFilePath) { wx.uploadFile({ url: app.globalData.apiBaseUrl + '/api/upload/checkin-image/', filePath: tempFilePath, name: 'image', header: { 'Authorization': 'Token ' + app.globalData.token, 'Content-Type': 'multipart/form-data' }, success: (res) => { try { const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data; if (data.status === 'success') { this.setData({ checkinImage: data.data.image_url, isUploading: false }); } else { wx.showToast({ title: '图片上传失败', icon: 'none' }); this.setData({ isUploading: false }); } } catch (e) { console.error('解析响应失败:', e); wx.showToast({ title: '处理响应失败', icon: 'none' }); this.setData({ isUploading: false }); } }, fail: (err) => { console.error('上传失败:', err); wx.showToast({ title: '上传失败', icon: 'none' }); this.setData({ isUploading: false }); } }); }, // 文案输入处理 onCheckinNoteInput(e) { this.setData({ checkinNote: e.detail.value }); }, // 提交打卡 submitCheckin() { const { dayIndex, spotIndex, spotId, planId, isEdit } = this.data.tempCheckinData; const { checkinImage, checkinNote } = this.data; if (!checkinImage) { wx.showToast({ title: '请上传打卡照片', icon: 'none' }); return; } wx.showLoading({ title: isEdit ? '更新打卡中...' : '提交打卡中...', mask: true }); // 统一使用POST方法,后端可以通过操作类型区分 wx.request({ url: `${app.globalData.apiBaseUrl}/api/user/checkin/`, method: 'POST', data: { spot_id: spotId.toString(), plan_id: planId.toString(), image_url: checkinImage, note: checkinNote, is_edit: isEdit // 添加编辑标记 }, header: { 'Authorization': 'Token ' + app.globalData.token, 'Content-Type': 'application/json' }, success: (res) => { wx.hideLoading(); // 接受200或201状态码 if (res.statusCode === 200 || res.statusCode === 201) { try { // 处理响应数据 const responseData = typeof res.data === 'string' ? JSON.parse(res.data) : res.data; if (responseData.status === 'success') { // 更新本地数据 const keyPath = `inProgressPlans[0].day_plans[${dayIndex}].spots[${spotIndex}]`; this.setData({ [keyPath]: { ...this.data.inProgressPlans[0].day_plans[dayIndex].spots[spotIndex], has_checked: true, checkin_images: [checkinImage], checkin_note: checkinNote }, showCheckinModal: false, 'currentSpot.has_checked': true, 'currentSpot.checkin_images': [checkinImage], 'currentSpot.checkin_note': checkinNote }); wx.showToast({ title: isEdit ? '更新成功' : '打卡成功', icon: 'success', duration: 2000 }); this.updateMarkerAfterCheckIn(dayIndex, spotIndex); this.loadInProgressPlans(); // 刷新数据 } else { throw new Error(responseData.message || '操作失败'); } } catch (e) { console.error('处理响应数据失败:', e); wx.showToast({ title: '处理响应数据失败', icon: 'none' }); } } else { throw new Error(res.data?.message || `请求失败,状态码: ${res.statusCode}`); } }, fail: (err) => { wx.hideLoading(); console.error('请求失败:', err); wx.showToast({ title: '网络错误,请检查连接', icon: 'none' }); } }); }, // 关闭打卡弹窗 closeCheckinModal() { this.setData({ showCheckinModal: false, checkinImage: '', checkinNote: '' }); }, // 更新地图标记点状态 updateMarkerAfterCheckIn(dayIndex, spotIndex) { const markerId = dayIndex * 100 + spotIndex; const markers = this.data.latestPlanMapData.markers.map(marker => { if (marker.id === markerId) { return { ...marker, iconPath: '/images/marker.png', callout: { // 更新callout内容 ...marker.callout, content: `已打卡 - ${marker.callout.content}` } }; } return marker; }); this.setData({ 'latestPlanMapData.markers': markers }); }, // 导航到景点位置 navigateToSpot() { const { latitude, longitude, name, address } = this.data.currentSpot; // 验证坐标是否存在 if (!latitude || !longitude) { wx.showToast({ title: '该地点缺少位置信息', icon: 'none' }); return; } // 使用微信内置地图 wx.openLocation({ latitude: Number(latitude), longitude: Number(longitude), name: name || '目的地', address: address || '', // 添加详细地址 scale: 18 // 缩放级别 }); }, // 跳转到详情页 navigateToDetail(e) { const planId = e.currentTarget.dataset.id wx.navigateTo({ url: `/pages/xingchengxiangqing/xingchengxiangqing?id=${planId}` }) }, // 跳转到创建行程页 navigateToCreate() { wx.navigateTo({ url: '/pages/xingchengguihua/xingchengguihua' }) }, // 分享行程 sharePlan(e) { const planId = e.currentTarget.dataset.id; let plan; // 根据当前选项卡确定要分享的行程 if (this.data.activeTab === 'in_progress' && this.data.inProgressPlans.length > 0) { plan = this.data.inProgressPlans[0]; } else if (this.data.activeTab === 'completed') { plan = this.data.completedPlans.find(p => p.id === planId); } else if (this.data.activeTab === 'all') { plan = this.data.allPlans.find(p => p.id === planId); } if (!plan) return; wx.showShareMenu({ withShareTicket: true }); }, onShareAppMessage() { let plan; // 根据当前选项卡确定要分享的行程 if (this.data.activeTab === 'in_progress' && this.data.inProgressPlans.length > 0) { plan = this.data.inProgressPlans[0]; } else if (this.data.activeTab === 'completed' && this.data.completedPlans.length > 0) { plan = this.data.completedPlans[0]; } else if (this.data.activeTab === 'all' && this.data.allPlans.length > 0) { plan = this.data.allPlans[0]; } if (!plan) return {}; return { title: plan.title || '我的红色之旅行程', path: `/pages/xingchengxiangqing/xingchengxiangqing?id=${plan.id}`, imageUrl: plan.day_plans[0]?.spots[0]?.image || '/images/red-tourism-share.jpg' }; }, // 处理错误响应 handleErrorResponse(res) { let errorMsg = '加载失败' if (res.data && res.data.message) { errorMsg += ': ' + res.data.message } if (res.statusCode === 401) { errorMsg = '登录已过期,请重新登录' this.showLoginModal() } wx.showToast({ title: errorMsg, icon: 'none' }) }, // 处理请求错误 handleRequestError(err) { console.error('请求失败:', err) wx.showToast({ title: '网络错误,请检查网络连接', icon: 'none' }) }, // 显示登录弹窗 showLoginModal() { wx.showModal({ title: '登录过期', content: '您的登录已过期,请重新登录', confirmText: '去登录', success: (res) => { if (res.confirm) { wx.navigateTo({ url: '/pages/login/login' }) } } }) } })