feat: 游玩记录多版本功能 - 支持多版本记录存储和回放 - 相同路径自动去重只保留最新 - 版本列表支持删除功能 - AI草稿箱游玩不记录历史 - iOS日期格式兼容修复
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user