feat: 完善结局页AI改写体验(配额检查/加载动画/历史记录)

This commit is contained in:
2026-03-05 14:34:19 +08:00
parent ac0accdde6
commit 89b5a3b658

View File

@@ -18,7 +18,16 @@ export default class EndingScene extends BaseScene {
this.rewritePrompt = ''; this.rewritePrompt = '';
this.rewriteTags = ['主角逆袭', '甜蜜HE', '虐心BE', '反转剧情', '意外重逢']; this.rewriteTags = ['主角逆袭', '甜蜜HE', '虐心BE', '反转剧情', '意外重逢'];
this.selectedTag = -1; this.selectedTag = -1;
// 改写历史
this.rewriteHistory = [];
this.currentHistoryIndex = -1;
// 配额信息
this.aiQuota = { daily: 3, used: 0, purchased: 0 };
// 加载状态
this.isRewriting = false;
this.rewriteProgress = 0;
this.initParticles(); this.initParticles();
this.loadQuota();
} }
init() { init() {
@@ -27,6 +36,17 @@ export default class EndingScene extends BaseScene {
}, 1500); }, 1500);
} }
async loadQuota() {
try {
const quota = await this.main.userManager.getAIQuota();
if (quota) {
this.aiQuota = quota;
}
} catch (e) {
console.error('加载配额失败:', e);
}
}
initParticles() { initParticles() {
for (let i = 0; i < 50; i++) { for (let i = 0; i < 50; i++) {
this.particles.push({ this.particles.push({
@@ -228,13 +248,15 @@ export default class EndingScene extends BaseScene {
const buttonHeight = 38; const buttonHeight = 38;
const buttonMargin = 8; const buttonMargin = 8;
const startY = this.screenHeight - 220; const startY = this.screenHeight - 220;
const buttonWidth = (this.screenWidth - padding * 2 - buttonMargin) / 2;
// AI改写按钮突出显示) // AI改写按钮带配额提示)
this.renderGradientButton(ctx, padding, startY, this.screenWidth - padding * 2, buttonHeight, '✨ AI改写结局', ['#a855f7', '#ec4899']); const remaining = this.aiQuota.daily - this.aiQuota.used + this.aiQuota.purchased;
const aiBtnText = remaining > 0 ? '✨ AI改写结局' : '⚠️ 次数不足';
this.renderGradientButton(ctx, padding, startY, this.screenWidth - padding * 2, buttonHeight, aiBtnText, ['#a855f7', '#ec4899']);
// 分享按钮 // 分享按钮
const row2Y = startY + buttonHeight + buttonMargin; const row2Y = startY + buttonHeight + buttonMargin;
const buttonWidth = (this.screenWidth - padding * 2 - buttonMargin) / 2;
this.renderGradientButton(ctx, padding, row2Y, buttonWidth, buttonHeight, '分享结局', ['#ff6b6b', '#ffd700']); this.renderGradientButton(ctx, padding, row2Y, buttonWidth, buttonHeight, '分享结局', ['#ff6b6b', '#ffd700']);
// 章节选择按钮 // 章节选择按钮
@@ -298,12 +320,12 @@ export default class EndingScene extends BaseScene {
renderRewritePanel(ctx) { renderRewritePanel(ctx) {
const padding = 20; const padding = 20;
const panelWidth = this.screenWidth - padding * 2; const panelWidth = this.screenWidth - padding * 2;
const panelHeight = 380; const panelHeight = 450;
const panelX = padding; const panelX = padding;
const panelY = (this.screenHeight - panelHeight) / 2; const panelY = (this.screenHeight - panelHeight) / 2;
// 遮罩层 // 遮罩层
ctx.fillStyle = 'rgba(0, 0, 0, 0.8)'; ctx.fillStyle = 'rgba(0, 0, 0, 0.85)';
ctx.fillRect(0, 0, this.screenWidth, this.screenHeight); ctx.fillRect(0, 0, this.screenWidth, this.screenHeight);
// 面板背景渐变 // 面板背景渐变
@@ -323,15 +345,23 @@ export default class EndingScene extends BaseScene {
this.roundRect(ctx, panelX, panelY, panelWidth, panelHeight, 20); this.roundRect(ctx, panelX, panelY, panelWidth, panelHeight, 20);
ctx.stroke(); ctx.stroke();
// 标题 // 标题
ctx.fillStyle = '#ffffff'; ctx.fillStyle = '#ffffff';
ctx.font = 'bold 18px sans-serif'; ctx.font = 'bold 18px sans-serif';
ctx.textAlign = 'center'; ctx.textAlign = 'center';
ctx.fillText('✨ AI改写结局', this.screenWidth / 2, panelY + 35); ctx.fillText('✨ AI改写结局', this.screenWidth / 2, panelY + 35);
// 配额提示
const remaining = this.aiQuota.daily - this.aiQuota.used + this.aiQuota.purchased;
ctx.fillStyle = remaining > 0 ? 'rgba(255,255,255,0.6)' : 'rgba(255,100,100,0.8)';
ctx.font = '11px sans-serif';
ctx.textAlign = 'right';
ctx.fillText(`剩余次数:${remaining}`, panelX + panelWidth - 15, panelY + 35);
// 副标题 // 副标题
ctx.fillStyle = 'rgba(255,255,255,0.6)'; ctx.fillStyle = 'rgba(255,255,255,0.6)';
ctx.font = '12px sans-serif'; ctx.font = '12px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('输入你想要的剧情走向AI将为你重新创作', this.screenWidth / 2, panelY + 58); ctx.fillText('输入你想要的剧情走向AI将为你重新创作', this.screenWidth / 2, panelY + 58);
// 分隔线 // 分隔线
@@ -641,6 +671,13 @@ export default class EndingScene extends BaseScene {
} }
handleAIRewrite() { handleAIRewrite() {
// 检查配额
const remaining = this.aiQuota.daily - this.aiQuota.used + this.aiQuota.purchased;
if (remaining <= 0) {
this.showQuotaModal();
return;
}
// 显示AI改写面板 // 显示AI改写面板
this.showRewritePanel = true; this.showRewritePanel = true;
this.rewritePrompt = ''; this.rewritePrompt = '';
@@ -701,7 +738,27 @@ export default class EndingScene extends BaseScene {
} }
async callAIRewrite(prompt) { async callAIRewrite(prompt) {
wx.showLoading({ title: 'AI创作中...' }); // 检查配额
const remaining = this.aiQuota.daily - this.aiQuota.used + this.aiQuota.purchased;
if (remaining <= 0) {
this.showQuotaModal();
return;
}
this.isRewriting = true;
this.rewriteProgress = 0;
// 显示加载动画
wx.showLoading({
title: 'AI创作中...',
mask: true
});
// 模拟进度条效果
const progressInterval = setInterval(() => {
this.rewriteProgress += Math.random() * 20;
if (this.rewriteProgress > 90) this.rewriteProgress = 90;
}, 500);
try { try {
const result = await this.main.storyManager.rewriteEnding( const result = await this.main.storyManager.rewriteEnding(
@@ -710,23 +767,73 @@ export default class EndingScene extends BaseScene {
prompt prompt
); );
clearInterval(progressInterval);
this.rewriteProgress = 100;
wx.hideLoading(); wx.hideLoading();
if (result && result.content) { if (result && result.content) {
// 跳转到故事场景播放新内容 // 记录改写历史
this.main.sceneManager.switchScene('story', { this.rewriteHistory.push({
storyId: this.storyId, prompt: prompt,
aiContent: result content: result.content,
timestamp: Date.now()
}); });
this.currentHistoryIndex = this.rewriteHistory.length - 1;
// 扣除配额
this.aiQuota.used += 1;
// 成功提示
wx.showToast({
title: '改写成功!',
icon: 'success',
duration: 1500
});
// 延迟跳转到故事场景播放新内容
setTimeout(() => {
this.main.sceneManager.switchScene('story', {
storyId: this.storyId,
aiContent: result
});
}, 1500);
} else { } else {
wx.showToast({ title: '改写失败,请重试', icon: 'none' }); wx.showToast({ title: '改写失败,请重试', icon: 'none' });
} }
} catch (error) { } catch (error) {
clearInterval(progressInterval);
wx.hideLoading(); wx.hideLoading();
wx.showToast({ title: '网络错误', icon: 'none' }); console.error('改写失败:', error);
wx.showToast({ title: error.message || '网络错误', icon: 'none' });
} finally {
this.isRewriting = false;
this.rewriteProgress = 0;
} }
} }
showQuotaModal() {
wx.showModal({
title: 'AI次数不足',
content: `今日剩余免费次数已用完。\n\n观看广告可获得1次 AI改写机会`,
confirmText: '看广告',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
this.watchAdForQuota();
}
}
});
}
watchAdForQuota() {
// 模拟看广告获得配额
wx.showToast({
title: '获得1次 AI 次数',
icon: 'success'
});
this.aiQuota.purchased += 1;
}
handleReplay() { handleReplay() {
this.main.storyManager.resetStory(); this.main.storyManager.resetStory();
this.main.sceneManager.switchScene('story', { storyId: this.storyId }); this.main.sceneManager.switchScene('story', { storyId: this.storyId });