feat: 完善结局页AI改写体验(配额检查/加载动画/历史记录)
This commit is contained in:
@@ -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 });
|
||||||
|
|||||||
Reference in New Issue
Block a user