import { API_BASE_URL, requestJson } from '@/services/api.uts' export type ContentSection = { id: string, title: string, body: string } export type NewsArticle = { id: string, title: string, summary: string, category: string, date: string, source: string, readingTime: string, image: string, sections: ContentSection[] } export type FinanceLesson = { id: string, title: string, desc: string, duration: string, tag: string, image: string, intro: string, topics: string[], chapters: ContentSection[], chapterCount: number, lessonVersion: string } export type ArticlePage = { items: NewsArticle[], total: number, hasMore: boolean } export type LessonPage = { items: FinanceLesson[], total: number, hasMore: boolean } export type LessonState = { lessonVersion: string, completedChapterIds: string[] } export type ContentHome = { lessons: FinanceLesson[], articles: NewsArticle[] } export type ContentSearchResult = { id: string, type: string, title: string, summary: string, category: string, meta: string, image: string } export type SearchPage = { items: ContentSearchResult[], total: number, hasMore: boolean } function imageUrl(value: string): string { // 随包图片保留本地路径,后台上传的封面从接口站点读取。 if (value.startsWith('/uploads/')) return API_BASE_URL.replace('/api/v1', '') + value return value } function sections(value: UTSJSONObject[]): ContentSection[] { return value.map((item: UTSJSONObject): ContentSection => ({ id: item.getString('id') ?? '', title: item.getString('title') ?? '', body: item.getString('body') ?? '' })) } function articleFrom(data: UTSJSONObject): NewsArticle { return { id: data.getString('id') ?? '', title: data.getString('title') ?? '', summary: data.getString('summary') ?? '', category: data.getString('category') ?? '', date: data.getString('date') ?? '', source: data.getString('source') ?? '', readingTime: data.getString('readingTime') ?? '', image: imageUrl(data.getString('image') ?? ''), sections: sections(data['sections'] as UTSJSONObject[]) } } function lessonFrom(data: UTSJSONObject): FinanceLesson { return { id: data.getString('id') ?? '', title: data.getString('title') ?? '', desc: data.getString('desc') ?? '', duration: data.getString('duration') ?? '', tag: data.getString('tag') ?? '', image: imageUrl(data.getString('image') ?? ''), intro: data.getString('intro') ?? '', topics: data['topics'] as string[], chapters: sections(data['chapters'] as UTSJSONObject[]), chapterCount: data.getNumber('chapterCount') ?? 0, lessonVersion: data.getString('lessonVersion') ?? '' } } export async function fetchArticles(category: string, page: number = 1): Promise { const data = await requestJson('/content/articles', 'GET', { category, page, pageSize: 20 }) return { items: (data['items'] as UTSJSONObject[]).map((item: UTSJSONObject): NewsArticle => articleFrom(item)), total: data.getNumber('total') ?? 0, hasMore: data.getBoolean('hasMore') ?? false } } export async function fetchArticle(id: string): Promise { return articleFrom(await requestJson('/content/articles/' + encodeURIComponent(id), 'GET', {})) } export async function fetchLessons(topic: string, page: number = 1): Promise { const data = await requestJson('/content/lessons', 'GET', { topic, page, pageSize: 20 }) return { items: (data['items'] as UTSJSONObject[]).map((item: UTSJSONObject): FinanceLesson => lessonFrom(item)), total: data.getNumber('total') ?? 0, hasMore: data.getBoolean('hasMore') ?? false } } export async function fetchLesson(id: string): Promise { return lessonFrom(await requestJson('/content/lessons/' + encodeURIComponent(id), 'GET', {})) } function stateFrom(data: UTSJSONObject): LessonState { return { lessonVersion: data.getString('lessonVersion') ?? '', completedChapterIds: data['completedChapterIds'] as string[] } } export async function fetchLessonProgress(id: string): Promise { return stateFrom(await requestJson('/content/lessons/' + id + '/progress', 'GET', {})) } export async function completeLessonChapter(id: string, chapterId: string, lessonVersion: string): Promise { return stateFrom(await requestJson('/content/lessons/' + id + '/progress', 'PUT', { chapterId, lessonVersion, completed: true })) } export async function fetchContentHome(): Promise { const data = await requestJson('/content/home', 'GET', {}) return { lessons: (data['lessons'] as UTSJSONObject[]).map((item: UTSJSONObject): FinanceLesson => lessonFrom(item)), articles: (data['articles'] as UTSJSONObject[]).map((item: UTSJSONObject): NewsArticle => articleFrom(item)) } } export async function searchContent(keyword: string, type: string, page: number = 1): Promise { const data = await requestJson('/content/search', 'GET', { keyword, type, page, pageSize: 20 }) const items = (data['items'] as UTSJSONObject[]).map((item: UTSJSONObject): ContentSearchResult => ({ id: item.getString('id') ?? '', type: item.getString('type') ?? '', title: item.getString('title') ?? '', summary: item.getString('summary') ?? '', category: item.getString('category') ?? '', meta: item.getString('meta') ?? '', image: imageUrl(item.getString('image') ?? '') })) return { items, total: data.getNumber('total') ?? 0, hasMore: data.getBoolean('hasMore') ?? false } } export function emptyArticle(): NewsArticle { return { id: '', title: '', summary: '', category: '', date: '', source: '', readingTime: '', image: '', sections: [] } } export function emptyLesson(): FinanceLesson { return { id: '', title: '', desc: '', duration: '', tag: '', image: '', intro: '', topics: [], chapters: [], chapterCount: 0, lessonVersion: '' } }