This commit is contained in:
parent
3ad86524d4
commit
cccbe20aa0
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { ThumbnailCell as ThumbnailCell_a0b2acb813359aec894b6644d7c3bfd2 } from '../../../components/products/ThumbnailCell'
|
||||||
|
import { ThumbnailAndStatusField as ThumbnailAndStatusField_8fa95ec6265982d11b99fbeb81e24c1c } from '../../../components/products/ThumbnailAndStatusField'
|
||||||
import { SyncMedusaButton as SyncMedusaButton_8c90663551920f0510ea531726668adc } from '../../../components/products/SyncMedusaButton'
|
import { SyncMedusaButton as SyncMedusaButton_8c90663551920f0510ea531726668adc } from '../../../components/products/SyncMedusaButton'
|
||||||
import { default as default_3fd1353246fc8a459244c8dc11f58470 } from '../../../components/products/ProductGridStyler'
|
import { default as default_3fd1353246fc8a459244c8dc11f58470 } from '../../../components/products/ProductGridStyler'
|
||||||
import { ForceSyncButton as ForceSyncButton_86f9d5df4f20495427521354d06db618 } from '../../../components/products/ForceSyncButton'
|
import { ForceSyncButton as ForceSyncButton_86f9d5df4f20495427521354d06db618 } from '../../../components/products/ForceSyncButton'
|
||||||
|
|
@ -5,6 +7,8 @@ import { S3ClientUploadHandler as S3ClientUploadHandler_f97aa6c64367fa259c5bc056
|
||||||
import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from '@payloadcms/next/rsc'
|
import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from '@payloadcms/next/rsc'
|
||||||
|
|
||||||
export const importMap = {
|
export const importMap = {
|
||||||
|
"/components/products/ThumbnailCell#ThumbnailCell": ThumbnailCell_a0b2acb813359aec894b6644d7c3bfd2,
|
||||||
|
"/components/products/ThumbnailAndStatusField#ThumbnailAndStatusField": ThumbnailAndStatusField_8fa95ec6265982d11b99fbeb81e24c1c,
|
||||||
"/components/products/SyncMedusaButton#SyncMedusaButton": SyncMedusaButton_8c90663551920f0510ea531726668adc,
|
"/components/products/SyncMedusaButton#SyncMedusaButton": SyncMedusaButton_8c90663551920f0510ea531726668adc,
|
||||||
"/components/products/ProductGridStyler#default": default_3fd1353246fc8a459244c8dc11f58470,
|
"/components/products/ProductGridStyler#default": default_3fd1353246fc8a459244c8dc11f58470,
|
||||||
"/components/products/ForceSyncButton#ForceSyncButton": ForceSyncButton_86f9d5df4f20495427521354d06db618,
|
"/components/products/ForceSyncButton#ForceSyncButton": ForceSyncButton_86f9d5df4f20495427521354d06db618,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export const Products: CollectionConfig = {
|
||||||
description: '管理 Medusa 商品的详细内容和描述',
|
description: '管理 Medusa 商品的详细内容和描述',
|
||||||
listSearchableFields: ['title', 'medusaId', 'handle'],
|
listSearchableFields: ['title', 'medusaId', 'handle'],
|
||||||
pagination: {
|
pagination: {
|
||||||
defaultLimit: 48,
|
defaultLimit: 25,
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
edit: {
|
edit: {
|
||||||
|
|
@ -57,6 +57,10 @@ export const Products: CollectionConfig = {
|
||||||
admin: {
|
admin: {
|
||||||
description: '商品缩略图 URL(从 Medusa 同步)',
|
description: '商品缩略图 URL(从 Medusa 同步)',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
|
components: {
|
||||||
|
Cell: '/components/products/ThumbnailCell#ThumbnailCell',
|
||||||
|
Field: '/components/products/ThumbnailAndStatusField#ThumbnailAndStatusField',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use client'
|
||||||
|
import type { SelectFieldClientComponent } from 'payload'
|
||||||
|
|
||||||
|
// 隐藏字段(因为在ThumbnailAndStatusField中已经显示和编辑)
|
||||||
|
export const HiddenField: SelectFieldClientComponent = () => {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
'use client'
|
||||||
|
import { useFormFields, useField } from '@payloadcms/ui'
|
||||||
|
import type { TextFieldClientComponent } from 'payload'
|
||||||
|
|
||||||
|
// 并排显示缩略图和状态(带状态选择器)
|
||||||
|
export const ThumbnailAndStatusField: TextFieldClientComponent = ({ path }) => {
|
||||||
|
// 获取thumbnail值
|
||||||
|
const fields = useFormFields(([fields]) => fields)
|
||||||
|
const thumbnail = fields.thumbnail?.value
|
||||||
|
|
||||||
|
// 获取status字段的值和setter
|
||||||
|
const { value: status, setValue: setStatus } = useField({ path: 'status' })
|
||||||
|
|
||||||
|
const isImage = typeof thumbnail === 'string' && thumbnail.match(/^https?:\/\/.+/)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<label style={{ display: 'block', marginBottom: 8, fontWeight: 500 }}>商品缩略图和状态</label>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 16 }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
borderRadius: 8,
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isImage ? (
|
||||||
|
<img
|
||||||
|
src={thumbnail}
|
||||||
|
alt="商品缩略图"
|
||||||
|
style={{ maxWidth: '100%', maxHeight: '100%', borderRadius: 6 }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span style={{ color: '#bbb' }}>无图片</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div style={{ flex: 1 }}>
|
||||||
|
<label style={{ display: 'block', marginBottom: 4, fontSize: 14 }}>状态</label>
|
||||||
|
<select
|
||||||
|
value={(status as string) || 'draft'}
|
||||||
|
onChange={(e) => setStatus(e.target.value)}
|
||||||
|
style={{
|
||||||
|
padding: '8px 12px',
|
||||||
|
borderRadius: 4,
|
||||||
|
fontSize: 14,
|
||||||
|
minWidth: 120,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="draft">草稿</option>
|
||||||
|
<option value="published">已发布</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
'use client'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
export const ThumbnailCell = (props: any) => {
|
||||||
|
console.log('=== ThumbnailCell All Props ===', props)
|
||||||
|
console.log('Props keys:', Object.keys(props))
|
||||||
|
|
||||||
|
// 尝试从不同的 props 路径获取值
|
||||||
|
const value = props.value || props.cellData || props.data
|
||||||
|
const rowData = props.rowData || props.row
|
||||||
|
|
||||||
|
console.log('Extracted value:', value)
|
||||||
|
console.log('Extracted rowData:', rowData)
|
||||||
|
|
||||||
|
const isImage = typeof value === 'string' && value.match(/^https?:\/\/.+/)
|
||||||
|
const editUrl = `/admin/collections/products/${rowData?.id || ''}`
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={editUrl}
|
||||||
|
style={{ display: 'block', width: '100%', height: '200px', textDecoration: 'none' }}
|
||||||
|
>
|
||||||
|
{isImage ? (
|
||||||
|
<img src={value} alt="商品缩略图" className="thumbnail-img" />
|
||||||
|
) : (
|
||||||
|
<div className="no-image">{value || '无图片'}</div>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -27,11 +27,14 @@
|
||||||
transition: all 0.2s ease-in-out !important;
|
transition: all 0.2s ease-in-out !important;
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
min-height: 320px;
|
min-height: 320px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: translateY(-4px);
|
transform: translateY(-4px);
|
||||||
box-shadow: 0 4px 12px -2px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 4px 12px -2px rgba(0, 0, 0, 0.1);
|
||||||
border-color: var(--theme-elevation-300) !important;
|
border-color: var(--theme-elevation-300) !important;
|
||||||
|
background: var(--theme-elevation-100) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
|
|
@ -59,8 +62,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Thumbnail (First content column)
|
// 2. Thumbnail (First content column)
|
||||||
// We depend on 'thumbnail' being the first custom column in Products.ts
|
|
||||||
// Note: td:nth-child(2) because checkbox is #1
|
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
height: 200px !important;
|
height: 200px !important;
|
||||||
|
|
@ -69,27 +70,23 @@
|
||||||
background: var(--theme-elevation-100) !important;
|
background: var(--theme-elevation-100) !important;
|
||||||
order: -1 !important; // Force to top
|
order: -1 !important; // Force to top
|
||||||
flex-grow: 0 !important;
|
flex-grow: 0 !important;
|
||||||
|
position: relative;
|
||||||
// Support for Payload's file cell or specific image structures
|
|
||||||
.file-cell, .thumbnail {
|
img {
|
||||||
width: 100%;
|
width: 100% !important;
|
||||||
height: 100%;
|
height: 100% !important;
|
||||||
|
object-fit: cover !important;
|
||||||
img {
|
display: block !important;
|
||||||
width: 100%;
|
background: var(--theme-elevation-100);
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.no-image {
|
||||||
// Fallback purely text content in that cell
|
|
||||||
span {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: var(--theme-elevation-400);
|
color: var(--theme-elevation-400);
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue