98 lines
3.7 KiB
JavaScript
98 lines
3.7 KiB
JavaScript
// 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');
|
|
|
|
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 `<span class="active-lang">${lContent.langName}</span>`;
|
|
return `<a href="../${l}/index.html">${lContent.langName}</a>`;
|
|
}).join('');
|
|
html = html.replace(/{{languageLinks}}/g, langLinksHtml);
|
|
|
|
// 表头
|
|
const headersHtml = content.headers.map(h => `<th>${h}</th>`).join('');
|
|
html = html.replace(/{{tableHeaders}}/g, headersHtml);
|
|
|
|
// 表格行 + 详情行
|
|
const rowsHtml = content.cities.map((city, idx) => `
|
|
<tr id="row-${idx}" class="city-row" onclick="toggleDetails(${idx})">
|
|
<td>
|
|
<div class="city-name-cell">
|
|
<strong>${city.name}</strong>
|
|
<span class="tag-region">${city.region}</span>
|
|
</div>
|
|
</td>
|
|
<td>${city.matches}</td>
|
|
<td style="font-weight:600">${city.budget}</td>
|
|
<td><span class="tag-visa ${city.vCls}">${city.visa}</span></td>
|
|
<td style="color:#64748b; font-size:13px">${city.tips}</td>
|
|
</tr>
|
|
<tr id="details-${idx}" class="detail-pane">
|
|
<td colspan="5">
|
|
<div class="detail-content">
|
|
<div class="info-box">
|
|
<h4>${content.ui_stadium}</h4>
|
|
<div class="info-text">${city.std}</div>
|
|
</div>
|
|
<div class="info-box">
|
|
<h4>${content.ui_logistics}</h4>
|
|
<div class="info-text">${city.log}</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
`).join('');
|
|
|
|
html = html.replace(/{{tableRows}}/g, rowsHtml);
|
|
|
|
const distDir = path.join(__dirname, 'dist');
|
|
const outputDir = path.join(distDir, lang);
|
|
if (!fs.existsSync(distDir)) fs.mkdirSync(distDir);
|
|
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir);
|
|
fs.writeFileSync(path.join(outputDir, 'index.html'), html);
|
|
console.log(`✅ ${lang} 版生成完毕`);
|
|
});
|
|
|
|
// 生成 sitemap.xml
|
|
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
${data.languages.map(lang => `
|
|
<url>
|
|
<loc>${data.siteConfig.domain}${data.siteConfig.basePath}/${lang}/index.html</loc>
|
|
<lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
|
|
<priority>0.80</priority>
|
|
</url>`).join('')}
|
|
</urlset>`;
|
|
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 已生成');
|