229 lines
5.2 KiB
TypeScript
229 lines
5.2 KiB
TypeScript
import type { CollectionConfig } from 'payload'
|
|
import { logAfterChange, logAfterDelete } from '../hooks/logAction'
|
|
import { cacheAfterChange, cacheAfterDelete } from '../hooks/cacheInvalidation'
|
|
import {
|
|
BlocksFeature,
|
|
BoldFeature,
|
|
HeadingFeature,
|
|
InlineCodeFeature,
|
|
ItalicFeature,
|
|
lexicalEditor,
|
|
LinkFeature,
|
|
OrderedListFeature,
|
|
ParagraphFeature,
|
|
UnorderedListFeature,
|
|
FixedToolbarFeature,
|
|
InlineToolbarFeature,
|
|
HorizontalRuleFeature,
|
|
BlockquoteFeature,
|
|
AlignFeature,
|
|
} from '@payloadcms/richtext-lexical'
|
|
|
|
export const Announcements: CollectionConfig = {
|
|
slug: 'announcements',
|
|
admin: {
|
|
useAsTitle: 'title',
|
|
defaultColumns: ['title', 'type', 'status', 'publishedAt', 'updatedAt'],
|
|
description: '管理系统公告和通知',
|
|
pagination: {
|
|
defaultLimit: 25,
|
|
},
|
|
},
|
|
access: {
|
|
read: ({ req: { user } }) => {
|
|
// 公开访问已发布的公告
|
|
if (!user) {
|
|
return {
|
|
status: { equals: 'published' },
|
|
}
|
|
}
|
|
// 认证用户可以查看所有
|
|
return true
|
|
},
|
|
create: ({ req: { user } }) => {
|
|
// 所有已认证用户都可以创建
|
|
return Boolean(user)
|
|
},
|
|
update: ({ req: { user } }) => {
|
|
// 所有已认证用户都可以更新
|
|
return Boolean(user)
|
|
},
|
|
delete: ({ req: { user } }) => {
|
|
// 只有 admin 可以删除
|
|
if (!user) return false
|
|
return user.roles?.includes('admin') || false
|
|
},
|
|
},
|
|
fields: [
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
admin: {
|
|
description: '公告标题',
|
|
width: '70%',
|
|
},
|
|
},
|
|
{
|
|
name: 'type',
|
|
type: 'select',
|
|
required: true,
|
|
defaultValue: 'info',
|
|
options: [
|
|
{
|
|
label: '信息',
|
|
value: 'info',
|
|
},
|
|
{
|
|
label: '警告',
|
|
value: 'warning',
|
|
},
|
|
{
|
|
label: '重要',
|
|
value: 'important',
|
|
},
|
|
{
|
|
label: '紧急',
|
|
value: 'urgent',
|
|
},
|
|
],
|
|
admin: {
|
|
description: '公告类型',
|
|
width: '30%',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'status',
|
|
type: 'select',
|
|
required: true,
|
|
defaultValue: 'draft',
|
|
options: [
|
|
{
|
|
label: '草稿',
|
|
value: 'draft',
|
|
},
|
|
{
|
|
label: '已发布',
|
|
value: 'published',
|
|
},
|
|
{
|
|
label: '已归档',
|
|
value: 'archived',
|
|
},
|
|
],
|
|
admin: {
|
|
description: '发布状态',
|
|
width: '50%',
|
|
},
|
|
},
|
|
{
|
|
name: 'priority',
|
|
type: 'number',
|
|
defaultValue: 0,
|
|
admin: {
|
|
description: '优先级(数字越大越靠前)',
|
|
width: '50%',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'summary',
|
|
type: 'textarea',
|
|
admin: {
|
|
description: '公告摘要(显示在列表页)',
|
|
},
|
|
},
|
|
{
|
|
name: 'content',
|
|
type: 'richText',
|
|
required: true,
|
|
admin: {
|
|
description: '公告详细内容',
|
|
},
|
|
editor: lexicalEditor({
|
|
features: ({ defaultFeatures }) => [
|
|
...defaultFeatures,
|
|
HeadingFeature({ enabledHeadingSizes: ['h1', 'h2', 'h3', 'h4'] }),
|
|
BoldFeature(),
|
|
ItalicFeature(),
|
|
LinkFeature({}),
|
|
OrderedListFeature(),
|
|
UnorderedListFeature(),
|
|
BlockquoteFeature(),
|
|
AlignFeature(),
|
|
InlineCodeFeature(),
|
|
FixedToolbarFeature(),
|
|
InlineToolbarFeature(),
|
|
HorizontalRuleFeature(),
|
|
],
|
|
}),
|
|
},
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'publishedAt',
|
|
type: 'date',
|
|
admin: {
|
|
description: '发布时间',
|
|
width: '50%',
|
|
date: {
|
|
displayFormat: 'yyyy-MM-dd HH:mm',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'expiresAt',
|
|
type: 'date',
|
|
admin: {
|
|
description: '过期时间(可选)',
|
|
width: '50%',
|
|
date: {
|
|
displayFormat: 'yyyy-MM-dd HH:mm',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'showOnHomepage',
|
|
type: 'checkbox',
|
|
defaultValue: false,
|
|
admin: {
|
|
description: '在首页显示此公告',
|
|
},
|
|
},
|
|
{
|
|
name: 'author',
|
|
type: 'relationship',
|
|
relationTo: 'users',
|
|
admin: {
|
|
description: '发布者',
|
|
},
|
|
},
|
|
],
|
|
timestamps: true,
|
|
hooks: {
|
|
beforeChange: [
|
|
({ data, operation }) => {
|
|
// 自动设置发布时间
|
|
if (operation === 'create' && data.status === 'published' && !data.publishedAt) {
|
|
data.publishedAt = new Date()
|
|
}
|
|
return data
|
|
},
|
|
],
|
|
afterChange: [logAfterChange],
|
|
afterDelete: [logAfterDelete],
|
|
},
|
|
}
|