import type { ChatSaveResult, MindSpacePage, MindSpacePageDeletePreview, MindSpacePageDeleteResult, MindSpaceSaveCategory, } from '../types'; import { ApiError, apiFetch, formatNetworkError, notifyUnauthorized, parseErrorResponse, } from './core'; export type MindSpaceListPage = { total?: number; offset?: number; limit?: number; has_more?: boolean; }; export async function getMindSpacePageDeletePreview( pageId: string, ): Promise { const result = await apiFetch<{ data: MindSpacePageDeletePreview }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}/delete-preview`, ); return result.data; } export function isMindSpacePageNotFoundError(err: unknown): boolean { return ( err instanceof ApiError && err.status === 404 && (err.code === 'page_not_found' || err.message === '页面不存在') ); } export async function deleteMindSpacePage( pageId: string, options?: { removeFromPlaza?: boolean }, ): Promise { const params = new URLSearchParams(); if (options?.removeFromPlaza) params.set('remove_from_plaza', 'true'); const query = params.toString() ? `?${params.toString()}` : ''; const result = await apiFetch<{ data: MindSpacePageDeleteResult }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}${query}`, { method: 'DELETE' }, ); return result.data; } export async function listMindSpacePages(options?: { status?: string; limit?: number; offset?: number; categoryCode?: string; }): Promise<{ items: MindSpacePage[]; page: MindSpaceListPage }> { const params = new URLSearchParams(); if (options?.status) params.set('status', options.status); if (options?.limit != null) params.set('limit', String(options.limit)); if (options?.offset != null) params.set('offset', String(options.offset)); if (options?.categoryCode) params.set('category_code', options.categoryCode); const query = params.toString() ? `?${params.toString()}` : ''; const result = await apiFetch<{ data: MindSpacePage[]; page?: MindSpaceListPage }>( `/mindspace/v1/pages${query}`, ); return { items: result.data, page: result.page ?? {} }; } export async function listMindSpaceAchievementPages(options?: { status?: string; limit?: number; offset?: number; categoryCode?: string; includeStats?: boolean; }): Promise<{ items: MindSpacePage[]; page: MindSpaceListPage }> { const params = new URLSearchParams(); if (options?.status) params.set('status', options.status); if (options?.limit != null) params.set('limit', String(options.limit)); if (options?.offset != null) params.set('offset', String(options.offset)); if (options?.categoryCode) params.set('category_code', options.categoryCode); if (options?.includeStats) params.set('include_stats', '1'); const query = params.toString() ? `?${params.toString()}` : ''; const result = await apiFetch<{ data: MindSpacePage[]; page?: MindSpaceListPage }>( `/mindspace/v1/pages/achievements${query}`, ); return { items: result.data, page: result.page ?? {} }; } export async function getMindSpacePage(pageId: string): Promise { const result = await apiFetch<{ data: MindSpacePage }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}`, ); return result.data; } export async function saveChatMessageAsPage(input: { sessionId: string; messageId: string; title: string; summary?: string; templateId?: string; categoryCode?: MindSpaceSaveCategory; selectedLinkIndex?: number; acknowledgedFindingIds?: string[]; replacePageId?: string; saveAsNew?: boolean; }): Promise { const result = await apiFetch<{ data: ChatSaveResult }>( '/mindspace/v1/pages/save-from-chat', { method: 'POST', body: JSON.stringify({ session_id: input.sessionId, message_id: input.messageId, title: input.title, summary: input.summary, template_id: input.templateId ?? 'editorial', category_code: input.categoryCode ?? 'draft', selected_link_index: input.selectedLinkIndex ?? 0, acknowledged_finding_ids: input.acknowledgedFindingIds, page_type: input.templateId === 'report' ? 'report' : 'article', replace_page_id: input.replacePageId, save_as_new: input.saveAsNew ?? false, }), }, ); return result.data; } export async function createMindSpacePageFromAsset(input: { assetId: string; title?: string; summary?: string; }): Promise { const result = await apiFetch<{ data: { page: MindSpacePage } }>( '/mindspace/v1/pages/from-asset', { method: 'POST', body: JSON.stringify({ asset_id: input.assetId, title: input.title, summary: input.summary, }), }, ); return result.data.page; } export async function createMindSpacePage(input: { title: string; summary?: string; content: string; templateId: string; }): Promise { const result = await apiFetch<{ data: MindSpacePage }>('/mindspace/v1/pages', { method: 'POST', body: JSON.stringify({ title: input.title, summary: input.summary, content: input.content, template_id: input.templateId, page_type: input.templateId === 'report' ? 'report' : 'article', }), }); return result.data; } export async function updateMindSpacePage( pageId: string, input: { expectedVersion: number; title: string; summary: string; content: string; templateId: string; changeNote?: string; }, ): Promise { const result = await apiFetch<{ data: MindSpacePage }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}`, { method: 'PUT', body: JSON.stringify({ expected_version: input.expectedVersion, title: input.title, summary: input.summary, content: input.content, template_id: input.templateId, page_type: input.templateId === 'report' ? 'report' : 'article', change_note: input.changeNote, }), }, ); return result.data; } export async function rewriteMindSpacePageDownloadLinks( pageId: string, content: string, ): Promise { const result = await apiFetch<{ data: { html: string } }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}/rewrite-download-links`, { method: 'POST', body: JSON.stringify({ content }), }, ); return result.data.html; } export async function fetchMindSpacePageDraftPreview( pageId: string, input: { title: string; summary: string; content: string; templateId: string; }, ): Promise { let res: Response; try { res = await fetch(`/api/mindspace/v1/pages/${encodeURIComponent(pageId)}/preview-draft`, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: input.title, summary: input.summary, content: input.content, template_id: input.templateId, }), }); } catch (err) { throw new ApiError(0, formatNetworkError(err)); } if (res.status === 401) { notifyUnauthorized(); throw new ApiError(401, '未授权,请重新登录'); } if (!res.ok) { const parsed = await parseErrorResponse(res); throw new ApiError(res.status, parsed.message || `${res.status} ${res.statusText}`, parsed.code); } return res.text(); } export function openMindSpaceDraftPreviewWindow(html: string) { const blob = new Blob([html], { type: 'text/html;charset=utf-8' }); const url = URL.createObjectURL(blob); const opened = window.open(url, '_blank', 'noopener,noreferrer'); if (!opened) { URL.revokeObjectURL(url); throw new ApiError(0, '无法打开新窗口,请检查浏览器是否拦截弹窗'); } window.setTimeout(() => URL.revokeObjectURL(url), 120_000); } export async function uploadMindSpacePageThumbnail( pageId: string, input: { imageBase64: string; mimeType?: string; title?: string; summary?: string; content?: string; }, ): Promise<{ updatedAt: number }> { const result = await apiFetch<{ data: { updatedAt: number } }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}/thumbnail/upload`, { method: 'POST', body: JSON.stringify({ image_base64: input.imageBase64, mime_type: input.mimeType, title: input.title, summary: input.summary, html: input.content, }), }, ); return result.data; } export async function regenerateMindSpacePageThumbnail( pageId: string, input: { title?: string; summary?: string; content?: string; useAi?: boolean; instruction?: string; } = {}, ): Promise<{ updatedAt: number; content?: string | null }> { const result = await apiFetch<{ data: { updatedAt: number; content?: string | null } }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}/thumbnail/regenerate`, { method: 'POST', body: JSON.stringify({ title: input.title, summary: input.summary, html: input.content, use_ai: input.useAi ?? false, instruction: input.instruction, }), }, ); return result.data; } export async function bindMindSpacePageLiveEdit( pageId: string, sessionId: string, options?: { parentSessionId?: string }, ): Promise<{ sessionId: string; pageId: string; parentSessionId?: string }> { const result = await apiFetch<{ data: { sessionId: string; pageId: string; parentSessionId?: string } }>( `/mindspace/v1/pages/${encodeURIComponent(pageId)}/live-edit/bind`, { method: 'POST', body: JSON.stringify({ session_id: sessionId, ...(options?.parentSessionId ? { parent_session_id: options.parentSessionId } : {}), }), }, ); return result.data; } export async function forkMindSpacePageEditSession( pageId: string, parentSessionId: string, h5ApiBase?: string | null, ): Promise<{ sessionId: string; pageId: string; parentSessionId: string }> { const result = await apiFetch<{ data: { sessionId: string; pageId: string; parentSessionId: string }; }>(`/mindspace/v1/pages/${encodeURIComponent(pageId)}/live-edit/fork-session`, { method: 'POST', body: JSON.stringify({ parent_session_id: parentSessionId, ...(h5ApiBase ? { h5_api_base: h5ApiBase } : {}), }), }); return result.data; } export async function closeMindSpacePageEditSession( pageId: string, input: { sessionId: string; parentSessionId?: string | null; summary?: string; }, ): Promise<{ sessionId: string; pageId: string; merged: boolean }> { const result = await apiFetch<{ data: { sessionId: string; pageId: string; merged: boolean }; }>(`/mindspace/v1/pages/${encodeURIComponent(pageId)}/live-edit/close-session`, { method: 'POST', body: JSON.stringify({ session_id: input.sessionId, parent_session_id: input.parentSessionId ?? undefined, summary: input.summary ?? '', }), }); return result.data; } export async function getMindSpacePageLiveRevision(pageId: string): Promise<{ pageId: string; versionNo: number; updatedAt: number; liveRevision: number; }> { const result = await apiFetch<{ data: { pageId: string; versionNo: number; updatedAt: number; liveRevision: number }; }>(`/mindspace/v1/pages/${encodeURIComponent(pageId)}/live-edit/revision`); return result.data; }