feat: 完善结局页AI改写体验(配额检查/加载动画/历史记录)
This commit is contained in:
@@ -18,7 +18,16 @@ export default class EndingScene extends BaseScene {
|
||||
this.rewritePrompt = '';
|
||||
this.rewriteTags = ['主角逆袭', '甜蜜HE', '虐心BE', '反转剧情', '意外重逢'];
|
||||
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.loadQuota();
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -27,6 +36,17 @@ export default class EndingScene extends BaseScene {
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
async loadQuota() {
|
||||
try {
|
||||
const quota = await this.main.userManager.getAIQuota();
|
||||
if (quota) {
|
||||
this.aiQuota = quota;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载配额失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
initParticles() {
|
||||
for (let i = 0; i < 50; i++) {
|
||||
this.particles.push({
|
||||
@@ -228,13 +248,15 @@ export default class EndingScene extends BaseScene {
|
||||
const buttonHeight = 38;
|
||||
const buttonMargin = 8;
|
||||
const startY = this.screenHeight - 220;
|
||||
const buttonWidth = (this.screenWidth - padding * 2 - buttonMargin) / 2;
|
||||
|
||||
// AI改写按钮(突出显示)
|
||||
this.renderGradientButton(ctx, padding, startY, this.screenWidth - padding * 2, buttonHeight, '✨ AI改写结局', ['#a855f7', '#ec4899']);
|
||||
// AI改写按钮(带配额提示)
|
||||
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 buttonWidth = (this.screenWidth - padding * 2 - buttonMargin) / 2;
|
||||
this.renderGradientButton(ctx, padding, row2Y, buttonWidth, buttonHeight, '分享结局', ['#ff6b6b', '#ffd700']);
|
||||
|
||||
// 章节选择按钮
|
||||
@@ -298,12 +320,12 @@ export default class EndingScene extends BaseScene {
|
||||
renderRewritePanel(ctx) {
|
||||
const padding = 20;
|
||||
const panelWidth = this.screenWidth - padding * 2;
|
||||
const panelHeight = 380;
|
||||
const panelHeight = 450;
|
||||
const panelX = padding;
|
||||
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);
|
||||
|
||||
// 面板背景渐变
|
||||
@@ -323,15 +345,23 @@ export default class EndingScene extends BaseScene {
|
||||
this.roundRect(ctx, panelX, panelY, panelWidth, panelHeight, 20);
|
||||
ctx.stroke();
|
||||
|
||||
// 标题
|
||||
// 标题栏
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.font = 'bold 18px sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
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.font = '12px sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText('输入你想要的剧情走向,AI将为你重新创作', this.screenWidth / 2, panelY + 58);
|
||||
|
||||
// 分隔线
|
||||
@@ -641,6 +671,13 @@ export default class EndingScene extends BaseScene {
|
||||
}
|
||||
|
||||
handleAIRewrite() {
|
||||
// 检查配额
|
||||
const remaining = this.aiQuota.daily - this.aiQuota.used + this.aiQuota.purchased;
|
||||
if (remaining <= 0) {
|
||||
this.showQuotaModal();
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示AI改写面板
|
||||
this.showRewritePanel = true;
|
||||
this.rewritePrompt = '';
|
||||
@@ -701,7 +738,27 @@ export default class EndingScene extends BaseScene {
|
||||
}
|
||||
|
||||
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 {
|
||||
const result = await this.main.storyManager.rewriteEnding(
|
||||
@@ -710,23 +767,73 @@ export default class EndingScene extends BaseScene {
|
||||
prompt
|
||||
);
|
||||
|
||||
clearInterval(progressInterval);
|
||||
this.rewriteProgress = 100;
|
||||
wx.hideLoading();
|
||||
|
||||
if (result && result.content) {
|
||||
// 跳转到故事场景播放新内容
|
||||
this.main.sceneManager.switchScene('story', {
|
||||
storyId: this.storyId,
|
||||
aiContent: result
|
||||
// 记录改写历史
|
||||
this.rewriteHistory.push({
|
||||
prompt: prompt,
|
||||
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 {
|
||||
wx.showToast({ title: '改写失败,请重试', icon: 'none' });
|
||||
}
|
||||
} catch (error) {
|
||||
clearInterval(progressInterval);
|
||||
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() {
|
||||
this.main.storyManager.resetStory();
|
||||
this.main.sceneManager.switchScene('story', { storyId: this.storyId });
|
||||
|
||||
Reference in New Issue
Block a user