- Header 改为异步 Server Component,接入 NavigationMenu(name=main), 接口不可用或未配置时回退静态导航项 - Footer 改为异步 Server Component,接入 SiteSettings, 公司名/ICP备案号/备案链接优先取后台配置,缺省回退硬编码值 - types/wagtail.ts 新增 TeamMember/Testimonial/Partner/NavigationMenu/SiteSettings 类型 - 新增 services: team/testimonial/partner/navigation/site-settings.service.ts - lint、build 均已验证通过
213 lines
4.7 KiB
TypeScript
213 lines
4.7 KiB
TypeScript
/**
|
|
* Wagtail API v2 通用类型定义。
|
|
* 对应后端 apps/core/blocks.py 中的 StreamField Block 结构,
|
|
* 前后端字段需保持一致(详见 documents/设计方案分析与完善版.md §2.6)。
|
|
*/
|
|
|
|
export interface WagtailMeta {
|
|
type: string;
|
|
detail_url: string;
|
|
html_url: string | null;
|
|
slug: string;
|
|
first_published_at: string | null;
|
|
}
|
|
|
|
export interface WagtailPageSummary {
|
|
id: number;
|
|
meta: WagtailMeta;
|
|
title: string;
|
|
}
|
|
|
|
export interface WagtailListResponse<T> {
|
|
meta: { total_count: number };
|
|
items: T[];
|
|
}
|
|
|
|
export interface CTAButtonValue {
|
|
text: string;
|
|
link: string;
|
|
}
|
|
|
|
export interface StatItemValue {
|
|
value: string;
|
|
label: string;
|
|
}
|
|
|
|
export interface FeatureItemValue {
|
|
icon?: string;
|
|
title: string;
|
|
description: string;
|
|
}
|
|
|
|
export interface FAQItemValue {
|
|
question: string;
|
|
answer: string; // richtext HTML
|
|
}
|
|
|
|
export interface HeroBlockValue {
|
|
title: string;
|
|
subtitle?: string;
|
|
background_image?: { url: string; title: string } | null;
|
|
buttons: CTAButtonValue[];
|
|
}
|
|
|
|
export interface StatsBlockValue {
|
|
items: StatItemValue[];
|
|
}
|
|
|
|
export interface FeatureGridBlockValue {
|
|
heading?: string;
|
|
items: FeatureItemValue[];
|
|
}
|
|
|
|
export interface FAQBlockValue {
|
|
items: FAQItemValue[];
|
|
}
|
|
|
|
export interface CTABlockValue {
|
|
heading: string;
|
|
description?: string;
|
|
button: CTAButtonValue;
|
|
}
|
|
|
|
export interface LogoCloudBlockValue {
|
|
heading?: string;
|
|
logos: { url: string; title: string }[];
|
|
}
|
|
|
|
export interface CaseStudyBlockValue {
|
|
case_page: WagtailPageSummary | null;
|
|
summary?: string;
|
|
}
|
|
|
|
/** 与后端 apps/forms/models.py FIELD_TYPE_CHOICES 保持一致 */
|
|
export type FormFieldType = "text" | "textarea" | "email" | "tel" | "select";
|
|
|
|
export interface FormFieldDef {
|
|
label: string;
|
|
field_key: string;
|
|
field_type: FormFieldType;
|
|
required: boolean;
|
|
choices: string[];
|
|
}
|
|
|
|
export interface FormDefinitionValue {
|
|
id: number;
|
|
name: string;
|
|
submit_button_text: string;
|
|
success_message: string;
|
|
fields: FormFieldDef[];
|
|
}
|
|
|
|
export interface FormBlockValue {
|
|
form: FormDefinitionValue | null;
|
|
}
|
|
|
|
export type StreamFieldBlock =
|
|
| { id: string; type: "hero"; value: HeroBlockValue }
|
|
| { id: string; type: "stats"; value: StatsBlockValue }
|
|
| { id: string; type: "feature_grid"; value: FeatureGridBlockValue }
|
|
| { id: string; type: "faq"; value: FAQBlockValue }
|
|
| { id: string; type: "cta"; value: CTABlockValue }
|
|
| { id: string; type: "logo_cloud"; value: LogoCloudBlockValue }
|
|
| { id: string; type: "case_study"; value: CaseStudyBlockValue }
|
|
| { id: string; type: "form"; value: FormBlockValue }
|
|
| { id: string; type: "richtext"; value: string };
|
|
|
|
export interface HomePageDetail extends WagtailPageSummary {
|
|
body: StreamFieldBlock[];
|
|
seo_title_override?: string;
|
|
seo_description_override?: string;
|
|
}
|
|
|
|
export interface BlogPageSummary extends WagtailPageSummary {
|
|
intro?: string;
|
|
published_at?: string;
|
|
}
|
|
|
|
export interface BlogPageDetail extends BlogPageSummary {
|
|
body: StreamFieldBlock[];
|
|
}
|
|
|
|
export interface ProductPageSummary extends WagtailPageSummary {
|
|
summary?: string;
|
|
}
|
|
|
|
export interface ProductPageDetail extends ProductPageSummary {
|
|
body: StreamFieldBlock[];
|
|
}
|
|
|
|
export interface CaseStudyPageSummary extends WagtailPageSummary {
|
|
client_name: string;
|
|
industry?: string;
|
|
published_at?: string;
|
|
summary?: string;
|
|
}
|
|
|
|
export interface CaseStudyPageDetail extends CaseStudyPageSummary {
|
|
body: StreamFieldBlock[];
|
|
}
|
|
|
|
export interface SolutionPageSummary extends WagtailPageSummary {
|
|
industry?: string;
|
|
summary?: string;
|
|
}
|
|
|
|
export interface SolutionPageDetail extends SolutionPageSummary {
|
|
body: StreamFieldBlock[];
|
|
}
|
|
|
|
export interface SimpleContentPageDetail extends WagtailPageSummary {
|
|
body: string; // richtext HTML
|
|
}
|
|
|
|
/**
|
|
* 全局 Snippet 类型(apps/core/models.py)。
|
|
* 通过 /api/v1/custom/core/... 只读接口获取,非 Wagtail Page API。
|
|
*/
|
|
export interface TeamMemberValue {
|
|
id: number;
|
|
name: string;
|
|
role: string;
|
|
bio: string;
|
|
photo: { url: string; title: string } | null;
|
|
}
|
|
|
|
export interface TestimonialValue {
|
|
id: number;
|
|
quote: string;
|
|
author_name: string;
|
|
author_title: string;
|
|
author_photo: { url: string; title: string } | null;
|
|
}
|
|
|
|
export interface PartnerValue {
|
|
id: number;
|
|
name: string;
|
|
website_url: string;
|
|
logo: { url: string; title: string } | null;
|
|
}
|
|
|
|
export interface NavigationMenuItemValue {
|
|
label: string;
|
|
url: string;
|
|
open_in_new_tab: boolean;
|
|
}
|
|
|
|
export interface NavigationMenuValue {
|
|
name: string;
|
|
items: NavigationMenuItemValue[];
|
|
}
|
|
|
|
export interface SiteSettingsValue {
|
|
company_name: string;
|
|
contact_phone: string;
|
|
contact_email: string;
|
|
address: string;
|
|
icp_number: string;
|
|
icp_url: string;
|
|
wechat_account: string;
|
|
weibo_url: string;
|
|
wechat_qrcode: { url: string; title: string } | null;
|
|
}
|