From 27d65ea08f6c6f6338b673a36cde38ac7028a3ae Mon Sep 17 00:00:00 2001 From: Lxy Date: Sun, 7 Jun 2026 11:05:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E5=AF=BC=E5=87=BAhtml?= =?UTF-8?q?=E7=9A=84demow=E6=96=87=E4=BB=B6=EF=BC=9B=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=AF=BC=E5=87=BAhtml=E5=8A=9F=E8=83=BD=EF=BC=8C=E7=9B=AE?= =?UTF-8?q?=E5=89=8D=E5=8A=A0=E8=BD=BD=E5=9C=B0=E5=9B=BE=E4=BE=9D=E7=84=B6?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/demo/demo.html | 948 ++++++++++++++++++++++++++++++ src/components/Workbench.vue | 26 +- src/services/exportHtmlService.js | 700 +++++++++++++++++----- 3 files changed, 1508 insertions(+), 166 deletions(-) create mode 100644 design/demo/demo.html diff --git a/design/demo/demo.html b/design/demo/demo.html new file mode 100644 index 0000000..efa7c15 --- /dev/null +++ b/design/demo/demo.html @@ -0,0 +1,948 @@ +云南4天自驾行程规划 - 交互式地图
正在加载地图...
请稍候
⚠️ 地图加载失败
请检查网络或稍后重试。

🚗 云南4天自驾行程规划

