// build.js const fs = require('fs'); const path = require('path'); const data = require('./data.js'); const template = fs.readFileSync(path.join(__dirname, 'template.html'), 'utf-8'); // 清理并创建 dist 目录 const distDir = path.join(__dirname, 'dist'); if (fs.existsSync(distDir)) { fs.rmSync(distDir, { recursive: true, force: true }); } fs.mkdirSync(distDir); // 创建子目录 const projectSubDir = path.join(distDir, data.siteConfig.basePath.replace(/^\//, '')); if (!fs.existsSync(projectSubDir)) { fs.mkdirSync(projectSubDir, { recursive: true }); } // 拷贝 assets 目录 const assetsDir = path.join(__dirname, 'assets'); const targetAssetsDir = path.join(projectSubDir, 'assets'); if (fs.existsSync(assetsDir)) { if (!fs.existsSync(targetAssetsDir)) fs.mkdirSync(targetAssetsDir, { recursive: true }); fs.cpSync(assetsDir, targetAssetsDir, { recursive: true }); console.log('✅ Assets 已同步'); } data.languages.forEach(lang => { const content = data.content[lang]; let html = template; const fullBasePath = data.siteConfig.basePath; const fullDomain = data.siteConfig.domain; html = html.replace(/{{langCode}}/g, lang); html = html.replace(/{{title}}/g, content.title); html = html.replace(/{{metaDesc}}/g, content.metaDesc); // SEO Dynamic Tags const canonicalUrl = `${fullDomain}${fullBasePath}/${lang}/index.html`; html = html.replace(/{{canonicalUrl}}/g, canonicalUrl); // Use a default OG image or generate one (placeholder for now) html = html.replace(/{{ogImage}}/g, `${fullDomain}${fullBasePath}/assets/og-shared.jpg`); // 语言链接 - 动态生成 (保持相对路径,兼容性更好) const langLinksHtml = data.languages.map(l => { const lContent = data.content[l]; if (l === lang) return `${lContent.langName}`; return `${lContent.langName}`; }).join(''); html = html.replace(/{{languageLinks}}/g, langLinksHtml); // 表头 const headersHtml = content.headers.map(h => `${h}`).join(''); html = html.replace(/{{tableHeaders}}/g, headersHtml); // 表格行 + 详情行 const rowsHtml = content.cities.map((city, idx) => `
${city.name} ${city.region}
${city.matches} ${city.budget} ${city.visa} ${city.tips}

${content.ui_stadium}

${city.std}

${content.ui_logistics}

${city.log}
`).join(''); html = html.replace(/{{tableRows}}/g, rowsHtml); const outputDir = path.join(projectSubDir, lang); if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true }); fs.writeFileSync(path.join(outputDir, 'index.html'), html); console.log(`✅ ${lang} 版生成完毕 (输出至: ${data.siteConfig.basePath}/${lang}/)`); }); // 生成 sitemap.xml const sitemap = ` ${data.languages.map(lang => ` ${data.siteConfig.domain}${data.siteConfig.basePath}/${lang}/index.html ${new Date().toISOString().split('T')[0]} 0.80 `).join('')} `; fs.writeFileSync(path.join(__dirname, 'dist', 'sitemap.xml'), sitemap); console.log('✅ sitemap.xml 已生成'); // 生成 robots.txt const robots = `User-agent: * Allow: / Sitemap: ${data.siteConfig.domain}${data.siteConfig.basePath}/sitemap.xml `; fs.writeFileSync(path.join(__dirname, 'dist', 'robots.txt'), robots); console.log('✅ robots.txt 已生成'); // 生成根目录首页 (PickBetterAI.com 门面) const homeHtml = ` Pick Better AI - Smart Decisions Enhanced by AI
PickBetterAI

Smart Decisions, Enhanced by AI

We help you find the best options in travel, tech, and life.

Active Tool
⚽️

2026 World Cup City Planner

Compare 16 host cities across USA, Canada, and Mexico. Decide where to watch based on match count, budget, and local logistics. Multi-language support included.

Coming Soon
💻

AI Tech Selection

Picking the right AI model or tool for your specific workflow.

Coming Soon
✈️

Smart Travel

Data-driven destination comparison for digital nomads.

© 2026 PickBetterAI.com | All Rights Reserved

`; fs.writeFileSync(path.join(__dirname, 'dist', 'index.html'), homeHtml); console.log('✅ 根目录首页 index.html 已生成');