206 lines
12 KiB
TypeScript
206 lines
12 KiB
TypeScript
import { z } from 'zod'
|
||
|
||
const localOrHttpUrl = z.string().max(300).refine(value => !value || value.startsWith('/') || /^https?:\/\//i.test(value), '请输入站内路径或以 http(s) 开头的完整链接')
|
||
const httpUrl = z.string().max(300).refine(value => !value || /^https?:\/\//i.test(value), '请输入以 http(s) 开头的完整链接')
|
||
|
||
const metricSchema = z.object({
|
||
value: z.string().max(20),
|
||
label: z.string().max(30),
|
||
description: z.string().max(80),
|
||
})
|
||
|
||
const productSchema = z.object({
|
||
slug: z.string().regex(/^[a-z0-9-]+$/).max(80),
|
||
title: z.string().max(60),
|
||
subtitle: z.string().max(80),
|
||
type: z.enum(['course', 'service', 'tool']).default('course'),
|
||
summary: z.string().max(300).default(''),
|
||
content: z.string().max(30000).default(''),
|
||
image: localOrHttpUrl,
|
||
href: localOrHttpUrl,
|
||
status: z.enum(['draft', 'published', 'offline']).default('draft'),
|
||
})
|
||
|
||
const articleSchema = z.object({
|
||
slug: z.string().regex(/^[a-z0-9-]+$/).max(100),
|
||
type: z.enum(['news', 'statement', 'media']),
|
||
title: z.string().min(1).max(120),
|
||
summary: z.string().max(300),
|
||
content: z.string().max(50000),
|
||
cover: localOrHttpUrl,
|
||
publishedAt: z.string().max(40),
|
||
status: z.enum(['draft', 'published', 'offline']),
|
||
statementNo: z.string().max(60).default(''),
|
||
sourceName: z.string().max(80).default(''),
|
||
sourceUrl: httpUrl.default(''),
|
||
})
|
||
|
||
const teamMemberSchema = z.object({
|
||
slug: z.string().regex(/^[a-z0-9-]+$/).max(80),
|
||
name: z.string().min(1).max(40),
|
||
role: z.string().max(80),
|
||
summary: z.string().max(300),
|
||
avatar: localOrHttpUrl,
|
||
specialties: z.array(z.string().max(30)).max(8),
|
||
status: z.enum(['draft', 'published', 'offline']),
|
||
})
|
||
|
||
const channelSchema = z.object({
|
||
name: z.string().min(1).max(40),
|
||
account: z.string().max(80),
|
||
url: httpUrl,
|
||
qrCode: localOrHttpUrl,
|
||
})
|
||
|
||
const siteDocumentBaseSchema = z.object({
|
||
brand: z.object({
|
||
name: z.string().min(1).max(40),
|
||
englishName: z.string().max(80),
|
||
logo: localOrHttpUrl,
|
||
slogan: z.string().min(1).max(40),
|
||
subSlogan: z.string().max(80),
|
||
companyName: z.string().max(100).default('待后台配置'),
|
||
creditCode: z.string().max(40).default('待后台配置'),
|
||
introduction: z.string().max(500).default(''),
|
||
copyright: z.string().max(100).default('© 2026 慧遇书院 版权所有'),
|
||
icp: z.string().max(80).default('备案信息待配置'),
|
||
policeRecord: z.string().max(80).default(''),
|
||
}),
|
||
hero: z.object({
|
||
titleLine1: z.string().min(1).max(20),
|
||
titleLine2: z.string().min(1).max(20),
|
||
subtitle: z.string().max(80),
|
||
cta: z.string().max(20),
|
||
backgroundImage: localOrHttpUrl,
|
||
}),
|
||
about: z.object({
|
||
title: z.string().max(40),
|
||
summary: z.string().max(300),
|
||
metrics: z.array(metricSchema).min(1).max(4),
|
||
}),
|
||
teacher: z.object({
|
||
name: z.string().max(30),
|
||
title: z.string().max(80),
|
||
summary: z.string().max(400),
|
||
portrait: localOrHttpUrl,
|
||
tags: z.array(z.string().max(20)).max(6),
|
||
fullBio: z.string().max(8000).default(''),
|
||
experiences: z.array(z.object({ year: z.string().max(20), title: z.string().max(100), description: z.string().max(300) })).max(20).default([]),
|
||
achievements: z.array(z.string().max(120)).max(12).default([]),
|
||
externalLinks: z.array(z.object({ label: z.string().max(40), url: httpUrl })).max(10).default([]),
|
||
}),
|
||
products: z.array(productSchema).max(8),
|
||
articles: z.array(articleSchema).max(60).default([]),
|
||
team: z.array(teamMemberSchema).max(30).default([]),
|
||
channels: z.array(channelSchema).max(12).default([]),
|
||
contact: z.object({
|
||
phone: z.string().max(30),
|
||
email: z.string().max(100),
|
||
address: z.string().max(160),
|
||
}),
|
||
seo: z.object({
|
||
title: z.string().max(70),
|
||
description: z.string().max(180),
|
||
}),
|
||
legal: z.object({
|
||
privacyTitle: z.string().max(80).default('隐私政策'),
|
||
privacyContent: z.string().max(12000).default(''),
|
||
termsTitle: z.string().max(80).default('服务条款'),
|
||
termsContent: z.string().max(12000).default(''),
|
||
}).default({ privacyTitle: '隐私政策', privacyContent: '', termsTitle: '服务条款', termsContent: '' }),
|
||
})
|
||
|
||
export const siteDocumentSchema = siteDocumentBaseSchema.superRefine((document, context) => {
|
||
const ensureUnique = (items: Array<{ slug: string }>, field: 'products' | 'articles' | 'team') => {
|
||
const seen = new Set<string>()
|
||
items.forEach((item, index) => {
|
||
if (seen.has(item.slug)) context.addIssue({ code: 'custom', path: [field, index, 'slug'], message: `英文标识“${item.slug}”重复` })
|
||
seen.add(item.slug)
|
||
})
|
||
}
|
||
ensureUnique(document.products, 'products')
|
||
ensureUnique(document.articles, 'articles')
|
||
ensureUnique(document.team, 'team')
|
||
})
|
||
|
||
export type SiteDocument = z.infer<typeof siteDocumentSchema>
|
||
|
||
export const defaultSiteDocument: SiteDocument = {
|
||
brand: {
|
||
name: '慧遇书院',
|
||
englishName: 'HUIYU ACADEMY',
|
||
logo: '/images/brand-mark-v2.png',
|
||
slogan: '身心疗愈 · 科技赋能',
|
||
subSlogan: '用科技与专业,陪伴每一次心灵的成长',
|
||
companyName: '慧遇书院',
|
||
creditCode: '待后台配置',
|
||
introduction: '慧遇书院专注于家庭教育、心理成长与长期成长实践。当前公司主体信息为演示内容,正式上线前需完成核验与替换。',
|
||
copyright: '© 2026 慧遇书院 版权所有',
|
||
icp: 'ICP备案信息待配置',
|
||
policeRecord: '',
|
||
},
|
||
hero: {
|
||
titleLine1: '身心疗愈',
|
||
titleLine2: '科技赋能',
|
||
subtitle: '用科技与专业,陪伴每一次心灵的成长',
|
||
cta: '了解慧遇书院',
|
||
backgroundImage: '/images/hero-bg-v3.webp',
|
||
},
|
||
about: {
|
||
title: '关于慧遇书院',
|
||
summary: '慧遇书院专注于身心疗愈与成长领域,以专业内容与长期实践陪伴心灵成长。',
|
||
metrics: [
|
||
{ value: '身心', label: '专注领域', description: '疗愈与成长' },
|
||
{ value: '10万+', label: '陪伴学员', description: '持续连接与支持' },
|
||
{ value: '2018', label: '成立时间', description: '长期主义实践' },
|
||
],
|
||
},
|
||
teacher: {
|
||
name: '卢慧老师',
|
||
title: '家庭教育与心理学研究者|慧遇书院创始人',
|
||
summary: '长期从事家庭教育与心理成长实践,探索东方智慧与现代心理学在家庭场景中的融合应用。',
|
||
portrait: '/images/lu-hui-portrait.jpg',
|
||
tags: ['家庭教育', '心理成长', '关系支持', '东方智慧'],
|
||
fullBio: '卢慧老师长期从事家庭教育与心理成长实践,关注个体在家庭关系、亲密关系与自我成长中的真实需要。\n\n她持续探索东方智慧与现代心理学在日常生活中的融合应用,并通过课程、陪伴与内容分享,帮助更多人建立稳定、清晰、可持续的成长路径。\n\n以上为官网演示介绍,正式发布前应以经本人确认的资料为准。',
|
||
experiences: [
|
||
{ year: '2024', title: '持续完善身心整合实践体系', description: '结合真实家庭场景,形成结构化的陪伴与成长方法。' },
|
||
{ year: '2021', title: '出版与内容传播', description: '围绕家庭教育、关系与自我成长开展内容分享。' },
|
||
{ year: '2018', title: '创立慧遇书院', description: '持续开展家庭教育与心理成长实践。' },
|
||
],
|
||
achievements: ['长期开展家庭教育与心理成长实践', '持续研发结构化陪伴与成长课程', '推动东方智慧与现代心理学融合应用'],
|
||
externalLinks: [{ label: '百度百科', url: 'https://baike.baidu.com/item/%E5%8D%A2%E6%85%A7/65761247' }],
|
||
},
|
||
products: [
|
||
{ slug: 'family-relationship', title: '家庭关系训练营', subtitle: '关注关系与代际议题', type: 'course', summary: '从真实家庭场景出发,理解关系互动背后的需要与模式。', content: '课程内容为演示信息,正式上线前需由运营人员在后台核验与替换。\n\n课程将围绕觉察、沟通和关系实践展开,帮助参与者把理解转化为日常行动。', image: '/images/hero-bg-v3.webp', href: '/products/family-relationship', status: 'published' },
|
||
{ slug: 'human-wisdom', title: '人本智慧学', subtitle: '从觉知走向实践', type: 'course', summary: '以长期主义的方式理解自我、关系与成长。', content: '本页面为产品结构演示,具体课程体系、适用人群和服务安排待后台补充。', image: '/images/hero-bg-v3.webp', href: '/products/human-wisdom', status: 'published' },
|
||
{ slug: 'companion-assistant', title: '智能陪伴助手', subtitle: '科技赋能日常练习', type: 'tool', summary: '让日常觉察和练习更清晰、更容易坚持。', content: '该产品当前处于演示阶段,正式能力与使用入口以后台发布信息为准。', image: '/images/hero-bg-v3.webp', href: '/products/companion-assistant', status: 'published' },
|
||
],
|
||
articles: [
|
||
{ slug: 'official-information-notice', type: 'statement', title: '慧遇书院官方信息说明(演示)', summary: '用于说明官网、官方账号与对外信息的统一发布原则。', content: '本页面为官方声明结构演示。正式上线前,需要由运营人员替换为经审核的真实声明内容。', cover: '/images/hero-bg-v3.webp', publishedAt: '2026-08-10', status: 'published', statementNo: 'HUIYU-DEMO-001', sourceName: '', sourceUrl: '' },
|
||
{ slug: 'website-phase-one', type: 'news', title: '慧遇书院官网一期建设启动', summary: '官网将成为品牌、人物、课程与官方信息的统一可信入口。', content: '慧遇书院官网一期建设已经启动。首阶段将完成品牌信息、卢慧老师资料、课程产品、官方声明与团队介绍的结构化呈现。\n\n当前内容包含演示数据,生产发布前将通过后台统一核验。', cover: '/images/hero-bg-v3.webp', publishedAt: '2026-08-10', status: 'published', statementNo: '', sourceName: '', sourceUrl: '' },
|
||
],
|
||
team: [
|
||
{ slug: 'course-consultant', name: '课程顾问', role: '成长路径与课程支持', summary: '为来访者提供清晰、克制的课程信息说明。演示成员,待后台替换。', avatar: '/images/lu-hui-portrait.jpg', specialties: ['课程咨询', '成长支持'], status: 'published' },
|
||
{ slug: 'content-editor', name: '内容老师', role: '品牌内容与知识整理', summary: '负责把专业内容整理成可信、易理解的表达。演示成员,待后台替换。', avatar: '/images/lu-hui-portrait.jpg', specialties: ['内容整理', '知识传播'], status: 'published' },
|
||
],
|
||
channels: [
|
||
{ name: '微信公众号', account: '账号待后台配置', url: '', qrCode: '' },
|
||
{ name: '视频号', account: '账号待后台配置', url: '', qrCode: '' },
|
||
],
|
||
contact: {
|
||
phone: '待后台配置',
|
||
email: '待后台配置',
|
||
address: '待后台配置',
|
||
},
|
||
seo: {
|
||
title: '慧遇书院|身心疗愈 专业陪伴',
|
||
description: '慧遇书院官方网站,关注家庭教育、心理成长与长期成长实践。',
|
||
},
|
||
legal: {
|
||
privacyTitle: '隐私政策',
|
||
privacyContent: '更新日期:2026年8月10日\n\n本网站一期不提供用户注册、支付或在线咨询信息收集功能。访问过程中产生的必要技术日志仅用于保障网站安全与稳定。\n\n如后续增加表单、统计或第三方服务,本政策将同步更新并在收集前说明用途、范围与保存期限。',
|
||
termsTitle: '服务条款',
|
||
termsContent: '本网站内容用于介绍慧遇书院、卢慧老师、课程产品与官方信息。\n\n演示或待替换内容不构成正式服务承诺,正式课程与服务以经审核发布的页面及双方确认的协议为准。\n\n未经授权,不得以误导方式转载、改编或冒用本网站品牌与人物资料。',
|
||
},
|
||
}
|