refactor: 将结果预览重构为独立页面

- 创建新的pages/result页面用于图片预览
- 修改index页面改用页面跳转替换组件调用
- 通过URL参数传递图片数据
- 在app.config.ts中注册新页面路由
- 删除ImageResultViewer组件,功能迁移至result页面
- 优化页面状态管理,简化index页面逻辑
This commit is contained in:
imeepos
2025-09-01 18:57:52 +08:00
parent 52b4786459
commit cef1c697a5
5 changed files with 70 additions and 49 deletions

View File

@@ -1,6 +1,7 @@
export default defineAppConfig({ export default defineAppConfig({
pages: [ pages: [
'pages/index/index' 'pages/index/index',
'pages/result/index'
], ],
window: { window: {
backgroundTextStyle: 'light', backgroundTextStyle: 'light',

View File

@@ -1,17 +1,16 @@
import { View } from '@tarojs/components' import { View } from '@tarojs/components'
import { useState } from 'react' import { useState } from 'react'
import { navigateTo } from '@tarojs/taro'
import './index.css' import './index.css'
import { useSdk } from '../../hooks/index' import { useSdk } from '../../hooks/index'
import UploadButton from '../../components/UploadButton' import UploadButton from '../../components/UploadButton'
import LoadingOverlay from '../../components/LoadingOverlay' import LoadingOverlay from '../../components/LoadingOverlay'
import ImageResultViewer from '../../components/ImageResultViewer'
import ErrorOverlay from '../../components/ErrorOverlay' import ErrorOverlay from '../../components/ErrorOverlay'
type PageStep = 'upload' | 'loading' | 'result' | 'error' type PageStep = 'upload' | 'loading' | 'error'
interface AppState { interface AppState {
step: PageStep; step: PageStep;
images: string[];
error: string | null; error: string | null;
} }
@@ -19,7 +18,6 @@ export default function Index() {
const sdk = useSdk() const sdk = useSdk()
const [state, setState] = useState<AppState>({ const [state, setState] = useState<AppState>({
step: 'upload', step: 'upload',
images: [],
error: null error: null
}) })
@@ -29,7 +27,7 @@ export default function Index() {
const task_id = await sdk.chooseAndGenerateImage({ const task_id = await sdk.chooseAndGenerateImage({
onImageSelected: () => { onImageSelected: () => {
// 选择图片完成后立即显示loading // 选择图片完成后立即显示loading
setState({ step: 'loading', images: [], error: null }) setState({ step: 'loading', error: null })
} }
}) })
@@ -37,15 +35,21 @@ export default function Index() {
await new Promise((resolve) => setTimeout(resolve, 5000)) await new Promise((resolve) => setTimeout(resolve, 5000))
const urls = await sdk.getTaskStatus(task_id) const urls = await sdk.getTaskStatus(task_id)
setState({ step: 'result', images: urls, error: null }) // 跳转到结果页面
navigateTo({
url: `/pages/result/index?images=${encodeURIComponent(JSON.stringify(urls))}`
})
// 重置状态
setState({ step: 'upload', error: null })
} catch (error) { } catch (error) {
const errorMsg = error instanceof Error ? error.message : '生成失败' const errorMsg = error instanceof Error ? error.message : '生成失败'
setState({ step: 'error', images: [], error: errorMsg }) setState({ step: 'error', error: errorMsg })
} }
} }
const resetToUpload = () => { const resetToUpload = () => {
setState({ step: 'upload', images: [], error: null }) setState({ step: 'upload', error: null })
} }
const renderCurrentStep = () => { const renderCurrentStep = () => {
@@ -54,8 +58,6 @@ export default function Index() {
return <UploadButton onUpload={chooseAndGenerateImage} /> return <UploadButton onUpload={chooseAndGenerateImage} />
case 'loading': case 'loading':
return <LoadingOverlay /> return <LoadingOverlay />
case 'result':
return <ImageResultViewer images={state.images} onClose={resetToUpload} />
case 'error': case 'error':
return <ErrorOverlay onRetry={resetToUpload} /> return <ErrorOverlay onRetry={resetToUpload} />
default: default:

View File

@@ -0,0 +1,8 @@
export default definePageConfig({
navigationBarTitleText: '图片预览',
navigationBarBackgroundColor: '#2c3e50',
navigationBarTextStyle: 'white',
backgroundColorTop: '#2c3e50',
backgroundColorBottom: '#34495e',
backgroundColor: '#2c3e50'
})

View File

@@ -1,16 +1,12 @@
.fullscreen-container { .result-page {
position: fixed;
top: 0;
left: 0;
width: 100%; width: 100%;
height: 100%; height: 100vh;
background: black; background: black;
z-index: 999;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.fullscreen-header { .result-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@@ -25,7 +21,7 @@
border-bottom: 2rpx solid rgba(255, 255, 255, 0.1); border-bottom: 2rpx solid rgba(255, 255, 255, 0.1);
} }
.fullscreen-title { .result-title {
font-size: 36rpx; font-size: 36rpx;
font-weight: bold; font-weight: bold;
} }
@@ -42,7 +38,7 @@
text-align: center; text-align: center;
} }
.fullscreen-image-container { .result-image-container {
flex: 1; flex: 1;
width: 100%; width: 100%;
position: relative; position: relative;
@@ -80,7 +76,7 @@
z-index: 1; z-index: 1;
} }
.fullscreen-image { .result-image {
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
width: 100%; width: 100%;

View File

@@ -1,16 +1,13 @@
import { View, Text, Button, Image } from '@tarojs/components' import { View, Image } from '@tarojs/components'
import { memo } from 'react' import { memo, useEffect, useState } from 'react'
import { saveImageToPhotosAlbum, downloadFile, showToast } from '@tarojs/taro' import { saveImageToPhotosAlbum, downloadFile, showToast, navigateBack, getCurrentInstance } from '@tarojs/taro'
import { useAd } from '../../hooks/useAd' import { useAd } from '../../hooks/useAd'
import DownloadSection from '../DownloadSection' import DownloadSection from '../../components/DownloadSection'
import './index.css' import './index.css'
interface ImageResultViewerProps { const ResultPage: React.FC = memo(() => {
images: string[] const [images, setImages] = useState<string[]>([])
onClose: () => void
}
const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onClose }) => {
// 广告激励下载功能 // 广告激励下载功能
const { loading: adLoading } = useAd({ const { loading: adLoading } = useAd({
onReward: () => { onReward: () => {
@@ -24,8 +21,36 @@ const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onCl
} }
}) })
useEffect(() => {
// 获取页面参数
const instance = getCurrentInstance()
const params = instance?.router?.params
if (params?.images) {
try {
const imageList = JSON.parse(decodeURIComponent(params.images))
setImages(imageList)
} catch (error) {
console.error('解析图片参数失败:', error)
showToast({
title: '参数错误',
icon: 'error'
})
navigateBack()
}
} else {
showToast({
title: '缺少图片参数',
icon: 'error'
})
navigateBack()
}
}, [])
// 下载图片到本地相册 // 下载图片到本地相册
const handleDownloadImages = async () => { const handleDownloadImages = async () => {
if (!images.length) return
try { try {
showToast({ title: '开始下载...', icon: 'loading' }) showToast({ title: '开始下载...', icon: 'loading' })
@@ -52,25 +77,14 @@ const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onCl
} }
} }
// 触发看广告下载 if (!images.length) {
// const handleWatchAdToDownload = () => { return null
// if (adLoading) { }
// showToast({ title: '广告加载中...', icon: 'loading' })
// return
// }
// showAd()
// }
return ( return (
<View className="fullscreen-container"> <View className="result-page">
<View className="fullscreen-header">
<Text className="fullscreen-title"></Text>
<View className="close-btn" onClick={onClose}>
</View>
</View>
<View <View
className="fullscreen-image-container" className="result-image-container"
style={{ style={{
backgroundImage: `url(${images[0]})`, backgroundImage: `url(${images[0]})`,
backgroundSize: 'cover', backgroundSize: 'cover',
@@ -79,7 +93,7 @@ const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onCl
}} }}
> >
<View className="backdrop-blur"> <View className="backdrop-blur">
<Image className="fullscreen-image" src={images[0]} mode="aspectFit" /> <Image className="result-image" src={images[0]} mode="aspectFit" />
</View> </View>
</View> </View>
<DownloadSection onDownload={handleDownloadImages} loading={adLoading} /> <DownloadSection onDownload={handleDownloadImages} loading={adLoading} />
@@ -87,4 +101,4 @@ const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onCl
) )
}) })
export default ImageResultViewer export default ResultPage