管理网站状态

This commit is contained in:
龟男日记\www 2026-02-17 23:57:30 +08:00
parent ee3ec61548
commit f5621a3aa1
4 changed files with 192 additions and 1 deletions

72
src/endpoints/homepage.ts Normal file
View File

@ -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 }
)
}
},
}

79
src/globals/SiteAccess.ts Normal file
View File

@ -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',
},
},
},
],
}

View File

@ -104,12 +104,14 @@ export interface Config {
'logs-manager': LogsManager;
'hero-slider': HeroSlider;
'product-recommendations': ProductRecommendation;
'site-access': SiteAccess;
};
globalsSelect: {
'admin-settings': AdminSettingsSelect<false> | AdminSettingsSelect<true>;
'logs-manager': LogsManagerSelect<false> | LogsManagerSelect<true>;
'hero-slider': HeroSliderSelect<false> | HeroSliderSelect<true>;
'product-recommendations': ProductRecommendationsSelect<false> | ProductRecommendationsSelect<true>;
'site-access': SiteAccessSelect<false> | SiteAccessSelect<true>;
};
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<T extends boolean = true> {
createdAt?: T;
globalType?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "site-access_select".
*/
export interface SiteAccessSelect<T extends boolean = true> {
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".

View File

@ -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: {