diff --git a/apps/jingrow/frontend/src/views/HomePage.vue b/apps/jingrow/frontend/src/views/HomePage.vue index ef947f9..ecde458 100644 --- a/apps/jingrow/frontend/src/views/HomePage.vue +++ b/apps/jingrow/frontend/src/views/HomePage.vue @@ -223,6 +223,60 @@ const isDragging = ref(false) const dragCounter = ref(0) const processing = ref(false) const splitPosition = ref(0) + +// 示例图片用于快速体验 - 使用适合抠图的图片 +const sampleImages = [ + { + id: 'sample-1', + url: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=1024&h=1024&fit=crop&q=80', + name: '人物示例' + }, + { + id: 'sample-2', + url: 'https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?w=1024&h=1024&fit=crop&q=80', + name: '人物示例' + }, + { + id: 'sample-3', + url: 'https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=1024&h=1024&fit=crop&q=80', + name: '产品示例' + }, + { + id: 'sample-4', + url: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=1024&h=1024&fit=crop&q=80', + name: '产品示例' + }, + { + id: 'sample-5', + url: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=1024&h=1024&fit=crop&q=80', + name: '动物示例' + }, + { + id: 'sample-6', + url: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e?w=1024&h=1024&fit=crop&q=80', + name: '物品示例' + }, + { + id: 'sample-7', + url: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=1024&h=1024&fit=crop&q=80', + name: '人物示例' + }, + { + id: 'sample-8', + url: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=1024&h=1024&fit=crop&q=80', + name: '人物示例' + }, + { + id: 'sample-9', + url: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=1024&h=1024&fit=crop&q=80', + name: '人物示例' + }, + { + id: 'sample-10', + url: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=1024&h=1024&fit=crop&q=80', + name: '人物示例' + } +] const comparisonContainerRef = ref(null) const originalImageRef = ref(null) const resultImageRef = ref(null) @@ -324,6 +378,54 @@ const processFile = async (file: File) => { } } +// 处理示例图片点击 +const handleSampleImageClick = async (imageUrl: string) => { + if (processing.value) return + + processing.value = true + + try { + const response = await fetch(imageUrl, { mode: 'cors' }) + if (!response.ok) { + throw new Error(`Failed to load image: ${response.status}`) + } + + const blob = await response.blob() + + // 验证文件类型 + const validTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp'] + if (!validTypes.includes(blob.type)) { + message.warning('不支持的图片格式') + processing.value = false + return + } + + // 验证文件大小 + const maxSize = 10 * 1024 * 1024 + if (blob.size > maxSize) { + message.warning('图片大小超过 10MB 限制') + processing.value = false + return + } + + // 转换为File对象 + const file = new File([blob], 'sample-image.jpg', { type: blob.type }) + await processFile(file) + } catch (error: any) { + console.error('加载示例图片失败:', error) + let errorMessage = '加载示例图片失败' + + if (error.message?.includes('CORS')) { + errorMessage = '图片服务器不允许跨域访问' + } else if (error.message?.includes('Failed to load')) { + errorMessage = '加载图片失败,请稍后重试' + } + + message.error(errorMessage) + processing.value = false + } +} + const handleRemoveBackground = async () => { if (!uploadedImage.value) { message.warning('请先上传图片') @@ -893,6 +995,27 @@ onUnmounted(() => { + + +
+

快速体验

+
+
+
+ +
+ +
+
+
+
+
@@ -1311,6 +1434,122 @@ onUnmounted(() => { min-height: 600px; /* 设置最小高度确保容器足够大 */ } +/* 示例图片区块 */ +.sample-images-section { + margin-top: 24px; + background: white; + border-radius: 12px; + padding: 24px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); + border: 1px solid #e5e7eb; +} + +.sample-images-title { + font-size: 14px; + font-weight: 600; + color: #64748b; + margin: 0 0 16px 0; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.sample-images-container { + display: flex; + gap: 16px; + overflow-x: auto; + overflow-y: hidden; + padding: 0; + padding-bottom: 8px; + justify-content: center; + scrollbar-width: thin; + scrollbar-color: #cbd5e1 transparent; + -webkit-overflow-scrolling: touch; + + &::-webkit-scrollbar { + height: 6px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 3px; + + &:hover { + background: #94a3b8; + } + } +} + +.sample-image-item { + flex-shrink: 0; + width: 100px; + height: 100px; + cursor: pointer; + position: relative; + padding: 4px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + + &:hover { + transform: translateY(-4px); + + .sample-image-overlay { + opacity: 1; + } + } + + &.loading { + pointer-events: none; + opacity: 0.6; + } + +} + +.sample-image-wrapper { + width: 100%; + height: 100%; + position: relative; + background: #f1f5f9; + border: 2px solid #e5e7eb; + border-radius: 8px; + overflow: hidden; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + + img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + } + + .sample-image-item:hover & { + border-color: #1fc76f; + box-shadow: 0 8px 16px rgba(31, 199, 111, 0.2); + } +} + +.sample-image-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(31, 199, 111, 0.9), rgba(13, 104, 75, 0.9)); + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.3s ease; + + .overlay-icon { + font-size: 32px; + color: white; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)); + } +} + .upload-section { flex: 1; display: flex; @@ -1973,6 +2212,25 @@ onUnmounted(() => { padding: 8px 12px; } + .sample-images-section { + padding: 16px; + margin-top: 16px; + } + + .sample-images-title { + font-size: 12px; + margin-bottom: 12px; + } + + .sample-image-item { + width: 100px; + height: 100px; + } + + .sample-image-overlay .overlay-icon { + font-size: 24px; + } + .upload-section { padding: 16px; }