Files
ai_game/client/js/data/StoryManager.js

357 lines
8.5 KiB
JavaScript
Raw Permalink Normal View History

/**
* 故事数据管理器
*/
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改写结局异步提交到草稿箱
*/
async rewriteEndingAsync(storyId, ending, prompt, userId) {
try {
// 先标记之前的未读草稿为已读
await this.markAllDraftsRead(userId);
const result = await post(`/drafts/ending`, {
userId: userId,
storyId: storyId,
endingName: ending?.name || '未知结局',
endingContent: ending?.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;
}
}
/**
* AI续写结局异步提交到草稿箱
*/
async continueEndingAsync(storyId, ending, prompt, userId) {
try {
// 先标记之前的未读草稿为已读
await this.markAllDraftsRead(userId);
const result = await post(`/drafts/continue-ending`, {
userId: userId,
storyId: storyId,
endingName: ending?.name || '未知结局',
endingContent: ending?.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;
}
}
/**
* 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;
}
}
}