北京出发 · 9月 · 昆明落地自驾
总里程 ~1450km
\ No newline at end of file diff --git a/src/components/Workbench.vue b/src/components/Workbench.vue index 1d63708..9a0f793 100644 --- a/src/components/Workbench.vue +++ b/src/components/Workbench.vue @@ -235,12 +235,17 @@ const toggleRoute = () => { function exportCurrentScheme() { const idx = store.activeSchemeIndex + let scheme + if (idx >= 0 && idx < store.quickSchemes.length) { - // 导出完整的方案数据 - exportToHtml(store.quickSchemes[idx], `${store.quickSchemes[idx].name || '行程规划'}.html`) + // 使用完整的方案数据,但 points 使用当前 store.points(包含所有详细信息) + scheme = { + ...store.quickSchemes[idx], + points: JSON.parse(JSON.stringify(store.points)) // 深拷贝完整 points 数据 + } } else { // 从 points 构建方案数据导出 - const scheme = { + scheme = { name: '我的行程', route: store.points.map(p => p.name).join(' → '), days: store.points.length, @@ -248,20 +253,11 @@ function exportCurrentScheme() { totalDriveTime: store.totalDriveTime, budget: '—', highlights: [], - daysDetail: store.points.map((p, i) => ({ - location: p.name, - desc: p.desc, - km: p.km, - driveTime: p.driveTime, - schedule: p.schedule || [], - foods: p.foods || [], - waypoints: p.waypoints || [], - hotel: p.hotel || '' - })), - tips: '' + points: JSON.parse(JSON.stringify(store.points)) // 深拷贝完整 points 数据 } - exportToHtml(scheme, '我的行程.html') } + + exportToHtml(scheme, `${scheme.name || '行程规划'}.html`) } // 监听 points 和 phase 变化,当进入工作台且有有效数据时自动获取真实路径 diff --git a/src/services/exportHtmlService.js b/src/services/exportHtmlService.js index a5a7fb4..7720190 100644 --- a/src/services/exportHtmlService.js +++ b/src/services/exportHtmlService.js @@ -1,8 +1,15 @@ -// 导出可交互的 HTML 行程文件 +// 导出可交互的 HTML 行程文件(包含地图和站点交互,样式与工作台一致) export function exportToHtml(scheme, filename = null) { if (!scheme) return - const html = generateHtml(scheme) + // 使用完整的 points 数据(包含 schedule, foods, waypoints, gallery 等) + const points = scheme.points || [] + if (!points || points.length === 0) { + console.error('导出失败:没有站点数据') + return + } + + const html = generateHtml(scheme, points) const blob = new Blob([html], { type: 'text/html;charset=utf-8' }) const url = URL.createObjectURL(blob) const link = document.createElement('a') @@ -14,25 +21,102 @@ export function exportToHtml(scheme, filename = null) { URL.revokeObjectURL(url) } -function generateHtml(scheme) { - const daysDetail = scheme.daysDetail || [] - const points = [] +// 检查 URL 是否安全 +function isSafeUrl(url) { + if (!url) return false + return url.startsWith('http://') || url.startsWith('https://') +} + +// 过滤安全的图片 URL +function getSafeGallery(gallery) { + return (gallery || []).filter(g => isSafeUrl(g.url)) +} + +// 生成站点详情 HTML(用于初始化页面) +function generatePointDetail(p) { + let html = '' + + // 统计信息 + html += `
+
${p.km || '—'}
行驶里程
+
${p.driveTime || '—'}
驾驶时间
+
${p.day || 'Day 1'}
第几天
+
` - // 从 daysDetail 中提取站点信息 - daysDetail.forEach((day, idx) => { - points.push({ - name: day.location || `Day ${idx + 1}`, - day: `Day ${idx + 1}`, - desc: day.desc || '', - km: day.km || '—', - driveTime: day.driveTime || '—', - schedule: day.schedule || [], - foods: day.foods || [], - waypoints: day.waypoints || [], - hotel: day.hotel || '' + // 描述 + if (p.desc) { + html += `

${p.desc}

` + } + + // 照片画廊 + const safeGallery = getSafeGallery(p.gallery); + if (safeGallery.length > 0) { + html += '' + } + + // 途径推荐 + if (p.waypoints && p.waypoints.length > 0) { + html += '

🗺️ 途径推荐

' + p.waypoints.forEach(wp => { + html += `
+
${wp.icon || '📍'}
+
${wp.name}
${wp.desc || ''}
+
` + }) + html += '
' + } + + // 行程安排 + if (p.schedule && p.schedule.length > 0) { + html += '

📅 行程安排

' + p.schedule.forEach(s => { + html += `
+ ${s.time} +
+
${s.title || s.content || ''}
+ ${s.desc ? `
${s.desc}
` : ''} +
+
` + }) + html += '
' + } + + // 美食推荐 + if (p.foods && p.foods.length > 0) { + html += '

🍽️ 美食推荐

' + p.foods.forEach(f => { + const name = typeof f === 'string' ? f : (f.name || '') + const icon = typeof f === 'object' ? (f.icon || '🍜') : '🍜' + const desc = typeof f === 'object' ? (f.desc || '') : '' + html += `
+
${icon}
+
+
${name}
+ ${desc ? `
${desc}
` : ''} +
+
` }) - }) + html += '
' + } + // 住宿推荐 + if (p.hotel) { + html += `

🏨 住宿推荐

${p.hotel}
` + } + + // 注意事项 + if (p.tips) { + html += `

💡 注意事项

${p.tips}
` + } + + return html +} + +function generateHtml(scheme, points) { return ` @@ -41,153 +125,467 @@ function generateHtml(scheme) { ${scheme.name || '行程规划'} -
-
-

${scheme.name || '行程规划'}

-
- 📍 ${scheme.route || '—'} - 📅 ${scheme.days || '—'}天 - 🚗 ~${scheme.totalKm || '—'}km - 💰 ${scheme.budget || '—'} +
+
+
正在加载地图...
+
请稍候
+
+ +
+ +
+
行程时间线
+
+
+ + +
+
+
${points[0]?.name || ''}
+
${points[0]?.day || 'Day 1'} · ${points[0]?.km || '—'}km · 驾车${points[0]?.driveTime || '—'}
+
+
+ ${generatePointDetail(points[0])}
- - ${scheme.highlights && scheme.highlights.length > 0 ? ` -
-

✨ 行程亮点

-
    - ${scheme.highlights.map(h => `
  • ${h}
  • `).join('')} -
+ + +
+
+ 行程地图 +
+
+
+ +
- ` : ''} +
-
- ${points.map((p, i) => ` -
Day ${i + 1}
- `).join('')} -
+