feat: 游玩记录多版本功能 - 支持多版本记录存储和回放 - 相同路径自动去重只保留最新 - 版本列表支持删除功能 - AI草稿箱游玩不记录历史 - iOS日期格式兼容修复

This commit is contained in:
wangwuww111
2026-03-10 12:44:55 +08:00
parent 9948ccba8f
commit baf7dd1e2b
8 changed files with 693 additions and 35 deletions

View File

@@ -8,6 +8,7 @@ export default class StoryScene extends BaseScene {
super(main, params);
this.storyId = params.storyId;
this.draftId = params.draftId || null; // 草稿ID
this.playRecordId = params.playRecordId || null; // 游玩记录ID从记录回放
this.aiContent = params.aiContent || null; // AI改写内容
this.story = null;
this.currentNode = null;
@@ -42,6 +43,8 @@ export default class StoryScene extends BaseScene {
this.recapCardRects = [];
// 重头游玩模式
this.isReplayMode = false;
this.isRecordReplay = false; // 是否是从记录回放区别AI改写回放
this.recordReplayEnding = null; // 记录回放的结局信息
this.replayPath = [];
this.replayPathIndex = 0;
}
@@ -59,6 +62,66 @@ export default class StoryScene extends BaseScene {
}
async init() {
// 如果是从记录回放
if (this.playRecordId) {
this.main.showLoading('加载回放记录...');
try {
const record = await this.main.userManager.getPlayRecordDetail(this.playRecordId);
if (record && record.pathHistory) {
// 加载故事
this.story = await this.main.storyManager.loadStoryDetail(record.storyId);
if (this.story) {
this.setThemeByCategory(this.story.category);
// 设置记录回放模式
this.isRecordReplay = true;
this.replayPath = record.pathHistory || [];
this.replayPathIndex = 0;
this.recordReplayEnding = {
name: record.endingName,
type: record.endingType
};
console.log('[RecordReplay] 开始记录回放, pathHistory长度:', this.replayPath.length);
this.main.hideLoading();
// 如果 pathHistory 为空,说明用户在起始节点就到达了结局
if (this.replayPath.length === 0) {
this.main.storyManager.currentNodeKey = 'start';
this.currentNode = this.main.storyManager.getCurrentNode();
if (this.currentNode) {
this.startTypewriter(this.currentNode.content);
}
return;
}
this.isReplayMode = true;
// 从 start 节点开始
this.main.storyManager.currentNodeKey = 'start';
this.main.storyManager.pathHistory = [];
this.currentNode = this.main.storyManager.getCurrentNode();
if (this.currentNode) {
this.startTypewriter(this.currentNode.content);
}
return;
}
}
} catch (e) {
console.error('加载回放记录失败:', e);
}
this.main.hideLoading();
this.main.showError('记录加载失败');
this.main.sceneManager.switchScene('home');
return;
}
// 如果是从Draft加载先获取草稿详情进入回顾模式
if (this.draftId) {
this.main.showLoading('加载AI改写内容...');
@@ -423,10 +486,21 @@ export default class StoryScene extends BaseScene {
if (!this.recapData) return;
this.isRecapMode = false;
this.isReplayMode = true;
this.replayPathIndex = 0;
this.replayPath = this.recapData.pathHistory || [];
console.log('[ReplayMode] 开始回放, pathHistory长度:', this.replayPath.length);
// 如果 pathHistory 为空,说明用户在起始节点就改写了,直接进入 AI 内容
if (this.replayPath.length === 0) {
console.log('[ReplayMode] pathHistory为空直接进入AI内容');
this.isReplayMode = false;
this.enterAIContent();
return;
}
this.isReplayMode = true;
// 从 start 节点开始
this.main.storyManager.currentNodeKey = 'start';
this.main.storyManager.pathHistory = [];
@@ -439,9 +513,20 @@ export default class StoryScene extends BaseScene {
// 自动选择回放路径中的选项
autoSelectReplayChoice() {
console.log('[ReplayMode] autoSelectReplayChoice, index:', this.replayPathIndex, ', total:', this.replayPath.length);
if (!this.isReplayMode || this.replayPathIndex >= this.replayPath.length) {
// 回放结束进入AI改写内容
// 回放结束
console.log('[ReplayMode] 回放结束');
this.isReplayMode = false;
// 记录回放模式:进入结局页面
if (this.isRecordReplay) {
this.finishRecordReplay();
return;
}
// AI改写回放模式进入AI内容
this.enterAIContent();
return;
}
@@ -450,6 +535,8 @@ export default class StoryScene extends BaseScene {
const currentPath = this.replayPath[this.replayPathIndex];
const currentNode = this.main.storyManager.getCurrentNode();
console.log('[ReplayMode] 当前路径:', currentPath?.choice, ', 当前节点选项:', currentNode?.choices?.map(c => c.text));
if (currentNode && currentNode.choices) {
const choiceIndex = currentNode.choices.findIndex(c => c.text === currentPath.choice);
if (choiceIndex >= 0) {
@@ -463,9 +550,34 @@ export default class StoryScene extends BaseScene {
}
}
// 找不到匹配的选项直接进入AI内容
// 找不到匹配的选项
console.log('[ReplayMode] 找不到匹配选项');
this.isReplayMode = false;
this.enterAIContent();
if (this.isRecordReplay) {
this.finishRecordReplay();
} else {
this.enterAIContent();
}
}
// 完成记录回放,进入结局页面
finishRecordReplay() {
console.log('[RecordReplay] 回放完成,进入结局页面');
// 获取结局信息
const endingInfo = this.main.storyManager.getEndingInfo() || this.recordReplayEnding || {};
this.main.sceneManager.switchScene('ending', {
storyId: this.storyId,
ending: {
name: endingInfo.name || this.recordReplayEnding?.name || '未知结局',
type: endingInfo.type || this.recordReplayEnding?.type || '',
content: this.currentNode?.content || '',
score: endingInfo.score || 80
},
isReplay: true // 标记为回放模式,不重复保存记录
});
}
// 进入AI改写内容
@@ -502,8 +614,9 @@ export default class StoryScene extends BaseScene {
startTypewriter(text) {
let content = text || '';
// 回放模式下,过滤掉结局提示(因为后面还有AI改写内容)
if (this.isReplayMode) {
// 回放模式下,过滤掉结局提示(因为后面还有内容)
// 但记录回放模式不过滤,因为要完整显示原结局
if (this.isReplayMode && !this.isRecordReplay) {
content = content.replace(/【达成结局[:][^】]*】/g, '').trim();
}
@@ -1110,13 +1223,29 @@ export default class StoryScene extends BaseScene {
return;
}
// 回放模式下,如果到达原结局或没有选项进入AI改写内容
// 回放模式下,如果回放路径已用完或到达原结局
if (this.isReplayMode) {
const currentNode = this.main.storyManager.getCurrentNode();
if (!currentNode || !currentNode.choices || currentNode.choices.length === 0 || currentNode.is_ending) {
// 回放结束进入AI改写内容
// 检查回放路径是否已用完
if (this.replayPathIndex >= this.replayPath.length) {
console.log('[ReplayMode] 回放路径已用完');
this.isReplayMode = false;
this.enterAIContent();
if (this.isRecordReplay) {
this.finishRecordReplay();
} else {
this.enterAIContent();
}
return;
}
// 检查当前节点是否是结局或没有选项
if (!currentNode || !currentNode.choices || currentNode.choices.length === 0 || currentNode.is_ending) {
console.log('[ReplayMode] 到达结局或无选项');
this.isReplayMode = false;
if (this.isRecordReplay) {
this.finishRecordReplay();
} else {
this.enterAIContent();
}
return;
}
}