|
|
@@ -1,7 +1,17 @@
|
|
|
import { useEffect, useRef, useState, type TouchEvent } from 'react';
|
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
-import { setStorage, STORAGE_KEYS, getUserId, getVisitedRoutes } from '@/utils/storage';
|
|
|
-import { updateUserUIState } from '@/utils/api';
|
|
|
+import { message } from 'antd';
|
|
|
+import {
|
|
|
+ setStorage,
|
|
|
+ STORAGE_KEYS,
|
|
|
+ getUserId,
|
|
|
+ getVisitedRoutes,
|
|
|
+ setCurrentBackgroundImageId,
|
|
|
+ setCurrentBackgroundImageUrl,
|
|
|
+ syncBackgroundImageToStorage,
|
|
|
+ setHasSharedAvatar,
|
|
|
+} from '@/utils/storage';
|
|
|
+import { updateUserUIState, claimShareReward } from '@/utils/api';
|
|
|
import { px2vmin, px2vw } from '@/utils/viewport';
|
|
|
import { getOssUrl } from '@/utils/oss';
|
|
|
|
|
|
@@ -13,7 +23,7 @@ const closeBtn = getOssUrl('close-btn.png');
|
|
|
// const wechatIcon = getOssUrl('wechat.png'); // 已注释,未使用
|
|
|
// const qqIcon = getOssUrl('QQ.png'); // 已注释,未使用
|
|
|
// const saveIcon = getOssUrl('save.png'); // 已注释,未使用
|
|
|
-const saveBtnImage = getOssUrl('Save-btn.png');
|
|
|
+const saveBtnImage = 'https://lyrria-pro.oss-cn-beijing.aliyuncs.com/share-done-claim-gift.png';
|
|
|
import { shareImages as fallbackShareImages } from '@/data/shareImages';
|
|
|
import { getShareImages, type ShareImageItem } from '@/utils/api';
|
|
|
|
|
|
@@ -75,97 +85,62 @@ export const FirstLoginRewardPage = () => {
|
|
|
setActiveShareIndex(0);
|
|
|
};
|
|
|
|
|
|
- // 保存所有图片到相册
|
|
|
+ // 领取分享奖励
|
|
|
const handleSaveImage = async () => {
|
|
|
try {
|
|
|
- if (!shareImages.length) {
|
|
|
+ const userId = getUserId();
|
|
|
+ if (!userId) {
|
|
|
+ message.error('用户未登录,请先登录');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 遍历所有分享图片,逐个下载
|
|
|
- for (let i = 0; i < shareImages.length; i++) {
|
|
|
- const imageUrl = shareImages[i]?.url;
|
|
|
- if (!imageUrl) {
|
|
|
- continue;
|
|
|
+ message.loading('正在领取分享奖励...', 0);
|
|
|
+
|
|
|
+ // 调用分享奖励接口
|
|
|
+ const result = await claimShareReward(userId);
|
|
|
+ message.destroy();
|
|
|
+
|
|
|
+ if (result.success && result.data) {
|
|
|
+ // 显式更新 localStorage 中的背景图片相关变量
|
|
|
+ const backgroundImageId = result.data.background_image_id || 'happynewyear';
|
|
|
+ const backgroundImageMetadata = result.data.background_image_metadata || { opacity: 0.5 };
|
|
|
+
|
|
|
+ // 同步背景图片到 localStorage(包括 ID、URL 和 metadata)
|
|
|
+ syncBackgroundImageToStorage(backgroundImageId, backgroundImageMetadata);
|
|
|
+
|
|
|
+ // 确保背景图片 ID 和 URL 都已更新
|
|
|
+ setCurrentBackgroundImageId(backgroundImageId);
|
|
|
+
|
|
|
+ // 获取背景图片 URL(从映射中获取)
|
|
|
+ const { getBackgroundImageUrlById } = await import('@/utils/storage');
|
|
|
+ const backgroundImageUrl = getBackgroundImageUrlById(backgroundImageId);
|
|
|
+ if (backgroundImageUrl) {
|
|
|
+ setCurrentBackgroundImageUrl(backgroundImageUrl);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ // 更新分享头像状态:更新 localStorage 和数据库
|
|
|
+ setHasSharedAvatar(true);
|
|
|
try {
|
|
|
- // 加载图片
|
|
|
- const img = new Image();
|
|
|
- img.crossOrigin = 'anonymous';
|
|
|
-
|
|
|
- await new Promise((resolve, reject) => {
|
|
|
- img.onload = resolve;
|
|
|
- img.onerror = reject;
|
|
|
- img.src = imageUrl;
|
|
|
- });
|
|
|
-
|
|
|
- // 创建 canvas 并绘制图片
|
|
|
- const canvas = document.createElement('canvas');
|
|
|
- const ctx = canvas.getContext('2d');
|
|
|
- if (!ctx) {
|
|
|
- console.error(`无法创建画布 (图片 ${i + 1})`);
|
|
|
- // 如果 Canvas 失败,尝试直接下载
|
|
|
- const link = document.createElement('a');
|
|
|
- link.href = imageUrl;
|
|
|
- link.download = `lyrria-share-${i + 1}-${Date.now()}.png`;
|
|
|
- document.body.appendChild(link);
|
|
|
- link.click();
|
|
|
- document.body.removeChild(link);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- canvas.width = img.naturalWidth || img.width;
|
|
|
- canvas.height = img.naturalHeight || img.height;
|
|
|
- ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
|
-
|
|
|
- // 转换为 blob 并下载
|
|
|
- await new Promise<void>((resolve) => {
|
|
|
- canvas.toBlob((blob) => {
|
|
|
- if (blob) {
|
|
|
- const url = URL.createObjectURL(blob);
|
|
|
- const link = document.createElement('a');
|
|
|
- link.href = url;
|
|
|
- link.download = `lyrria-share-${i + 1}-${Date.now()}.png`;
|
|
|
- document.body.appendChild(link);
|
|
|
- link.click();
|
|
|
- document.body.removeChild(link);
|
|
|
- URL.revokeObjectURL(url);
|
|
|
- } else {
|
|
|
- // 如果 blob 转换失败,尝试直接下载
|
|
|
- const link = document.createElement('a');
|
|
|
- link.href = imageUrl;
|
|
|
- link.download = `lyrria-share-${i + 1}-${Date.now()}.png`;
|
|
|
- document.body.appendChild(link);
|
|
|
- link.click();
|
|
|
- document.body.removeChild(link);
|
|
|
- }
|
|
|
- // 添加延迟,避免浏览器阻止多个下载
|
|
|
- setTimeout(resolve, 300);
|
|
|
- }, 'image/png');
|
|
|
+ await updateUserUIState(userId, {
|
|
|
+ has_shared_avatar: true,
|
|
|
});
|
|
|
} catch (error) {
|
|
|
- console.error(`保存图片 ${i + 1} 失败:`, error);
|
|
|
- // 备用方案:直接下载图片
|
|
|
- try {
|
|
|
- const link = document.createElement('a');
|
|
|
- link.href = imageUrl;
|
|
|
- link.download = `lyrria-share-${i + 1}-${Date.now()}.png`;
|
|
|
- document.body.appendChild(link);
|
|
|
- link.click();
|
|
|
- document.body.removeChild(link);
|
|
|
- // 添加延迟
|
|
|
- await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
- } catch (fallbackError) {
|
|
|
- console.error(`备用保存方案也失败 (图片 ${i + 1}):`, fallbackError);
|
|
|
- }
|
|
|
+ console.error('同步分享头像状态到数据库失败:', error);
|
|
|
+ // 即使同步失败,localStorage 已更新,不影响主流程
|
|
|
}
|
|
|
+
|
|
|
+ message.success('分享奖励已领取!新年背景已解锁');
|
|
|
+ // 跳转到分享成功页面
|
|
|
+ setTimeout(() => {
|
|
|
+ navigate('/share-success');
|
|
|
+ }, 1000);
|
|
|
+ } else {
|
|
|
+ message.error(result.message || '领取分享奖励失败,请重试');
|
|
|
}
|
|
|
-
|
|
|
- // 所有图片保存成功后跳转到 ShareSuccessPage
|
|
|
- navigate('/share-success');
|
|
|
} catch (error) {
|
|
|
- console.error('保存图片过程出错:', error);
|
|
|
+ console.error('领取分享奖励失败:', error);
|
|
|
+ message.destroy();
|
|
|
+ message.error('领取分享奖励失败,请重试');
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -351,8 +326,8 @@ export const FirstLoginRewardPage = () => {
|
|
|
position: 'absolute',
|
|
|
top: px2vmin(62),
|
|
|
right: `calc((100% - ${px2vmin(311)}) / 2 - ${px2vmin(5)})`,
|
|
|
- width: px2vmin(42),
|
|
|
- height: px2vmin(42),
|
|
|
+ width: px2vmin(30),
|
|
|
+ height: px2vmin(30),
|
|
|
padding: 0,
|
|
|
border: 'none',
|
|
|
background: 'none',
|
|
|
@@ -427,7 +402,6 @@ export const FirstLoginRewardPage = () => {
|
|
|
<img
|
|
|
src={shareImages[activeShareIndex]?.url}
|
|
|
alt="Share preview"
|
|
|
- onClick={handleShareClose}
|
|
|
style={{
|
|
|
width: '100%',
|
|
|
height: 'auto',
|
|
|
@@ -478,30 +452,55 @@ export const FirstLoginRewardPage = () => {
|
|
|
|
|
|
{/* 保存按钮 */}
|
|
|
{shareImages.length > 0 && (
|
|
|
- <button
|
|
|
- type="button"
|
|
|
- onClick={handleSaveImage}
|
|
|
+ <div
|
|
|
style={{
|
|
|
position: 'absolute',
|
|
|
left: '50%',
|
|
|
top: px2vmin(670),
|
|
|
transform: 'translateX(-50%)',
|
|
|
- border: 'none',
|
|
|
- padding: 0,
|
|
|
- background: 'none',
|
|
|
- width: px2vmin(116),
|
|
|
- cursor: 'pointer',
|
|
|
+ width: px2vmin(211),
|
|
|
+ display: 'flex',
|
|
|
+ flexDirection: 'column',
|
|
|
+ alignItems: 'center',
|
|
|
}}
|
|
|
>
|
|
|
- <img
|
|
|
- src={saveBtnImage}
|
|
|
- alt="Save"
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ onClick={handleSaveImage}
|
|
|
style={{
|
|
|
+ border: 'none',
|
|
|
+ padding: 0,
|
|
|
+ background: 'none',
|
|
|
width: '100%',
|
|
|
- display: 'block',
|
|
|
+ cursor: 'pointer',
|
|
|
}}
|
|
|
- />
|
|
|
- </button>
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ src={saveBtnImage}
|
|
|
+ alt="Save"
|
|
|
+ style={{
|
|
|
+ width: '100%',
|
|
|
+ display: 'block',
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </button>
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ marginTop: px2vmin(12),
|
|
|
+ width: px2vmin(311),
|
|
|
+ color: '#FFFFFF',
|
|
|
+ fontSize: px2vmin(12),
|
|
|
+ textAlign: 'center',
|
|
|
+ lineHeight: px2vmin(14),
|
|
|
+ wordWrap: 'break-word',
|
|
|
+ overflowWrap: 'break-word',
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 长按保存精彩图片,或使用浏览器分享,邀请好友一起加入学习旅程!
|
|
|
+ <br />
|
|
|
+ Long-press to save the image or share via your browser. Invite friends to join your learning journey!
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
)}
|
|
|
|
|
|
{/* 底部分享按钮区域 - 已注释 */}
|