fix: update TemplateCard component by removing unused state and handlers

This commit is contained in:
iHeyTang 2025-09-29 11:42:08 +08:00
parent c714e78ecb
commit 941c143c6b
5 changed files with 27 additions and 137 deletions

View File

@ -12,7 +12,7 @@
"scripts": {
"claude": "claude --dangerously-skip-permissions",
"prepare": "husky",
"dev": "vite",
"dev": "vite --host 0.0.0.0 --port 3000",
"build": "vite build",
"build:check": "tsc && vite build",
"preview": "vite preview",

View File

@ -1,6 +1,5 @@
import { useState, useRef, useMemo } from 'react';
import { useRef, useMemo } from 'react';
import { Template } from '../../store/types';
import { useI18n } from '../../hooks/useI18n';
import './index.css';
interface TemplateCardProps {
@ -9,10 +8,6 @@ interface TemplateCardProps {
}
export default function TemplateCard({ template, onClick }: TemplateCardProps) {
const { t } = useI18n();
const [splitPosition, setSplitPosition] = useState(50); // 分割线位置百分比
const [isDragging, setIsDragging] = useState(false);
const [containerInfo, setContainerInfo] = useState<any>(null);
const containerRef = useRef<any>(null);
const containerId = `container-${template.code}`; // 为每个容器创建唯一ID
@ -21,137 +16,35 @@ export default function TemplateCard({ template, onClick }: TemplateCardProps) {
return /\.(mp4|webm|ogg|mov|avi|mkv|flv)$/i.test(template.outputExampleUrl || '');
}, [template.outputExampleUrl]);
// 检测input是否为视频
const isInputVideo = useMemo(() => {
return /\.(mp4|webm|ogg|mov|avi|mkv|flv)$/i.test(template.inputExampleUrl || ``);
}, [template.inputExampleUrl]);
const handleClick = () => {
if (!isDragging) {
onClick(template);
}
};
// 获取容器信息
const getContainerInfo = () => {
return new Promise(resolve => {
const element = document.getElementById(containerId);
if (element) {
const rect = element.getBoundingClientRect();
setContainerInfo(rect);
resolve(rect);
}
});
};
// 处理触摸开始
const handleTouchStart = async (e: any) => {
e.stopPropagation();
setIsDragging(true);
// 获取容器信息用于后续计算
await getContainerInfo();
};
// 处理触摸移动 - 优化:添加节流,减少计算频率
const handleTouchMove = (e: any) => {
if (!isDragging || !containerInfo) return;
e.stopPropagation();
const touch = e.touches[0];
if (!touch) return;
// 使用requestAnimationFrame节流提升性能
requestAnimationFrame(() => {
// 计算触摸点相对于容器的位置
const touchX = touch.clientX - containerInfo.left;
const percentage = Math.max(10, Math.min(90, (touchX / containerInfo.width) * 100));
setSplitPosition(percentage);
});
};
// 处理触摸结束
const handleTouchEnd = (e: any) => {
e.stopPropagation();
setTimeout(() => setIsDragging(false), 100); // 延迟重置,避免触发点击
onClick(template);
};
return (
<div className="template-card" onClick={handleClick}>
{/* 根据output类型显示不同的内容 */}
{isOutputVideo ? (
// 当output是视频时只显示单个视频
<div className="single-video-container">
<img className="video-poster" src={template.inputExampleUrl || ``} alt="poster" />
<video className="single-video" src={template.outputExampleUrl || ``} autoPlay muted loop style={{ objectFit: 'cover' }} controls={false} />
{/* 模板名称悬浮 - 视频底部 */}
{/* <div className="name-overlay">
<span className="name-badge">{template.name}</span>
</div> */}
<video
className="single-video"
src={template.outputExampleUrl || ``}
autoPlay
muted
loop
playsInline
webkit-playsinline="true"
style={{ objectFit: 'cover' }}
controls={false}
/>
</div>
) : (
<div className="image-comparison">
<div id={containerId} className="merged-image-container" ref={containerRef} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
{/* 效果图层 - 完整图片,通过遮罩显示右半部分 */}
<div id={containerId} className="merged-image-container" ref={containerRef}>
<div className="image-layer overlay-layer">
<img className="full-image" src={template.outputExampleUrl || ``} alt="output" loading="lazy" />
</div>
{/* 模板名称悬浮 - 图片底部 */}
{/* <div className="name-overlay">
<span className="name-badge">{template.name}</span>
</div> */}
</div>
</div>
// 原有的图片对比逻辑
// <div className="image-comparison">
// <div id={containerId} className="merged-image-container" ref={containerRef} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
// {/* 原图层 - 完整图片/视频 */}
// <div className="image-layer">
// {isInputVideo ? (
// <video
// className="full-video"
// src={template.inputExampleUrl || ``}
// autoPlay
// muted
// loop
// style={{ objectFit: 'cover' }}
// controls={false}
// />
// ) : (
// <img className="full-image" src={template.inputExampleUrl || ``} alt="input" loading="lazy" />
// )}
// </div>
// {/* 效果图层 - 完整图片,通过遮罩显示右半部分 */}
// <div
// className="image-layer overlay-layer"
// style={{
// clipPath: `polygon(${splitPosition}% 0%, 100% 0%, 100% 100%, ${splitPosition}% 100%)`,
// }}
// >
// <img className="full-image" src={template.outputExampleUrl || ``} alt="output" loading="lazy" />
// </div>
// {/* 可拖拽的分割线 */}
// <div
// className="split-line"
// style={{ left: `${splitPosition}%` }}
// onTouchStart={handleTouchStart}
// onTouchMove={handleTouchMove}
// onTouchEnd={handleTouchEnd}
// >
// <div className="split-handle">
// <span className="split-icon">⟷</span>
// </div>
// </div>
// {/* 模板名称悬浮 - 图片底部 */}
// <div className="name-overlay">
// <span className="name-badge">✨{template.name}</span>
// </div>
// </div>
// </div>
)}
</div>
);

View File

@ -17,7 +17,6 @@ export default function Home() {
const dispatch = useAppDispatch();
const templates = useAppSelector(selectTemplates);
const serverSdk = useServerSdk();
const [refreshing, setRefreshing] = useState(false);
const loadTemplates = async () => {
try {
@ -30,19 +29,6 @@ export default function Home() {
}
};
// 下拉刷新处理
const handleRefresh = async () => {
setRefreshing(true);
try {
await loadTemplates();
alert(t('home.refreshSuccess'));
} catch (error) {
console.error(t('home.refreshFailed'), error);
} finally {
setRefreshing(false);
}
};
useEffect(() => {
// 需要先检查是否有模板配置文件
loadTemplates();

View File

@ -29,7 +29,16 @@ const SuccessComponent: React.FC<SuccessComponentProps> = ({ task }) => {
<div className="result-container">
{task?.outputUrl ? (
task.outputUrl.includes('.mp4') ? (
<video className="result-video" src={task.outputUrl} controls autoPlay muted loop />
<video
className="result-video"
src={task.outputUrl}
controls
autoPlay
muted
loop
playsInline
webkit-playsinline="true"
/>
) : (
<img className="result-image" src={`https://mixvideo-workflow.bowong.cc/cdn/${encodeURIComponent(task.outputUrl)}`} alt="Generated result" />
)

View File

@ -58,6 +58,8 @@
height: 70vh;
object-fit: contain;
border-radius: 12px;
transform: translateZ(0);
backface-visibility: hidden;
}
/* 底部操作区域 */