From 64df42678f624e056f7e8a5fc43b70ea98a78313 Mon Sep 17 00:00:00 2001 From: iHeyTang Date: Thu, 11 Sep 2025 15:24:35 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E9=83=A8=E5=88=86=E7=BB=84=E4=BB=B6=E5=8F=8A=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E4=BC=98=E5=8C=96=E9=A1=B9=E7=9B=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除DownloadSection组件及其相关CSS,简化代码结构 - 在历史页面中添加生成中任务的进度计算和显示功能 - 更新历史页面样式,增强用户体验和视觉效果 - 添加缩略图毛玻璃蒙版和进度指示器,提升信息传达的清晰度 --- src/components/DownloadSection/index.css | 74 ------------- src/components/DownloadSection/index.tsx | 61 ----------- src/pages/history/index.css | 89 ++++++++++++++++ src/pages/history/index.tsx | 100 +++++++++++++----- .../result/components/SuccessComponent.tsx | 14 +-- 5 files changed, 167 insertions(+), 171 deletions(-) delete mode 100644 src/components/DownloadSection/index.css delete mode 100644 src/components/DownloadSection/index.tsx diff --git a/src/components/DownloadSection/index.css b/src/components/DownloadSection/index.css deleted file mode 100644 index cccea7b..0000000 --- a/src/components/DownloadSection/index.css +++ /dev/null @@ -1,74 +0,0 @@ -.download-section { - width: 100%; - text-align: center; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 20px 0 40px; -} - -.download-btn { - width: 80%; - height: 100px; - background: linear-gradient(45deg, #ff6b6b, #ee5a24); - color: white; - border: none; - border-radius: 50px; - font-size: 32px; - font-weight: bold; - margin-bottom: 20px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: opacity 0.2s; -} - -.download-btn:active { - opacity: 0.8; -} - -.download-btn.disabled { - background: #ccc; - color: #666; - cursor: not-allowed; -} - -.download-btn.disabled:active { - opacity: 1; -} - -.download-btn.watched { - background: linear-gradient(45deg, #52c41a, #73d13d); -} - -.download-btn.watched:active { - opacity: 0.8; -} - -.regenerate-btn { - width: 80%; - height: 100px; - background: linear-gradient(45deg, #52c41a, #73d13d); - color: white; - border: none; - border-radius: 50px; - font-size: 32px; - font-weight: bold; - margin-bottom: 20px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: opacity 0.2s; -} - -.regenerate-btn:active { - opacity: 0.8; -} - -.download-tip { - font-size: 24px; - opacity: 0.8; -} diff --git a/src/components/DownloadSection/index.tsx b/src/components/DownloadSection/index.tsx deleted file mode 100644 index 2fb8361..0000000 --- a/src/components/DownloadSection/index.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { View, Text } from '@tarojs/components'; -import './index.css'; - -interface DownloadSectionProps { - onDownload: () => void; - onRegenerate?: () => void; - onImageToVideo?: () => void; - loading: boolean; - hasWatchedAd?: boolean; - adAvailable?: boolean; - showImageToVideo?: boolean; - imageToVideoLoading?: boolean; -} - -const DownloadSection: React.FC = ({ - onDownload, - onRegenerate, - onImageToVideo, - loading, - adAvailable = true, - showImageToVideo = false, - imageToVideoLoading = false, -}) => { - const getButtonText = () => { - if (loading) { - return '广告加载中...'; - } - if (!adAvailable) { - return '📱 免费下载'; - } - return '🎬 看广告下载'; - }; - - const getTipText = () => { - if (!adAvailable) { - return '🎁 已为您跳过广告,可以直接免费下载'; - } - return '观看完整广告即可免费下载所有图片'; - }; - - return ( - - - {getButtonText()} - - {onRegenerate && ( - - 🎨 再来一张 - - )} - {showImageToVideo && onImageToVideo && ( - - {imageToVideoLoading ? '🎬 生成中...' : '🎬 图片生视频'} - - )} - {getTipText()} - - ); -}; - -export default DownloadSection; diff --git a/src/pages/history/index.css b/src/pages/history/index.css index 4529b32..0844529 100644 --- a/src/pages/history/index.css +++ b/src/pages/history/index.css @@ -274,3 +274,92 @@ font-weight: 500; letter-spacing: 0.5px; } + +/* 缩略图毛玻璃蒙版 */ +.thumbnail-overlay { + position: absolute; + inset: 0; + border-radius: 12px; + overflow: hidden; + z-index: 10; + pointer-events: none; +} + +.thumbnail-glassmorphism { + position: absolute; + inset: 0; + background: linear-gradient(135deg, rgb(255 255 255 / 80%) 0%, rgb(255 255 255 / 70%) 50%, rgb(255 255 255 / 85%) 100%); + backdrop-filter: blur(6px); +} + +.thumbnail-progress { + position: relative; + z-index: 2; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.thumbnail-progress-circle { + width: 100px; + height: 100px; + border-radius: 50%; + position: relative; + display: flex; + align-items: center; + justify-content: center; + background: transparent; + animation: pulse 2s ease-in-out infinite; +} + +.thumbnail-progress-fill { + position: absolute; + inset: 0; + border-radius: 50%; + background: conic-gradient(#ff9500 0deg, transparent 0deg); + transition: all 0.3s ease; + mask: radial-gradient(circle at center, transparent 42px, black 45px); +} + +.thumbnail-progress-inner { + width: 90px; + height: 90px; + border-radius: 50%; + background: transparent; + display: flex; + align-items: center; + justify-content: center; + position: relative; + z-index: 2; +} + +.thumbnail-progress-text { + font-size: 28px; + color: #ff9500; + text-shadow: 0 1px 2px rgb(0 0 0 / 20%); +} + +/* 动画效果 */ +@keyframes pulse { + 0%, + 100% { + transform: scale(1); + opacity: 1; + } + + 50% { + transform: scale(1.05); + opacity: 0.8; + } +} + +@keyframes shimmer { + 0% { + background-position: -200px 0; + } + + 100% { + background-position: calc(200px + 100%) 0; + } +} diff --git a/src/pages/history/index.tsx b/src/pages/history/index.tsx index bff7c7d..b6b3608 100644 --- a/src/pages/history/index.tsx +++ b/src/pages/history/index.tsx @@ -10,10 +10,26 @@ export default function History() { const [loading, setLoading] = useState(true); const serverSdk = useServerSdk(); + // 计算生成中任务的进度 + const calculateProgress = (record: any) => { + if (!record?.createdAt || record.status !== 'processing') return 0; + + const createdAt = new Date(record.createdAt).getTime(); + const now = Date.now(); + const elapsedMinutes = (now - createdAt) / (1000 * 60); + + // 根据任务类型确定预计时间 + const isVideo = record.taskType === 'video' || record.outputType === 'video' || record.type === 'video'; + const estimatedTime = isVideo ? 2.5 : 1; // 视频2.5分钟,图片1分钟 + + // 计算进度百分比,最大95% + const calculatedProgress = Math.min((elapsedMinutes / estimatedTime) * 100, 95); + return Math.max(calculatedProgress, 0); + }; + const loadRecords = async () => { try { const logs = await serverSdk.getMineLogs(); - console.log(logs); setRecords(logs || []); } catch (error) { console.error('加载记录失败:', error); @@ -31,6 +47,19 @@ export default function History() { loadRecords(); }, []); + // 定时更新生成中任务的进度 + useEffect(() => { + const hasGeneratingTasks = records.some(record => record.status === 'processing'); + if (!hasGeneratingTasks) return; + + const interval = setInterval(() => { + // 触发重新渲染以更新进度 + setRecords(prevRecords => [...prevRecords]); + }, 1000); + + return () => clearInterval(interval); + }, [records]); + // 下拉刷新 const handleRefresh = async () => { setRefreshing(true); @@ -110,39 +139,52 @@ export default function History() { 开始创作你的第一个作品吧!{'\n'}所有的处理记录都会保存在这里 ) : ( - records.map(record => ( - handleItemClick(record)}> - - {record.status === 'completed' && record.outputResult ? ( - - ) : ( - + records.map(record => { + const progress = calculateProgress(record); + const isGenerating = record.status === 'processing'; + + return ( + handleItemClick(record)}> + + {record.status === 'completed' && record.outputResult ? ( - - )} - - - - - {record.templateName} - - {/* 添加状态指示器 */} - {record.status === 'generating' && ( - - - - - - )} - + ) : ( + + + {/* 生成中状态的缩略图毛玻璃蒙版 */} + {isGenerating && ( + + + + + + + {Math.round(progress)}% + + + + + )} + + )} - - {formatTime(record.createdAt)} + + + {record.templateName} + + + {formatTime(record.createdAt)} + - - )) + ); + }) )} diff --git a/src/pages/result/components/SuccessComponent.tsx b/src/pages/result/components/SuccessComponent.tsx index 5689b7d..90790a6 100644 --- a/src/pages/result/components/SuccessComponent.tsx +++ b/src/pages/result/components/SuccessComponent.tsx @@ -18,7 +18,7 @@ const SuccessComponent: React.FC = ({ task }) => { onClose: isEnded => { if (!isEnded) { showToast({ - title: '请观看完整广告才能下载', + title: '请观看完整广告才能保存', icon: 'none', duration: 2000, }); @@ -48,7 +48,7 @@ const SuccessComponent: React.FC = ({ task }) => { finalExtension = task?.type === 'video' ? 'mp4' : 'jpg'; } - showToast({ title: '下载中...', icon: 'loading', duration: 1000 * 60 }); + showToast({ title: '保存中...', icon: 'loading', duration: 1000 * 60 }); const downloadRes = await downloadFile({ url: mediaUrl, header: { @@ -98,7 +98,7 @@ const SuccessComponent: React.FC = ({ task }) => { } else if (err.errMsg.includes('file')) { errorMsg = '文件格式不支持或已损坏'; } else if (err.errMsg.includes('download')) { - errorMsg = '文件下载失败,请重试'; + errorMsg = '文件保存失败,请重试'; } } } @@ -117,9 +117,9 @@ const SuccessComponent: React.FC = ({ task }) => { return '广告加载中...'; } if (!adAvailable) { - return '免费下载'; + return '免费保存'; } - return '观看广告下载'; + return '观看广告并保存到相册'; }; const getTipText = () => { @@ -127,9 +127,9 @@ const SuccessComponent: React.FC = ({ task }) => { return '正在加载广告...'; } if (!adAvailable) { - return '🎉 恭喜!无需观看广告即可免费下载'; + return '🎉 恭喜!无需观看广告即可免费保存'; } - return '观看完整广告后即可下载到相册'; + return '观看完整广告后即可保存到相册'; }; return (