export interface SiteSettings { siteTitle: string; siteFooter: string; enableCodeIcon: boolean; repoUrl: string; favicon: string; } export const getSettings = async (): Promise => { try { const response = await fetch('/api/settings'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1000 && json.data) { const data = json.data; return { siteTitle: data.title, siteFooter: data.footer_text, enableCodeIcon: data.enable_repo_button ?? true, repoUrl: data.repo_link, favicon: data.icon, }; } else { throw new Error('Invalid response code or missing data'); } } catch (error) { console.error('Failed to fetch settings:', error); throw error; } }; export const getAbout = async (): Promise => { try { const response = await fetch('/api/about'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1000) { return json.data; } else { throw new Error('Invalid response code'); } } catch (error) { console.error('Failed to fetch about content:', error); throw error; } }; export interface StaticsData { posts: number; comments: number; images: number; } export const testApiStatus = async (): Promise => { try { const response = await fetch('/api/test'); return response.ok; } catch (error) { return false; } }; export const getStatics = async (): Promise => { try { const response = await fetch('/api/statics'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1000) { return json.data; } else { throw new Error('Invalid response code'); } } catch (error) { console.error('Failed to fetch statics:', error); throw error; } }; export const saveDraft = (content: string): void => { localStorage.setItem('draft', content); }; export const getDraft = (): string | null => { return localStorage.getItem('draft'); }; export const fetch_id_token = async (): Promise => { try { const response = await fetch('/api/get_id_token'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1000) { return json.data; } else { throw new Error(json.data || 'Failed to fetch identity token'); } } catch (error) { console.error('Failed to fetch identity token:', error); throw error; } }; export const get_id_token = async (): Promise => { let token = localStorage.getItem('identity_token'); if (!token) { token = await fetch_id_token(); localStorage.setItem('identity_token', token); } return token; }; export interface CreatePostResponse { code: number; data: any; } export const createPost = async (content: string): Promise => { try { const identity = await get_id_token(); // 解析标签:#开头,后跟非空白字符 const hashtopic: string[] = []; const regex = /#\S+/g; const matches = content.match(regex); if (matches) { matches.forEach(tag => { const cleanTag = tag.substring(1); // 去重添加 if (!hashtopic.includes(cleanTag)) { hashtopic.push(cleanTag); } }); } const response = await fetch('/api/post', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ content, hashtopic, identity }), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { console.error('Failed to create post:', error); throw error; } }; export interface Article { id: number; content: string; upvotes: number; downvotes: number; created_at?: string; comment_count?: number; total_pages?: number; } export const fetchArticles = async (page: number, signal?: AbortSignal): Promise => { try { const response = await fetch(`/api/posts_info?page=${page}`, { signal }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1000 && Array.isArray(json.data)) { return json.data as Article[]; } throw new Error('Invalid response code or missing data'); } catch (error) { console.error('Failed to fetch articles:', error); throw error; } }; export const voteArticle = async (id: number, type: 'up' | 'down'): Promise => { try { const response = await fetch(`/api/${type}`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id, type: 'submission' }), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code !== 1000) { throw new Error('Vote failed'); } } catch (error) { console.error('Failed to vote:', error); throw error; } }; export interface Comment { id: number; nickname: string; content: string; parent_comment_id: number; } export interface CommentPage { comments: Comment[]; total_pages: number; } export const getComments = async (id: string | number, page: number = 1): Promise => { try { const response = await fetch(`/api/get/comment?id=${id}&page=${page}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1000 && json.data && Array.isArray(json.data.comments)) { return { comments: json.data.comments as Comment[], total_pages: Number(json.data.total_pages) || 0, }; } throw new Error('Invalid response code or missing data'); } catch (error) { console.error('Failed to fetch comments:', error); throw error; } }; export interface PostCommentRequest { content: string; submission_id: number; parent_comment_id: number; nickname: string; } export interface PostCommentResponse { id: number; } export const postComment = async (commentData: PostCommentRequest): Promise => { try { const identity = await get_id_token(); const hashtopic: string[] = []; const regex = /#\S+/g; const matches = commentData.content.match(regex); if (matches) { matches.forEach(tag => { const cleanTag = tag.substring(1); if (!hashtopic.includes(cleanTag)) { hashtopic.push(cleanTag); } }); } const response = await fetch('/api/comment', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ ...commentData, hashtopic, identity, }), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1001 && json.data?.id !== undefined) { return { id: Number(json.data.id) }; } if (json.code === 2005) { throw new Error('评论包含违禁词'); } throw new Error('Comment failed'); } catch (error) { console.error('Failed to post comment:', error); throw error; } }; export interface ReportPostResponse { id: number; } export const reportPost = async (reportData: { id: number; title: string; content: string }): Promise => { try { const identity = await get_id_token(); const response = await fetch('/api/report', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ ...reportData, identity, }), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1001 && json.data?.id !== undefined) { return { id: Number(json.data.id) }; } throw new Error(json.data || 'Report failed'); } catch (error) { console.error('Failed to report post:', error); throw error; } }; export const uploadImage = async (file: File): Promise => { try { const identity_token = await get_id_token(); const formData = new FormData(); formData.append('file', file); if (identity_token) { formData.append('identity_token', identity_token); } const response = await fetch('/api/upload_pic', { method: 'POST', body: formData, }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1001 && typeof json.data === 'string') { return json.data; } if (json.code === 2006) { throw new Error('UPLOAD_TOO_LARGE'); } if (json.code === 2007) { throw new Error('UNSUPPORTED_FORMAT'); } throw new Error(json.data || 'Upload failed'); } catch (error) { console.error('Failed to upload image:', error); throw error; } }; export const getFileName = async (path: string): Promise => { try { const response = await fetch(`/api/file_name?path=${encodeURIComponent(path)}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); if (json.code === 1000 && typeof json.data === 'string') { return json.data; } throw new Error('Invalid response code or missing data'); } catch (error) { console.error('Failed to fetch file name:', error); throw error; } };