bw-mini-app/src/pages/home/index.tsx

203 lines
6.0 KiB
TypeScript

import { View, ScrollView, Canvas } from '@tarojs/components';
import { useEffect, useState } from 'react';
import Taro, { navigateTo } from '@tarojs/taro';
import { useAppDispatch, useAppSelector } from '../../hooks/redux';
import { selectTemplates } from '../../selectors/template';
import { initTemplates } from '../../actions/template';
import { Template } from '../../store/types';
import TemplateCard from '../../components/TemplateCard';
import { useSdk, useServerSdk } from '../../hooks/index';
import { useImageDetectionTaskManager, ImageAuditResult, AuditConclusion } from '../../hooks/useImageDetectionTaskManager';
import './index.css';
// 定义详细的加载状态类型
type LoadingState = false | 'uploading' | 'auditing' | 'processing';
export default function Home() {
const dispatch = useAppDispatch();
const templates = useAppSelector(selectTemplates);
const sdk = useSdk();
const serverSdk = useServerSdk();
const { submitAuditTask } = useImageDetectionTaskManager();
const [refreshing, setRefreshing] = useState(false);
const loadTemplates = async () => {
try {
const templates = await serverSdk.getAllTemplates();
console.log(templates);
dispatch(initTemplates(templates));
} catch (error) {
console.error('加载模板失败:', error);
Taro.showToast({
title: '加载模板失败',
icon: 'error',
duration: 2000,
});
}
};
// 下拉刷新处理
const handleRefresh = async () => {
setRefreshing(true);
try {
await loadTemplates();
Taro.showToast({
title: '刷新成功',
icon: 'success',
duration: 1500,
});
} catch (error) {
console.error('刷新失败:', error);
} finally {
setRefreshing(false);
}
};
useEffect(() => {
// 需要先检查是否有模板配置文件
loadTemplates();
}, [dispatch]);
// 获取加载状态的显示文本
const getLoadingText = (state: LoadingState): string => {
switch (state) {
default:
return '请稍后...';
}
};
// 处理审核失败
const handleAuditFailure = (auditResult: ImageAuditResult) => {
const messages: Record<AuditConclusion, string> = {
[AuditConclusion.REJECT]: '图片内容不符合规范,请重新选择符合规范的图片',
[AuditConclusion.REVIEW]: '图片需要人工审核,请稍后重试或更换其他图片',
[AuditConclusion.UNCERTAIN]: '图片审核结果不确定,请重新选择图片',
[AuditConclusion.PASS]: '图片审核通过', // 虽然不会用到,但为了类型完整性
};
const message = auditResult.conclusion ? messages[auditResult.conclusion] : '图片审核失败,请重新选择图片';
Taro.showModal({
title: '图片审核未通过',
content: message,
confirmText: '我知道了',
showCancel: false,
success: () => {
console.log('用户确认审核失败信息');
},
});
};
const handleTemplateClick = async (template: Template) => {
try {
// 第一步:选择并上传图片
const imageCount = template.templateType === '2image-to-video' ? 2 : 1;
const imageUrl = await sdk.chooseAndUploadImage({
count: imageCount,
onImageSelected: () => {
Taro.showLoading({
title: getLoadingText('uploading'),
mask: true,
});
},
onProgress: () => {
Taro.showLoading({
title: `请稍后...`,
mask: true,
});
},
});
const auditResult = await new Promise<ImageAuditResult>((resolve, reject) => {
submitAuditTask(
{
imageUrl,
options: {
enableCache: true,
timeout: 30000,
},
},
(status, progress) => {
console.log('审核进度:', status, progress);
},
result => {
console.log('审核成功:', result);
resolve(result);
},
error => {
console.error('审核失败:', error);
reject(error);
}
);
});
// 第三步:检查审核结果
if (auditResult.conclusion === AuditConclusion.PASS) {
// 短暂延迟后继续业务处理
await new Promise(resolve => setTimeout(resolve, 1000));
// 第四步:执行业务逻辑
try {
const taskId = await serverSdk.executeTemplate({
imageUrl,
templateCode: template.code,
});
// 隐藏loading
Taro.hideLoading();
// 跳转到生成页面
navigateTo({
url: `/pages/result/index?taskId=${taskId}&templateCode=${template.code}`,
});
} catch (businessError) {
// 业务处理失败
Taro.hideLoading();
Taro.showToast({
title: '请等待生成中的任务完成后再尝试',
icon: 'none',
duration: 2000,
});
}
} else {
// 审核不通过
handleAuditFailure(auditResult);
}
} catch (error: any) {
if (error.errMsg.includes('chooseImage:fail cancel')) {
return;
}
// 统一错误处理
Taro.hideLoading();
Taro.showToast({
title: '图片审核失败,请重试',
icon: 'error',
duration: 2000,
});
} finally {
}
};
return (
<View className="home">
<ScrollView
className="home-scroll"
scrollY
enhanced
showScrollbar={false}
enablePassive
bounces
scrollWithAnimation={false}
refresherEnabled
refresherTriggered={refreshing}
onRefresherRefresh={handleRefresh}
refresherBackground="#f8f9fa"
refresherDefaultStyle="black"
>
<View className="template-grid">
{templates.map(template => (
<TemplateCard key={template.code} template={template} onClick={handleTemplateClick} />
))}
</View>
</ScrollView>
</View>
);
}