refactor: 将结果预览重构为独立页面
- 创建新的pages/result页面用于图片预览 - 修改index页面改用页面跳转替换组件调用 - 通过URL参数传递图片数据 - 在app.config.ts中注册新页面路由 - 删除ImageResultViewer组件,功能迁移至result页面 - 优化页面状态管理,简化index页面逻辑
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
export default defineAppConfig({
|
||||
pages: [
|
||||
'pages/index/index'
|
||||
'pages/index/index',
|
||||
'pages/result/index'
|
||||
],
|
||||
window: {
|
||||
backgroundTextStyle: 'light',
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { View } from '@tarojs/components'
|
||||
import { useState } from 'react'
|
||||
import { navigateTo } from '@tarojs/taro'
|
||||
import './index.css'
|
||||
import { useSdk } from '../../hooks/index'
|
||||
import UploadButton from '../../components/UploadButton'
|
||||
import LoadingOverlay from '../../components/LoadingOverlay'
|
||||
import ImageResultViewer from '../../components/ImageResultViewer'
|
||||
import ErrorOverlay from '../../components/ErrorOverlay'
|
||||
|
||||
type PageStep = 'upload' | 'loading' | 'result' | 'error'
|
||||
type PageStep = 'upload' | 'loading' | 'error'
|
||||
|
||||
interface AppState {
|
||||
step: PageStep;
|
||||
images: string[];
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
@@ -19,7 +18,6 @@ export default function Index() {
|
||||
const sdk = useSdk()
|
||||
const [state, setState] = useState<AppState>({
|
||||
step: 'upload',
|
||||
images: [],
|
||||
error: null
|
||||
})
|
||||
|
||||
@@ -29,7 +27,7 @@ export default function Index() {
|
||||
const task_id = await sdk.chooseAndGenerateImage({
|
||||
onImageSelected: () => {
|
||||
// 选择图片完成后立即显示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))
|
||||
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) {
|
||||
const errorMsg = error instanceof Error ? error.message : '生成失败'
|
||||
setState({ step: 'error', images: [], error: errorMsg })
|
||||
setState({ step: 'error', error: errorMsg })
|
||||
}
|
||||
}
|
||||
|
||||
const resetToUpload = () => {
|
||||
setState({ step: 'upload', images: [], error: null })
|
||||
setState({ step: 'upload', error: null })
|
||||
}
|
||||
|
||||
const renderCurrentStep = () => {
|
||||
@@ -54,8 +58,6 @@ export default function Index() {
|
||||
return <UploadButton onUpload={chooseAndGenerateImage} />
|
||||
case 'loading':
|
||||
return <LoadingOverlay />
|
||||
case 'result':
|
||||
return <ImageResultViewer images={state.images} onClose={resetToUpload} />
|
||||
case 'error':
|
||||
return <ErrorOverlay onRetry={resetToUpload} />
|
||||
default:
|
||||
|
||||
8
src/pages/result/index.config.ts
Normal file
8
src/pages/result/index.config.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '图片预览',
|
||||
navigationBarBackgroundColor: '#2c3e50',
|
||||
navigationBarTextStyle: 'white',
|
||||
backgroundColorTop: '#2c3e50',
|
||||
backgroundColorBottom: '#34495e',
|
||||
backgroundColor: '#2c3e50'
|
||||
})
|
||||
@@ -1,16 +1,12 @@
|
||||
.fullscreen-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
.result-page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: 100vh;
|
||||
background: black;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.fullscreen-header {
|
||||
.result-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@@ -25,7 +21,7 @@
|
||||
border-bottom: 2rpx solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.fullscreen-title {
|
||||
.result-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -42,7 +38,7 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fullscreen-image-container {
|
||||
.result-image-container {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
@@ -80,7 +76,7 @@
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.fullscreen-image {
|
||||
.result-image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
@@ -1,16 +1,13 @@
|
||||
import { View, Text, Button, Image } from '@tarojs/components'
|
||||
import { memo } from 'react'
|
||||
import { saveImageToPhotosAlbum, downloadFile, showToast } from '@tarojs/taro'
|
||||
import { View, Image } from '@tarojs/components'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
import { saveImageToPhotosAlbum, downloadFile, showToast, navigateBack, getCurrentInstance } from '@tarojs/taro'
|
||||
import { useAd } from '../../hooks/useAd'
|
||||
import DownloadSection from '../DownloadSection'
|
||||
import DownloadSection from '../../components/DownloadSection'
|
||||
import './index.css'
|
||||
|
||||
interface ImageResultViewerProps {
|
||||
images: string[]
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onClose }) => {
|
||||
const ResultPage: React.FC = memo(() => {
|
||||
const [images, setImages] = useState<string[]>([])
|
||||
|
||||
// 广告激励下载功能
|
||||
const { loading: adLoading } = useAd({
|
||||
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 () => {
|
||||
if (!images.length) return
|
||||
|
||||
try {
|
||||
showToast({ title: '开始下载...', icon: 'loading' })
|
||||
|
||||
@@ -52,25 +77,14 @@ const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onCl
|
||||
}
|
||||
}
|
||||
|
||||
// 触发看广告下载
|
||||
// const handleWatchAdToDownload = () => {
|
||||
// if (adLoading) {
|
||||
// showToast({ title: '广告加载中...', icon: 'loading' })
|
||||
// return
|
||||
// }
|
||||
// showAd()
|
||||
// }
|
||||
if (!images.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<View className="fullscreen-container">
|
||||
<View className="fullscreen-header">
|
||||
<Text className="fullscreen-title">图片预览</Text>
|
||||
<View className="close-btn" onClick={onClose}>
|
||||
✕
|
||||
</View>
|
||||
</View>
|
||||
<View className="result-page">
|
||||
<View
|
||||
className="fullscreen-image-container"
|
||||
className="result-image-container"
|
||||
style={{
|
||||
backgroundImage: `url(${images[0]})`,
|
||||
backgroundSize: 'cover',
|
||||
@@ -79,7 +93,7 @@ const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onCl
|
||||
}}
|
||||
>
|
||||
<View className="backdrop-blur">
|
||||
<Image className="fullscreen-image" src={images[0]} mode="aspectFit" />
|
||||
<Image className="result-image" src={images[0]} mode="aspectFit" />
|
||||
</View>
|
||||
</View>
|
||||
<DownloadSection onDownload={handleDownloadImages} loading={adLoading} />
|
||||
@@ -87,4 +101,4 @@ const ImageResultViewer: React.FC<ImageResultViewerProps> = memo(({ images, onCl
|
||||
)
|
||||
})
|
||||
|
||||
export default ImageResultViewer
|
||||
export default ResultPage
|
||||
Reference in New Issue
Block a user