refactor: 将结果预览重构为独立页面
- 创建新的pages/result页面用于图片预览 - 修改index页面改用页面跳转替换组件调用 - 通过URL参数传递图片数据 - 在app.config.ts中注册新页面路由 - 删除ImageResultViewer组件,功能迁移至result页面 - 优化页面状态管理,简化index页面逻辑
This commit is contained in:
@@ -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',
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
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 {
|
.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%;
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user