diff --git a/src/endpoints/homepage.ts b/src/endpoints/homepage.ts new file mode 100644 index 0000000..4b31d4c --- /dev/null +++ b/src/endpoints/homepage.ts @@ -0,0 +1,72 @@ +import type { Endpoint } from 'payload' + +export const homepageDataEndpoint: Endpoint = { + path: '/homepage-data', + method: 'get', + handler: async (req) => { + try { + const payload = req.payload + + // 获取首页公告(已发布且在首页显示) + 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', + }) + + // 获取产品推荐 + const productRecommendations = await payload.findGlobal({ + slug: 'product-recommendations', + }) + + // 构建响应数据 + 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 || [], + }, + } + + return Response.json(response, { status: 200 }) + } catch (error: any) { + req.payload.logger.error('Error fetching homepage data:', error) + return Response.json( + { + error: 'Failed to fetch homepage data', + message: error.message, + }, + { status: 500 } + ) + } + }, +} diff --git a/src/globals/SiteAccess.ts b/src/globals/SiteAccess.ts new file mode 100644 index 0000000..25dd81c --- /dev/null +++ b/src/globals/SiteAccess.ts @@ -0,0 +1,79 @@ +import type { GlobalConfig } from 'payload' + +export const SiteAccess: GlobalConfig = { + slug: 'site-access', + label: { + en: 'Site Access Control', + zh: '站点访问控制', + }, + access: { + read: () => true, // 公开可读,前端需要检查访问状态 + update: ({ req: { user } }) => { + // 只有 admin 可以更新 + if (!user) return false + return user.roles?.includes('admin') || false + }, + }, + admin: { + group: { + en: 'System', + zh: '系统', + }, + description: { + en: 'Control site accessibility and maintenance mode', + zh: '控制站点可访问性和维护模式', + }, + }, + fields: [ + { + name: 'isAccessible', + type: 'checkbox', + label: { + en: 'Site Accessible', + zh: '站点可访问', + }, + defaultValue: true, + required: true, + admin: { + description: { + en: 'Toggle to enable/disable public access to the site', + zh: '切换以启用/禁用站点的公开访问', + }, + }, + }, + { + name: 'maintenanceMessage', + type: 'textarea', + label: { + en: 'Maintenance Message', + zh: '维护提示消息', + }, + defaultValue: 'The site is currently under maintenance. Please check back later.', + required: true, + admin: { + description: { + en: 'Message to display when site is not accessible', + zh: '站点不可访问时显示的消息', + }, + rows: 4, + }, + }, + { + name: 'estimatedRestoreTime', + type: 'date', + label: { + en: 'Estimated Restore Time', + zh: '预计恢复时间', + }, + admin: { + description: { + en: 'Optional: When the site is expected to be back online', + zh: '可选:预计站点恢复在线的时间', + }, + date: { + displayFormat: 'yyyy-MM-dd HH:mm', + }, + }, + }, + ], +} diff --git a/src/payload-types.ts b/src/payload-types.ts index b2c4c1f..d7ac0ef 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -104,12 +104,14 @@ export interface Config { 'logs-manager': LogsManager; 'hero-slider': HeroSlider; 'product-recommendations': ProductRecommendation; + 'site-access': SiteAccess; }; globalsSelect: { 'admin-settings': AdminSettingsSelect | AdminSettingsSelect; 'logs-manager': LogsManagerSelect | LogsManagerSelect; 'hero-slider': HeroSliderSelect | HeroSliderSelect; 'product-recommendations': ProductRecommendationsSelect | ProductRecommendationsSelect; + 'site-access': SiteAccessSelect | SiteAccessSelect; }; locale: null; user: User; @@ -1042,6 +1044,29 @@ export interface ProductRecommendation { updatedAt?: string | null; createdAt?: string | null; } +/** + * Control site accessibility and maintenance mode + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "site-access". + */ +export interface SiteAccess { + id: number; + /** + * Toggle to enable/disable public access to the site + */ + isAccessible: boolean; + /** + * Message to display when site is not accessible + */ + maintenanceMessage: string; + /** + * Optional: When the site is expected to be back online + */ + estimatedRestoreTime?: string | null; + updatedAt?: string | null; + createdAt?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "admin-settings_select". @@ -1103,6 +1128,18 @@ export interface ProductRecommendationsSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "site-access_select". + */ +export interface SiteAccessSelect { + isAccessible?: T; + maintenanceMessage?: T; + estimatedRestoreTime?: T; + updatedAt?: T; + createdAt?: T; + globalType?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "TaskSchedulePublish". diff --git a/src/payload.config.ts b/src/payload.config.ts index 8376cf7..3d8d3c0 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -16,9 +16,11 @@ import { AdminSettings } from './globals/AdminSettings' import { LogsManager } from './globals/LogsManager' import { HeroSlider } from './globals/HeroSlider' import { ProductRecommendations } from './globals/ProductRecommendations' +import { SiteAccess } from './globals/SiteAccess' import { s3Storage } from '@payloadcms/storage-s3' import { en } from '@payloadcms/translations/languages/en' import { zh } from '@payloadcms/translations/languages/zh' +import { homepageDataEndpoint } from './endpoints/homepage' // 导入自定义翻译 import enProducts from './translations/en/products.json' @@ -48,7 +50,8 @@ export default buildConfig({ fallbackLanguage: 'zh', }, collections: [Users, Media, Products, PreorderProducts, Announcements, Articles, Logs], - globals: [AdminSettings, LogsManager, HeroSlider, ProductRecommendations], + globals: [AdminSettings, LogsManager, HeroSlider, ProductRecommendations, SiteAccess], + endpoints: [homepageDataEndpoint], editor: lexicalEditor(), secret: process.env.PAYLOAD_SECRET || '', typescript: {