| |
| |
|
|
| export interface KnowledgeArticle { |
| id: string; |
| slug: string; |
| title: string; |
| category: string; |
| level: number; |
| tags: string[]; |
| summary: string; |
| content?: string; |
| viewCount: number; |
| createdAt: string; |
| } |
|
|
| export interface Case { |
| id: string; |
| title: string; |
| persona: string; |
| curveType: string; |
| chartData?: any[]; |
| highlights?: { age: number; type: string; note: string }[]; |
| narrative: string; |
| tags: string[]; |
| viewCount: number; |
| createdAt: string; |
| } |
|
|
| export interface SearchResult { |
| articles: Pick<KnowledgeArticle, 'id' | 'slug' | 'title' | 'category' | 'summary'>[]; |
| cases: Pick<Case, 'id' | 'title' | 'persona' | 'curveType'>[]; |
| } |
|
|
| |
| export async function getArticles(category?: string, limit = 20, offset = 0): Promise<KnowledgeArticle[]> { |
| const params = new URLSearchParams(); |
| if (category) params.append('category', category); |
| params.append('limit', String(limit)); |
| params.append('offset', String(offset)); |
|
|
| const response = await fetch(`/api/content/knowledge?${params}`); |
| if (!response.ok) { |
| throw new Error('Failed to fetch articles'); |
| } |
| const data = await response.json(); |
| return data.items; |
| } |
|
|
| |
| export async function getArticleBySlug(slug: string): Promise<KnowledgeArticle | null> { |
| const response = await fetch(`/api/content/knowledge/${slug}`); |
| if (!response.ok) { |
| if (response.status === 404) return null; |
| throw new Error('Failed to fetch article'); |
| } |
| const data = await response.json(); |
| return data.article; |
| } |
|
|
| |
| export async function getCases(curveType?: string, limit = 20, offset = 0): Promise<Case[]> { |
| const params = new URLSearchParams(); |
| if (curveType) params.append('curveType', curveType); |
| params.append('limit', String(limit)); |
| params.append('offset', String(offset)); |
|
|
| const response = await fetch(`/api/content/cases?${params}`); |
| if (!response.ok) { |
| throw new Error('Failed to fetch cases'); |
| } |
| const data = await response.json(); |
| return data.items; |
| } |
|
|
| |
| export async function getCaseById(id: string): Promise<Case | null> { |
| const response = await fetch(`/api/content/cases/${id}`); |
| if (!response.ok) { |
| if (response.status === 404) return null; |
| throw new Error('Failed to fetch case'); |
| } |
| const data = await response.json(); |
| return data.case; |
| } |
|
|
| |
| export async function searchContent(query: string, limit = 10): Promise<SearchResult> { |
| if (!query || query.length < 2) { |
| return { articles: [], cases: [] }; |
| } |
| const params = new URLSearchParams(); |
| params.append('q', query); |
| params.append('limit', String(limit)); |
|
|
| const response = await fetch(`/api/content/search?${params}`); |
| if (!response.ok) { |
| throw new Error('Failed to search content'); |
| } |
| return response.json(); |
| } |
|
|
| |
| export const CATEGORY_MAP: Record<string, string> = { |
| quickstart: '快速入门', |
| kline: 'K线逻辑', |
| bazi: '八字基础', |
| dayun: '大运流年', |
| method: '方法误区', |
| faq: '常见问题', |
| }; |
|
|
| |
| export const CURVE_TYPE_MAP: Record<string, string> = { |
| '早发': '早发型', |
| '晚成': '晚成型', |
| '大起大落': '大起大落型', |
| }; |
|
|
| |
| export function getCategoryName(category: string): string { |
| return CATEGORY_MAP[category] || category; |
| } |
|
|
| |
| export function getCurveTypeName(curveType: string): string { |
| return CURVE_TYPE_MAP[curveType] || curveType; |
| } |
|
|