feat: 官网代码全量更新
覆盖最新版本代码,包含: - 新增品牌百科、公司百科页面及CMS管理 - 新增微信引导组件(WechatCTA) - 新增品牌/公司图片资源 - 全站组件/页面/数据/样式更新 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
这个提交包含在:
+96
-49
@@ -1,64 +1,105 @@
|
||||
export default defineEventHandler((event) => {
|
||||
const pages = [
|
||||
{
|
||||
url: '/', priority: '1.0', changefreq: 'weekly',
|
||||
images: [{ loc: '/images/team/hero-grassland.jpg', title: '呼伦贝尔草原风光 - 呼籁旅行' }],
|
||||
},
|
||||
{
|
||||
url: '/faq', priority: '0.95', changefreq: 'weekly',
|
||||
images: [],
|
||||
},
|
||||
{
|
||||
url: '/products', priority: '0.9', changefreq: 'weekly',
|
||||
images: [{ loc: '/images/mascot/xiaomengma.png', title: '小蒙马夏令营IP形象' }],
|
||||
},
|
||||
{
|
||||
url: '/about', priority: '0.85', changefreq: 'monthly',
|
||||
images: [
|
||||
{ loc: '/images/team/hero-family.jpg', title: '呼伦贝尔家庭游合影' },
|
||||
{ loc: '/images/team/guide-group.jpg', title: '呼籁旅行领队团队合影' },
|
||||
{ loc: '/images/mascot/mascot-front.png', title: '呼籁旅行吉祥物' },
|
||||
],
|
||||
},
|
||||
{
|
||||
url: '/reviews', priority: '0.8', changefreq: 'weekly',
|
||||
images: [],
|
||||
},
|
||||
{
|
||||
url: '/contact', priority: '0.8', changefreq: 'monthly',
|
||||
images: [{ loc: '/images/contact/qrcode-wechat.jpg', title: '呼籁旅行微信客服二维码' }],
|
||||
},
|
||||
{
|
||||
url: '/guides', priority: '0.8', changefreq: 'monthly',
|
||||
images: [],
|
||||
},
|
||||
{
|
||||
url: '/summer-camp', priority: '0.85', changefreq: 'monthly',
|
||||
images: [
|
||||
{ loc: '/images/summer-camp/river-banner.jpg', title: '小蒙马夏令营河畔活动' },
|
||||
{ loc: '/images/summer-camp/grassland-group.jpg', title: '草原亲子夏令营合影' },
|
||||
{ loc: '/images/summer-camp/birch-group.jpg', title: '白桦林研学活动' },
|
||||
{ loc: '/images/summer-camp/camp-graduation.jpg', title: '夏令营结营仪式' },
|
||||
],
|
||||
},
|
||||
]
|
||||
import { eq, desc } from 'drizzle-orm'
|
||||
import { useDB, schema } from '../utils/db.js'
|
||||
|
||||
export default defineEventHandler((event) => {
|
||||
const db = useDB()
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
const base = 'https://1814.love'
|
||||
|
||||
// ── 静态页面 ──
|
||||
const staticPages = [
|
||||
{ url: '/', priority: '1.0', changefreq: 'weekly', images: [{ loc: '/images/team/hero-grassland.jpg', title: '呼伦贝尔草原风光 - 呼籁旅行' }] },
|
||||
{ url: '/products', priority: '0.9', changefreq: 'weekly', images: [{ loc: '/images/mascot/xiaomengma.png', title: '小蒙马亲子游学营IP形象' }] },
|
||||
{ url: '/faq', priority: '0.95', changefreq: 'weekly', images: [] },
|
||||
{ url: '/reviews', priority: '0.8', changefreq: 'weekly', images: [] },
|
||||
{ url: '/about', priority: '0.85', changefreq: 'monthly', images: [{ loc: '/images/team/hero-family.jpg', title: '呼伦贝尔家庭游合影' }, { loc: '/images/team/guide-group.jpg', title: '呼籁旅行领队团队合影' }] },
|
||||
{ url: '/contact', priority: '0.8', changefreq: 'monthly', images: [{ loc: '/images/contact/qrcode-wechat.jpg', title: '呼籁旅行微信客服二维码' }] },
|
||||
{ url: '/guides', priority: '0.8', changefreq: 'monthly', images: [] },
|
||||
{ url: '/guide-custom', priority: '0.7', changefreq: 'monthly', images: [] },
|
||||
{ url: '/summer-camp', priority: '0.85', changefreq: 'monthly', images: [{ loc: '/images/summer-camp/river-banner.jpg', title: '小蒙马亲子游学营河畔活动' }] },
|
||||
{ url: '/winter-camp', priority: '0.8', changefreq: 'monthly', images: [] },
|
||||
{ url: '/courses', priority: '0.7', changefreq: 'monthly', images: [] },
|
||||
{ url: '/blog', priority: '0.9', changefreq: 'weekly', images: [] },
|
||||
{ url: '/news', priority: '0.7', changefreq: 'weekly', images: [] },
|
||||
{ url: '/gallery', priority: '0.7', changefreq: 'monthly', images: [] },
|
||||
{ url: '/stories', priority: '0.7', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations', priority: '0.85', changefreq: 'monthly', images: [] },
|
||||
{ url: '/calendar', priority: '0.7', changefreq: 'monthly', images: [] },
|
||||
{ url: '/pricing', priority: '0.8', changefreq: 'monthly', images: [] },
|
||||
{ url: '/selector', priority: '0.7', changefreq: 'monthly', images: [] },
|
||||
{ url: '/customize', priority: '0.8', changefreq: 'monthly', images: [] },
|
||||
{ url: '/brand', priority: '0.7', changefreq: 'monthly', images: [] },
|
||||
{ url: '/company', priority: '0.6', changefreq: 'monthly', images: [] },
|
||||
{ url: '/qualifications', priority: '0.6', changefreq: 'monthly', images: [] },
|
||||
{ url: '/partners', priority: '0.5', changefreq: 'monthly', images: [] },
|
||||
{ url: '/xiaohongshu', priority: '0.7', changefreq: 'weekly', images: [] },
|
||||
{ url: '/youji', priority: '0.7', changefreq: 'weekly', images: [] },
|
||||
// 产品详情页
|
||||
{ url: '/products/v9-5d4n-forest', priority: '0.85', changefreq: 'monthly', images: [] },
|
||||
{ url: '/products/v9-5d4n-prairie', priority: '0.85', changefreq: 'monthly', images: [] },
|
||||
{ url: '/products/v9-6d5n-family', priority: '0.85', changefreq: 'monthly', images: [] },
|
||||
{ url: '/products/v9-6d5n-explore', priority: '0.85', changefreq: 'monthly', images: [] },
|
||||
{ url: '/products/v9-7d6n-family', priority: '0.85', changefreq: 'monthly', images: [] },
|
||||
{ url: '/products/v9-7d6n-wild', priority: '0.85', changefreq: 'monthly', images: [] },
|
||||
{ url: '/products/autumn', priority: '0.8', changefreq: 'monthly', images: [] },
|
||||
{ url: '/products/winter', priority: '0.8', changefreq: 'monthly', images: [] },
|
||||
// 目的地详情页
|
||||
{ url: '/destinations/moriguole', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/eergunashire', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/baihualin', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/enhe-shiwei', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/heishantou', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/manzhouli', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/hulunhu', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/aershan', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/daxinganling', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/aoluguya', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
{ url: '/destinations/genhe', priority: '0.75', changefreq: 'monthly', images: [] },
|
||||
]
|
||||
|
||||
// ── 动态页面:从数据库读取已发布的博客文章 ──
|
||||
const blogArticles = db.select().from(schema.articles)
|
||||
.where(eq(schema.articles.published, true))
|
||||
.orderBy(desc(schema.articles.id))
|
||||
.all()
|
||||
.filter(a => a.type === 'blog')
|
||||
|
||||
const blogPages = blogArticles.map(a => ({
|
||||
url: `/blog/${a.slug}`,
|
||||
priority: '0.8',
|
||||
changefreq: 'monthly',
|
||||
lastmod: a.updatedAt ? a.updatedAt.split('T')[0] : (a.createdAt ? a.createdAt.split('T')[0] : today),
|
||||
images: a.coverImage ? [{ loc: a.coverImage, title: a.title }] : [],
|
||||
}))
|
||||
|
||||
// ── 动态页面:从数据库读取已发布的客户故事 ──
|
||||
const stories = db.select().from(schema.stories)
|
||||
.where(eq(schema.stories.published, true))
|
||||
.all()
|
||||
|
||||
const storyPages = stories.map(s => ({
|
||||
url: `/stories/${s.slug}`,
|
||||
priority: '0.7',
|
||||
changefreq: 'monthly',
|
||||
lastmod: s.createdAt ? s.createdAt.split('T')[0] : today,
|
||||
images: s.coverImage ? [{ loc: s.coverImage, title: s.title }] : [],
|
||||
}))
|
||||
|
||||
const allPages = [...staticPages, ...blogPages, ...storyPages]
|
||||
|
||||
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
|
||||
${pages
|
||||
${allPages
|
||||
.map(
|
||||
(p) => ` <url>
|
||||
<loc>${base}${p.url}</loc>
|
||||
<lastmod>${today}</lastmod>
|
||||
<lastmod>${p.lastmod || today}</lastmod>
|
||||
<changefreq>${p.changefreq}</changefreq>
|
||||
<priority>${p.priority}</priority>${p.images.map(img => `
|
||||
<priority>${p.priority}</priority>${(p.images || []).map(img => `
|
||||
<image:image>
|
||||
<image:loc>${base}${img.loc}</image:loc>
|
||||
<image:title>${img.title}</image:title>
|
||||
<image:loc>${img.loc.startsWith('http') ? img.loc : base + img.loc}</image:loc>
|
||||
<image:title>${escapeXml(img.title)}</image:title>
|
||||
</image:image>`).join('')}
|
||||
</url>`
|
||||
)
|
||||
@@ -66,5 +107,11 @@ ${pages
|
||||
</urlset>`
|
||||
|
||||
setResponseHeader(event, 'content-type', 'application/xml')
|
||||
setHeader(event, 'Cache-Control', 'public, max-age=3600')
|
||||
return xml
|
||||
})
|
||||
|
||||
function escapeXml(str) {
|
||||
if (!str) return ''
|
||||
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''')
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户