feat: AI中间章节改写功能 + 滚动优化

This commit is contained in:
wangwuww111
2026-03-06 13:16:54 +08:00
parent 66d4bd60c1
commit bbdccfa843
9 changed files with 602 additions and 21 deletions

View File

@@ -29,6 +29,8 @@ export default class StoryScene extends BaseScene {
// 场景图相关
this.sceneImage = null;
this.sceneColors = this.generateSceneColors();
// AI改写相关
this.isAIRewriting = false;
}
// 根据场景生成氛围色
@@ -246,16 +248,33 @@ export default class StoryScene extends BaseScene {
ctx.textAlign = 'center';
ctx.font = 'bold 15px sans-serif';
ctx.fillStyle = this.sceneColors.accent;
const title = this.story.title.length > 10 ? this.story.title.substring(0, 10) + '...' : this.story.title;
const title = this.story.title.length > 8 ? this.story.title.substring(0, 8) + '...' : this.story.title;
ctx.fillText(title, this.screenWidth / 2, 35);
}
// 进度指示
ctx.textAlign = 'right';
ctx.font = '12px sans-serif';
ctx.fillStyle = 'rgba(255,255,255,0.5)';
const progress = this.main.storyManager.getProgress ? this.main.storyManager.getProgress() : '';
ctx.fillText(progress, this.screenWidth - 15, 35);
// AI改写按钮右上角
const btnX = this.screenWidth - 70;
const btnY = 18;
const btnW = 55;
const btnH = 26;
// 按钮背景
if (this.isAIRewriting) {
ctx.fillStyle = 'rgba(255,255,255,0.2)';
} else {
const gradient = ctx.createLinearGradient(btnX, btnY, btnX + btnW, btnY);
gradient.addColorStop(0, '#a855f7');
gradient.addColorStop(1, '#ec4899');
ctx.fillStyle = gradient;
}
this.roundRect(ctx, btnX, btnY, btnW, btnH, 13);
ctx.fill();
// 按钮文字
ctx.fillStyle = '#ffffff';
ctx.font = '11px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(this.isAIRewriting ? '生成中' : 'AI改写', btnX + btnW / 2, btnY + 17);
}
renderDialogBox(ctx) {
@@ -300,14 +319,14 @@ export default class StoryScene extends BaseScene {
const textY = boxY + 65;
const lineHeight = 26;
const maxWidth = this.screenWidth - padding * 2;
const visibleHeight = boxHeight - 105; // 可见区域高度
const visibleHeight = boxHeight - 90; // 增加可见区域高度
ctx.font = '15px sans-serif';
const allLines = this.getWrappedLines(ctx, this.displayText, maxWidth);
const totalTextHeight = allLines.length * lineHeight;
// 计算最大滚动距离
this.maxScrollY = Math.max(0, totalTextHeight - visibleHeight);
this.maxScrollY = Math.max(0, totalTextHeight - visibleHeight + 30);
// 自动滚动到最新内容(打字时)
if (this.isTyping) {
@@ -334,9 +353,17 @@ export default class StoryScene extends BaseScene {
if (this.maxScrollY > 0) {
const scrollBarHeight = 40;
const scrollBarY = boxY + 55 + (this.textScrollY / this.maxScrollY) * (visibleHeight - scrollBarHeight);
ctx.fillStyle = 'rgba(255,255,255,0.2)';
this.roundRect(ctx, this.screenWidth - 6, scrollBarY, 3, scrollBarHeight, 1.5);
ctx.fillStyle = 'rgba(255,255,255,0.3)';
this.roundRect(ctx, this.screenWidth - 8, scrollBarY, 4, scrollBarHeight, 2);
ctx.fill();
// 如果还没滚动到底部,显示滚动提示
if (this.textScrollY < this.maxScrollY - 10 && !this.isTyping) {
ctx.fillStyle = 'rgba(255,255,255,0.5)';
ctx.font = '12px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('↑ 上滑查看更多 ↑', this.screenWidth / 2, this.screenHeight - 25);
}
}
// 打字机光标
@@ -496,13 +523,15 @@ export default class StoryScene extends BaseScene {
const touch = e.touches[0];
// 滑动对话框内容
if (this.isDragging && this.maxScrollY > 0) {
if (this.isDragging) {
const deltaY = this.lastTouchY - touch.clientY;
if (Math.abs(deltaY) > 2) {
this.hasMoved = true;
}
this.textScrollY += deltaY;
this.textScrollY = Math.max(0, Math.min(this.textScrollY, this.maxScrollY));
if (this.maxScrollY > 0) {
this.textScrollY += deltaY;
this.textScrollY = Math.max(0, Math.min(this.textScrollY, this.maxScrollY));
}
this.lastTouchY = touch.clientY;
}
}
@@ -525,6 +554,18 @@ export default class StoryScene extends BaseScene {
return;
}
// AI改写按钮点击
const btnX = this.screenWidth - 70;
const btnY = 18;
const btnW = 55;
const btnH = 26;
if (y >= btnY && y <= btnY + btnH && x >= btnX && x <= btnX + btnW) {
if (!this.isAIRewriting) {
this.showAIRewriteInput();
}
return;
}
// 加速打字
if (this.isTyping) {
this.displayText = this.targetText;
@@ -638,6 +679,71 @@ export default class StoryScene extends BaseScene {
ctx.closePath();
}
/**
* 显示AI改写输入框
*/
showAIRewriteInput() {
wx.showModal({
title: 'AI改写剧情',
editable: true,
placeholderText: '输入你的改写指令,如"让主角暴富"',
success: (res) => {
if (res.confirm && res.content) {
this.doAIRewrite(res.content);
}
}
});
}
/**
* 执行AI改写
*/
async doAIRewrite(prompt) {
if (this.isAIRewriting) return;
this.isAIRewriting = true;
this.main.showLoading('AI正在改写剧情...');
try {
const userId = this.main.userManager.userId || 0;
const newNode = await this.main.storyManager.rewriteBranch(
this.storyId,
prompt,
userId
);
this.main.hideLoading();
if (newNode) {
// 成功获取新分支,开始播放
this.currentNode = newNode;
this.startTypewriter(newNode.content);
wx.showToast({
title: '改写成功!',
icon: 'success',
duration: 1500
});
} else {
// AI 失败,继续原故事
wx.showToast({
title: 'AI暂时不可用继续原故事',
icon: 'none',
duration: 2000
});
}
} catch (error) {
this.main.hideLoading();
console.error('AI改写出错:', error);
wx.showToast({
title: '网络错误,请重试',
icon: 'none',
duration: 2000
});
} finally {
this.isAIRewriting = false;
}
}
destroy() {
if (this.main.userManager.isLoggedIn && this.story) {
this.main.userManager.saveProgress(