134 lines
4.3 KiB
TypeScript
134 lines
4.3 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
||
import { getPayload } from 'payload'
|
||
import config from '@payload-config'
|
||
|
||
/**
|
||
* GET /api/home
|
||
* 获取首页所有数据:公告 + Hero Slider + 产品推荐(含完整产品信息)
|
||
*/
|
||
export async function GET(req: NextRequest) {
|
||
try {
|
||
const payload = await getPayload({ config })
|
||
|
||
// 获取首页公告(已发布且在首页显示)
|
||
const announcements = await payload.find({
|
||
collection: 'announcements',
|
||
where: {
|
||
and: [
|
||
{
|
||
status: {
|
||
equals: 'published',
|
||
},
|
||
},
|
||
{
|
||
showOnHomepage: {
|
||
equals: true,
|
||
},
|
||
},
|
||
],
|
||
},
|
||
sort: '-priority',
|
||
limit: 10,
|
||
})
|
||
|
||
// 获取 Hero Slider
|
||
const heroSlider = await payload.findGlobal({
|
||
slug: 'hero-slider',
|
||
})
|
||
|
||
// 获取产品推荐(depth: 2 足以拿到产品文档及其直接关联字段)
|
||
const productRecommendations = await payload.findGlobal({
|
||
slug: 'product-recommendations',
|
||
depth: 2,
|
||
})
|
||
|
||
// 构建响应数据
|
||
const response = {
|
||
announcements: announcements.docs.map((announcement) => ({
|
||
id: announcement.id,
|
||
title: announcement.title,
|
||
type: announcement.type,
|
||
summary: announcement.summary,
|
||
priority: announcement.priority,
|
||
publishedAt: announcement.publishedAt,
|
||
})),
|
||
heroSlider: {
|
||
slides: heroSlider.slides || [],
|
||
},
|
||
productRecommendations: {
|
||
enabled: productRecommendations.enabled || false,
|
||
lists: (productRecommendations.lists || []).map((list: any) => ({
|
||
title: list.title,
|
||
subtitle: list.subtitle,
|
||
preorder: list.preorder || false,
|
||
products: (list.products || []).map((productRef: any) => {
|
||
const product = productRef.value
|
||
|
||
// description 是纯文本(从 Medusa 同步)
|
||
const description = product.description || ''
|
||
|
||
// 基础产品信息
|
||
const baseInfo = {
|
||
id: product.id,
|
||
medusaId: product.medusaId,
|
||
handle: product.handle || null,
|
||
seedId: product.seedId,
|
||
title: product.title,
|
||
thumbnail: product.thumbnail,
|
||
status: product.status,
|
||
description,
|
||
content: product.content || null,
|
||
startPrice: product.startPrice ?? null,
|
||
}
|
||
|
||
// 如果是预购产品,添加预购特有字段
|
||
if (productRef.relationTo === 'preorder-products') {
|
||
const realOrderCount = product.orderCount || 0
|
||
const fakeOrderCount = product.fakeOrderCount || 0
|
||
const totalCount = realOrderCount + fakeOrderCount
|
||
return {
|
||
...baseInfo,
|
||
relationTo: 'preorder-products',
|
||
preorder: {
|
||
type: product.preorderType || 'standard',
|
||
fundingGoal: product.fundingGoal || 0,
|
||
orderCount: totalCount,
|
||
startDate: product.preorderStartDate,
|
||
endDate: product.preorderEndDate,
|
||
// 计算进度百分比(含 fakeOrderCount,用于展示,不限制 100 以支持超出显示)
|
||
progress: product.fundingGoal > 0
|
||
? Math.round((totalCount / product.fundingGoal) * 100)
|
||
: 0,
|
||
// 计算剩余天数
|
||
daysLeft: product.preorderEndDate
|
||
? Math.max(0, Math.ceil((new Date(product.preorderEndDate).getTime() - Date.now()) / (1000 * 60 * 60 * 24)))
|
||
: null,
|
||
// 支持者数量(含 fakeOrderCount,用于展示)
|
||
backers: totalCount,
|
||
},
|
||
}
|
||
}
|
||
|
||
// 普通产品
|
||
return {
|
||
...baseInfo,
|
||
relationTo: 'products',
|
||
}
|
||
}),
|
||
})),
|
||
},
|
||
}
|
||
|
||
return NextResponse.json(response, { status: 200 })
|
||
} catch (error: any) {
|
||
console.error('Error fetching homepage data:', error)
|
||
return NextResponse.json(
|
||
{
|
||
error: 'Failed to fetch homepage data',
|
||
message: error.message,
|
||
},
|
||
{ status: 500 }
|
||
)
|
||
}
|
||
}
|