首页展示

This commit is contained in:
龟男日记\www 2026-02-22 04:29:53 +08:00
parent 14a2aaced0
commit dc8c88e463
7 changed files with 43 additions and 49 deletions

View File

@ -36,14 +36,12 @@ export async function GET(req: NextRequest) {
slug: 'hero-slider', slug: 'hero-slider',
}) })
// 获取产品推荐(包含深度查询的产品信息 // 获取产品推荐(depth: 2 足以拿到产品文档及其直接关联字段
const productRecommendations = await payload.findGlobal({ const productRecommendations = await payload.findGlobal({
slug: 'product-recommendations', slug: 'product-recommendations',
depth: 3, // 增加深度以确保完全获取嵌套数据 depth: 2,
}) })
console.log('Raw productRecommendations:', JSON.stringify(productRecommendations, null, 2))
// 构建响应数据 // 构建响应数据
const response = { const response = {
announcements: announcements.docs.map((announcement) => ({ announcements: announcements.docs.map((announcement) => ({
@ -66,22 +64,8 @@ export async function GET(req: NextRequest) {
products: (list.products || []).map((productRef: any) => { products: (list.products || []).map((productRef: any) => {
const product = productRef.value const product = productRef.value
// 调试日志:查看实际接收到的产品数据 // description 是纯文本(从 Medusa 同步)
console.log('=== Product Debug Info ===') const description = product.description || ''
console.log('relationTo:', productRef.relationTo)
console.log('product object:', product)
console.log('Available fields:', Object.keys(product || {}))
console.log('=========================')
// 处理 description 字段
// Products 使用 textarea (字符串)PreorderProducts 使用 richText (对象)
let description = ''
if (typeof product.description === 'string') {
description = product.description
} else if (product.description && typeof product.description === 'object') {
// richText 字段,提取纯文本(简单处理)
description = JSON.stringify(product.description)
}
// 基础产品信息 // 基础产品信息
const baseInfo = { const baseInfo = {
@ -92,7 +76,8 @@ export async function GET(req: NextRequest) {
thumbnail: product.thumbnail, thumbnail: product.thumbnail,
status: product.status, status: product.status,
description, description,
minPrice: product.minPrice, content: product.content || null,
startPrice: product.startPrice ?? null,
} }
// 如果是预购产品,添加预购特有字段 // 如果是预购产品,添加预购特有字段

View File

@ -5,7 +5,6 @@ import {
getAllMedusaProducts, getAllMedusaProducts,
transformMedusaProductToPayload, transformMedusaProductToPayload,
getProductCollection, getProductCollection,
convertTextToLexical,
} from '@/lib/medusa' } from '@/lib/medusa'
import { addCorsHeaders, handleCorsOptions } from '@/lib/cors' import { addCorsHeaders, handleCorsOptions } from '@/lib/cors'
@ -137,11 +136,8 @@ export async function POST(request: Request) {
id: existingProduct.id, id: existingProduct.id,
}) })
// 准备移动数据,包括描述转换 // 准备移动数据description 已包含在 productData 中)
const moveData: any = { ...productData } const moveData: any = { ...productData }
if (medusaProduct.description) {
moveData.description = convertTextToLexical(medusaProduct.description)
}
finalProduct = await payload.create({ finalProduct = await payload.create({
collection: targetCollection, collection: targetCollection,
@ -168,10 +164,8 @@ export async function POST(request: Request) {
if (!existingProduct.handle) mergedData.handle = productData.handle if (!existingProduct.handle) mergedData.handle = productData.handle
if (!existingProduct.thumbnail) mergedData.thumbnail = productData.thumbnail if (!existingProduct.thumbnail) mergedData.thumbnail = productData.thumbnail
if (!existingProduct.status) mergedData.status = productData.status if (!existingProduct.status) mergedData.status = productData.status
// 描述为空时也从 Medusa 导入(转换为富文本格式) // description 始终从 Medusa 同步(纯文本,只读字段)
if (!existingProduct.description && medusaProduct.description) { mergedData.description = medusaProduct.description || null
(mergedData as any).description = convertTextToLexical(medusaProduct.description)
}
// 最低价格和 seedId总是更新 // 最低价格和 seedId总是更新
mergedData.seedId = productData.seedId mergedData.seedId = productData.seedId
@ -219,12 +213,9 @@ export async function POST(request: Request) {
}) })
action = 'updated_partial' action = 'updated_partial'
} else { } else {
// 强制更新所有字段(包括描述转换为富文本 // 强制更新所有字段(description 已包含在 productData 中
console.log(`[Sync Product API] ⚡ 强制更新所有字段`) console.log(`[Sync Product API] ⚡ 强制更新所有字段`)
const forceUpdateData: any = { ...productData } const forceUpdateData: any = { ...productData }
if (medusaProduct.description) {
forceUpdateData.description = convertTextToLexical(medusaProduct.description)
}
finalProduct = await payload.update({ finalProduct = await payload.update({
collection: targetCollection, collection: targetCollection,
id: existingProduct.id, id: existingProduct.id,
@ -240,10 +231,7 @@ export async function POST(request: Request) {
// 如果是预购产品,添加预购相关字段 // 如果是预购产品,添加预购相关字段
const createData: any = { ...productData } const createData: any = { ...productData }
// 添加描述(转换为富文本格式) // description 已包含在 productData 中(纯文本,从 Medusa 同步)
if (medusaProduct.description) {
createData.description = convertTextToLexical(medusaProduct.description)
}
if (targetCollection === 'preorder-products') { if (targetCollection === 'preorder-products') {
if (fundingGoal !== undefined) { if (fundingGoal !== undefined) {

View File

@ -163,10 +163,10 @@ export const PreorderProducts: CollectionConfig = {
], ],
}, },
{ {
label: '📝 商品描述', label: '📝 商品详情',
fields: [ fields: [
{ {
name: 'description', name: 'content',
type: 'richText', type: 'richText',
editor: lexicalEditor({ editor: lexicalEditor({
features: [ features: [
@ -217,7 +217,7 @@ export const PreorderProducts: CollectionConfig = {
], ],
}), }),
admin: { admin: {
description: '预售商品的详细描述(支持富文本编辑', description: '预售商品的详细内容(富文本,由 Payload 编辑,展示在产品详情页',
}, },
}, },
], ],

View File

@ -56,7 +56,7 @@ export const Products: CollectionConfig = {
label: '📄 商品详情', label: '📄 商品详情',
fields: [ fields: [
{ {
name: 'description', name: 'content',
type: 'richText', type: 'richText',
editor: lexicalEditor({ editor: lexicalEditor({
features: [ features: [
@ -107,7 +107,7 @@ export const Products: CollectionConfig = {
], ],
}), }),
admin: { admin: {
description: '商品详细描述(支持富文本编辑', description: '商品详细内容(富文本,由 Payload 编辑,展示在产品详情页',
}, },
}, },
], ],

View File

@ -95,6 +95,14 @@ export const ProductBaseFields: Field[] = [
}, },
}, },
}, },
{
name: 'description',
type: 'text',
admin: {
description: '产品简介(纯文本,从 Medusa 同步,显示在卡片和列表页)',
readOnly: true,
},
},
] ]
/** /**

View File

@ -319,6 +319,9 @@ export function transformMedusaProductToPayload(product: MedusaProduct) {
collection: collection, collection: collection,
category: category, category: category,
// 物理属性(优先使用直接字段,否则从 metadata 中提取)
description: product.description || null,
// 物理属性(优先使用直接字段,否则从 metadata 中提取) // 物理属性(优先使用直接字段,否则从 metadata 中提取)
height: product.height || (product.metadata?.height ? Number(product.metadata.height) : null), height: product.height || (product.metadata?.height ? Number(product.metadata.height) : null),
width: product.width || (product.metadata?.width ? Number(product.metadata.width) : null), width: product.width || (product.metadata?.width ? Number(product.metadata.width) : null),

View File

@ -226,9 +226,13 @@ export interface Product {
*/ */
lastSyncedAt?: string | null; lastSyncedAt?: string | null;
/** /**
* * Medusa
*/ */
description?: { description?: string | null;
/**
* Payload
*/
content?: {
root: { root: {
type: string; type: string;
children: { children: {
@ -356,6 +360,10 @@ export interface PreorderProduct {
* *
*/ */
lastSyncedAt?: string | null; lastSyncedAt?: string | null;
/**
* Medusa
*/
description?: string | null;
/** /**
* *
*/ */
@ -381,9 +389,9 @@ export interface PreorderProduct {
*/ */
fakeOrderCount?: number | null; fakeOrderCount?: number | null;
/** /**
* * Payload
*/ */
description?: { content?: {
root: { root: {
type: string; type: string;
children: { children: {
@ -921,6 +929,7 @@ export interface ProductsSelect<T extends boolean = true> {
startPrice?: T; startPrice?: T;
lastSyncedAt?: T; lastSyncedAt?: T;
description?: T; description?: T;
content?: T;
relatedProducts?: T; relatedProducts?: T;
tags?: T; tags?: T;
type?: T; type?: T;
@ -957,13 +966,14 @@ export interface PreorderProductsSelect<T extends boolean = true> {
thumbnail?: T; thumbnail?: T;
startPrice?: T; startPrice?: T;
lastSyncedAt?: T; lastSyncedAt?: T;
description?: T;
preorderType?: T; preorderType?: T;
fundingGoal?: T; fundingGoal?: T;
preorderStartDate?: T; preorderStartDate?: T;
preorderEndDate?: T; preorderEndDate?: T;
orderCount?: T; orderCount?: T;
fakeOrderCount?: T; fakeOrderCount?: T;
description?: T; content?: T;
relatedProducts?: T; relatedProducts?: T;
tags?: T; tags?: T;
type?: T; type?: T;