/** * 故事数据管理器 */ import { get, post, request } from '../utils/http'; export default class StoryManager { constructor() { this.storyList = []; this.currentStory = null; this.currentNodeKey = 'start'; this.categories = []; this.pathHistory = []; // 记录用户走过的路径 } /** * 加载故事列表 */ async loadStoryList(options = {}) { try { this.storyList = await get('/stories', options); return this.storyList; } catch (error) { console.error('加载故事列表失败:', error); return []; } } /** * 加载热门故事 */ async loadHotStories(limit = 10) { try { return await get('/stories/hot', { limit }); } catch (error) { console.error('加载热门故事失败:', error); return []; } } /** * 加载分类列表 */ async loadCategories() { try { this.categories = await get('/stories/categories'); return this.categories; } catch (error) { console.error('加载分类失败:', error); return []; } } /** * 加载故事详情 */ async loadStoryDetail(storyId) { try { this.currentStory = await get(`/stories/${storyId}`); this.currentNodeKey = 'start'; this.pathHistory = []; // 重置路径历史 // 记录游玩次数 await post(`/stories/${storyId}/play`); return this.currentStory; } catch (error) { console.error('加载故事详情失败:', error); return null; } } /** * 获取当前节点 */ getCurrentNode() { if (!this.currentStory || !this.currentStory.nodes) return null; return this.currentStory.nodes[this.currentNodeKey]; } /** * 选择选项,前进到下一个节点 */ selectChoice(choiceIndex) { const currentNode = this.getCurrentNode(); if (!currentNode || !currentNode.choices || !currentNode.choices[choiceIndex]) { return null; } const choice = currentNode.choices[choiceIndex]; // 记录路径历史 this.pathHistory.push({ nodeKey: this.currentNodeKey, content: currentNode.content, choice: choice.text }); this.currentNodeKey = choice.nextNodeKey; return this.getCurrentNode(); } /** * 检查当前节点是否为结局 */ isEnding() { const currentNode = this.getCurrentNode(); return currentNode && currentNode.is_ending; } /** * 获取结局信息 */ getEndingInfo() { const currentNode = this.getCurrentNode(); if (!currentNode || !currentNode.is_ending) return null; return { name: currentNode.ending_name, score: currentNode.ending_score, type: currentNode.ending_type, content: currentNode.content }; } /** * 重置故事进度 */ resetStory() { this.currentNodeKey = 'start'; this.pathHistory = []; // 清空路径历史 } /** * 点赞故事 */ async likeStory(like = true) { if (!this.currentStory) return; await post(`/stories/${this.currentStory.id}/like`, { like }); } /** * AI改写结局 */ async rewriteEnding(storyId, ending, prompt) { try { const result = await post(`/stories/${storyId}/rewrite`, { ending_name: ending?.name, ending_content: ending?.content, prompt: prompt }, { timeout: 60000 }); return result; } catch (error) { console.error('AI改写失败:', error?.errMsg || error?.message || JSON.stringify(error)); return null; } } /** * AI改写中间章节,异步提交到草稿箱 * @returns {Object|null} 成功返回草稿ID,失败返回 null */ async rewriteBranchAsync(storyId, prompt, userId) { try { // 先标记之前的未读草稿为已读,避免轮询弹出之前的通知 await this.markAllDraftsRead(userId); const currentNode = this.getCurrentNode(); const result = await post(`/drafts`, { userId: userId, storyId: storyId, currentNodeKey: this.currentNodeKey, pathHistory: this.pathHistory, currentContent: currentNode?.content || '', prompt: prompt }, { timeout: 30000 }); if (result && result.draftId) { return result; } return null; } catch (error) { console.error('AI改写提交失败:', error?.errMsg || error?.message || JSON.stringify(error)); return null; } } /** * 获取用户草稿列表 */ async getDrafts(userId) { try { const result = await get(`/drafts?userId=${userId}`); return result || []; } catch (error) { console.error('获取草稿列表失败:', error); return []; } } /** * 检查是否有新完成的草稿 */ async checkNewDrafts(userId) { try { const result = await get(`/drafts/check-new?userId=${userId}`); return result || { hasNew: false, count: 0, drafts: [] }; } catch (error) { console.error('检查新草稿失败:', error); return { hasNew: false, count: 0, drafts: [] }; } } /** * 批量标记所有未读草稿为已读 */ async markAllDraftsRead(userId) { try { await request({ url: `/drafts/batch-read?userId=${userId}`, method: 'PUT' }); return true; } catch (error) { console.error('批量标记已读失败:', error); return false; } } /** * 获取草稿详情 */ async getDraftDetail(draftId) { try { const result = await get(`/drafts/${draftId}`); return result; } catch (error) { console.error('获取草稿详情失败:', error); return null; } } /** * 删除草稿 */ async deleteDraft(draftId, userId) { try { const result = await request({ url: `/drafts/${draftId}?userId=${userId}`, method: 'DELETE' }); return true; } catch (error) { console.error('删除草稿失败:', error); return false; } } /** * 从草稿加载并播放 AI 生成的内容 */ loadDraftContent(draft) { if (!draft || !draft.aiNodes) return null; // 将 AI 生成的节点合并到当前故事 if (this.currentStory) { Object.assign(this.currentStory.nodes, draft.aiNodes); this.currentNodeKey = draft.entryNodeKey || 'branch_1'; return this.getCurrentNode(); } return null; } /** * AI续写故事 */ async continueStory(storyId, prompt) { try { const result = await post(`/stories/${storyId}/continue`, { current_node_key: this.currentNodeKey, prompt: prompt }); return result; } catch (error) { console.error('AI续写失败:', error); return null; } } /** * AI创作新故事 */ async createStory(params) { try { const result = await post('/stories/ai-create', { genre: params.genre, keywords: params.keywords, protagonist: params.protagonist, conflict: params.conflict }); return result; } catch (error) { console.error('AI创作失败:', error); return null; } } }