富文本模式

This commit is contained in:
龟男日记\www 2026-02-09 04:27:32 +08:00
parent 4f14ac59f3
commit b4991fcefd
4 changed files with 250 additions and 56 deletions

View File

@ -1,5 +1,29 @@
import { ThumbnailCell as ThumbnailCell_a0b2acb813359aec894b6644d7c3bfd2 } from '../../../components/products/ThumbnailCell'
import { ThumbnailAndStatusField as ThumbnailAndStatusField_8fa95ec6265982d11b99fbeb81e24c1c } from '../../../components/products/ThumbnailAndStatusField'
import { ThumbnailField as ThumbnailField_ba44ab32cac4d742a03a48fb6960602e } from '../../../components/products/ThumbnailField'
import { RscEntryLexicalCell as RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc'
import { RscEntryLexicalField as RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc'
import { LexicalDiffComponent as LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc'
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { InlineToolbarFeatureClient as InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { FixedToolbarFeatureClient as FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { UploadFeatureClient as UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { BlockquoteFeatureClient as BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { RelationshipFeatureClient as RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { LinkFeatureClient as LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { ChecklistFeatureClient as ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { OrderedListFeatureClient as OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { UnorderedListFeatureClient as UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { IndentFeatureClient as IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { AlignFeatureClient as AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { HeadingFeatureClient as HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { ParagraphFeatureClient as ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { InlineCodeFeatureClient as InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { SuperscriptFeatureClient as SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { SubscriptFeatureClient as SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { SyncMedusaButton as SyncMedusaButton_8c90663551920f0510ea531726668adc } from '../../../components/products/SyncMedusaButton'
import { default as default_3fd1353246fc8a459244c8dc11f58470 } from '../../../components/products/ProductGridStyler'
import { ForceSyncButton as ForceSyncButton_86f9d5df4f20495427521354d06db618 } from '../../../components/products/ForceSyncButton'
@ -8,7 +32,31 @@ import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } f
export const importMap = {
"/components/products/ThumbnailCell#ThumbnailCell": ThumbnailCell_a0b2acb813359aec894b6644d7c3bfd2,
"/components/products/ThumbnailAndStatusField#ThumbnailAndStatusField": ThumbnailAndStatusField_8fa95ec6265982d11b99fbeb81e24c1c,
"/components/products/ThumbnailField#ThumbnailField": ThumbnailField_ba44ab32cac4d742a03a48fb6960602e,
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
"@payloadcms/richtext-lexical/rsc#LexicalDiffComponent": LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e,
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#UploadFeatureClient": UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#BlockquoteFeatureClient": BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#RelationshipFeatureClient": RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ChecklistFeatureClient": ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#OrderedListFeatureClient": OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#UnorderedListFeatureClient": UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#IndentFeatureClient": IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#AlignFeatureClient": AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#InlineCodeFeatureClient": InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#SuperscriptFeatureClient": SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#SubscriptFeatureClient": SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#StrikethroughFeatureClient": StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"/components/products/SyncMedusaButton#SyncMedusaButton": SyncMedusaButton_8c90663551920f0510ea531726668adc,
"/components/products/ProductGridStyler#default": default_3fd1353246fc8a459244c8dc11f58470,
"/components/products/ForceSyncButton#ForceSyncButton": ForceSyncButton_86f9d5df4f20495427521354d06db618,

View File

@ -1,4 +1,25 @@
import type { CollectionConfig } from 'payload'
import {
AlignFeature,
BlocksFeature,
BoldFeature,
ChecklistFeature,
HeadingFeature,
IndentFeature,
InlineCodeFeature,
ItalicFeature,
lexicalEditor,
LinkFeature,
OrderedListFeature,
ParagraphFeature,
RelationshipFeature,
UnorderedListFeature,
UploadFeature,
FixedToolbarFeature,
InlineToolbarFeature,
HorizontalRuleFeature,
BlockquoteFeature,
} from '@payloadcms/richtext-lexical'
export const Products: CollectionConfig = {
slug: 'products',
@ -23,6 +44,9 @@ export const Products: CollectionConfig = {
access: {
read: () => true, // 公开可读
},
fields: [
{
type: 'row',
fields: [
{
name: 'medusaId',
@ -33,34 +57,7 @@ export const Products: CollectionConfig = {
admin: {
description: 'Medusa 商品 ID',
readOnly: true,
},
},
{
name: 'title',
type: 'text',
required: true,
admin: {
description: '商品标题(从 Medusa 同步)',
},
},
{
name: 'handle',
type: 'text',
admin: {
description: '商品 URL slug从 Medusa 同步)',
readOnly: true,
},
},
{
name: 'thumbnail',
type: 'text',
admin: {
description: '商品缩略图 URL从 Medusa 同步)',
readOnly: true,
components: {
Cell: '/components/products/ThumbnailCell#ThumbnailCell',
Field: '/components/products/ThumbnailAndStatusField#ThumbnailAndStatusField',
},
width: '80%',
},
},
{
@ -80,6 +77,91 @@ export const Products: CollectionConfig = {
],
admin: {
description: '商品详情状态',
width: '20%',
},
},
],
},
{
type: 'row',
fields: [
{
name: 'title',
type: 'text',
required: true,
admin: {
description: '商品标题(从 Medusa 同步)',
readOnly: true,
width: '80%',
},
},
{
name: 'thumbnail',
type: 'text',
admin: {
description: '商品封面 URL从 Medusa 同步)',
readOnly: true,
width: '20%',
components: {
Cell: '/components/products/ThumbnailCell#ThumbnailCell',
Field: '/components/products/ThumbnailField#ThumbnailField',
},
},
},
],
},
{
name: 'content',
type: 'richText',
admin: {
description: '商品详细内容',
},
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
HeadingFeature({ enabledHeadingSizes: ['h1', 'h2', 'h3', 'h4'] }),
LinkFeature({
enabledCollections: ['products'],
fields: ({ defaultFields }) => [
...defaultFields,
{
name: 'rel',
label: 'Rel Attribute',
type: 'select',
hasMany: true,
options: ['noopener', 'noreferrer', 'nofollow'],
admin: {
description: 'The rel attribute defines the relationship between a linked resource and the current document. This is a custom link field.',
},
},
],
}),
UploadFeature({
collections: {
media: {
fields: [
{
name: 'caption',
type: 'richText',
label: '图片说明',
editor: lexicalEditor(),
},
],
},
},
}),
FixedToolbarFeature(),
InlineToolbarFeature(),
HorizontalRuleFeature(),
],
}),
},
{
name: 'handle',
type: 'text',
admin: {
description: '商品 URL slug从 Medusa 同步)',
readOnly: true,
},
},
{

View File

@ -0,0 +1,45 @@
'use client'
import { useFormFields } from '@payloadcms/ui'
import type { TextFieldClientComponent } from 'payload'
// 只显示缩略图封面
export const ThumbnailField: TextFieldClientComponent = ({ path }) => {
const fields = useFormFields(([fields]) => fields)
const thumbnail = fields.thumbnail?.value
const isImage = typeof thumbnail === 'string' && thumbnail.match(/^https?:\/\/.+/)
return (
<div>
<label style={{ display: 'block', marginBottom: 8, fontWeight: 500 }}></label>
<div
style={{
width: '100%',
maxWidth: 300,
height: 200,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: '1px solid #eee',
borderRadius: 8,
background: '#fafbfc',
overflow: 'hidden',
}}
>
{isImage ? (
<img
src={thumbnail}
alt="商品封面"
style={{
width: '100%',
height: '100%',
objectFit: 'contain',
}}
/>
) : (
<span style={{ color: '#bbb' }}></span>
)}
</div>
</div>
)
}

View File

@ -172,22 +172,40 @@ export interface Product {
* Medusa ID
*/
medusaId: string;
/**
*
*/
status: 'draft' | 'published';
/**
* Medusa
*/
title: string;
/**
* URL slug Medusa
*/
handle?: string | null;
/**
* URL Medusa
* URL Medusa
*/
thumbnail?: string | null;
/**
*
*
*/
status: 'draft' | 'published';
content?: {
root: {
type: string;
children: {
type: any;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
} | null;
/**
* URL slug Medusa
*/
handle?: string | null;
/**
*
*/
@ -323,10 +341,11 @@ export interface MediaSelect<T extends boolean = true> {
*/
export interface ProductsSelect<T extends boolean = true> {
medusaId?: T;
title?: T;
handle?: T;
thumbnail?: T;
status?: T;
title?: T;
thumbnail?: T;
content?: T;
handle?: T;
relatedProducts?: T;
lastSyncedAt?: T;
updatedAt?: T;