Files
agent/index.html

2134 lines
90 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Agent 设计工作流 - 奶茶快闪店</title>
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background: linear-gradient(135deg, #0f0f14 0%, #1a1825 25%, #252538 50%, #1a1825 75%, #0f0f14 100%);
min-height: 100vh;
position: relative;
overflow: hidden;
}
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
radial-gradient(circle at 20% 50%, rgba(120, 119, 198, 0.12) 0%, transparent 40%),
radial-gradient(circle at 80% 80%, rgba(255, 119, 168, 0.08) 0%, transparent 40%),
radial-gradient(circle at 40% 20%, rgba(100, 220, 255, 0.1) 0%, transparent 40%),
radial-gradient(circle at 70% 40%, rgba(162, 155, 254, 0.08) 0%, transparent 40%);
z-index: 0;
animation: dataFlow 30s ease-in-out infinite;
}
@keyframes dataFlow {
0%, 100% {
transform: scale(1) rotate(0deg);
opacity: 0.7;
}
25% {
transform: scale(1.05) rotate(0.5deg);
opacity: 0.85;
}
50% {
transform: scale(1.08) rotate(-0.5deg);
opacity: 1;
}
75% {
transform: scale(1.03) rotate(0.3deg);
opacity: 0.9;
}
}
/* 细微点阵网格 */
body::after {
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(circle at center, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
background-size: 30px 30px;
animation: gridPulse 20s ease-in-out infinite;
z-index: 1;
pointer-events: none;
}
@keyframes gridPulse {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.6; }
}
/* 移除原有的cyber-grid、scan-line、matrix-rain等过于强烈的效果 */
.cyber-grid,
.scan-line,
.matrix-rain {
display: none;
}
@keyframes matrixFall {
0% {
transform: translateY(-100vh);
opacity: 0;
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
transform: translateY(100vh);
opacity: 0;
}
}
.floating-orb {
position: fixed;
border-radius: 50%;
filter: blur(40px);
opacity: 0.6;
animation: float 20s infinite ease-in-out;
z-index: 0;
}
.orb-1 {
width: 300px;
height: 300px;
background: linear-gradient(135deg, #ffd89b 0%, #ff6b9d 100%);
top: -100px;
left: -100px;
animation-delay: 0s;
}
.orb-2 {
width: 200px;
height: 200px;
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
bottom: -50px;
right: -50px;
animation-delay: 5s;
}
.orb-3 {
width: 250px;
height: 250px;
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
top: 50%;
left: 50%;
animation-delay: 10s;
}
@keyframes float {
0%, 100% { transform: translate(0, 0) scale(1); }
33% { transform: translate(30px, -30px) scale(1.1); }
66% { transform: translate(-20px, 20px) scale(0.9); }
}
#root {
width: 100%;
height: 100vh;
position: relative;
z-index: 1;
}
.app-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.02);
position: relative;
}
/* 数字粒子效果 */
.digital-particles {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 2;
}
.particle {
position: absolute;
width: 2px;
height: 2px;
background: rgba(162, 155, 254, 0.6);
border-radius: 50%;
box-shadow:
0 0 6px rgba(162, 155, 254, 0.3),
0 0 12px rgba(162, 155, 254, 0.2);
animation: float 20s infinite ease-in-out;
}
@keyframes float {
0%, 100% {
transform: translateY(0) translateX(0);
opacity: 0;
}
10% {
opacity: 0.8;
}
50% {
transform: translateY(-30px) translateX(20px);
opacity: 0.3;
}
90% {
opacity: 0.8;
}
}
/* 数据流线条 */
.data-lines {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
z-index: 1;
}
.data-line {
animation: dataFlow 10s infinite ease-in-out;
}
@keyframes dataFlow {
0%, 100% {
stroke-dasharray: 0 100%;
}
50% {
stroke-dasharray: 100% 0;
}
}
.header {
padding: 30px 40px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(20px);
}
.title {
display: flex;
align-items: center;
gap: 15px;
font-size: 1.8rem;
font-weight: 700;
color: white;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.title span:first-child {
font-size: 2.2rem;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.view-toggle {
display: flex;
background: rgba(255, 255, 255, 0.1);
border-radius: 50px;
padding: 4px;
backdrop-filter: blur(10px);
}
.toggle-btn {
padding: 12px 24px;
border: none;
background: transparent;
color: rgba(255, 255, 255, 0.7);
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 600;
font-size: 0.95rem;
}
.toggle-btn.active {
background: white;
color: #764ba2;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.workflow-view {
flex: 1;
position: relative;
overflow: hidden;
}
/* 总览视图 */
.overview-container {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
overflow: auto;
}
.workflow-track {
display: flex;
align-items: center;
gap: 60px;
position: relative;
padding: 40px;
min-width: max-content;
}
.workflow-line {
position: absolute;
top: 50%;
left: 50px;
right: 50px;
height: 3px;
background: linear-gradient(90deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0.3) 50%,
rgba(255, 255, 255, 0.1) 100%);
z-index: 1;
animation: flowLine 3s linear infinite;
}
@keyframes flowLine {
0% { background-position: -100% 0; }
100% { background-position: 100% 0; }
}
.workflow-node {
width: 120px;
height: 120px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.85) 100%);
border-radius: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
position: relative;
z-index: 10;
box-shadow:
0 10px 30px rgba(0, 0, 0, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.5);
border: 2px solid rgba(255, 255, 255, 0.3);
overflow: hidden;
}
.workflow-node::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent);
transform: rotate(45deg);
transition: all 0.5s;
opacity: 0;
}
.workflow-node:hover::before {
animation: shimmer 0.5s ease;
opacity: 1;
}
@keyframes shimmer {
0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
100% { transform: translateX(100%) translateY(100%) rotate(45deg); }
}
.workflow-node.small {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
border-radius: 25px;
}
.workflow-node.small .node-icon {
font-size: 36px;
}
.workflow-node.small .node-title {
font-size: 11px;
}
.workflow-node.detect {
width: 85px;
height: 85px;
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
border-radius: 20px;
transform: rotate(10deg);
}
.workflow-node.detect:hover {
transform: rotate(0deg) translateY(-10px) scale(1.1);
}
.workflow-node.detect .node-icon {
font-size: 30px;
transform: rotate(-10deg);
}
.workflow-node.detect .node-title {
font-size: 10px;
transform: rotate(-10deg);
}
.branch-container {
display: flex;
flex-direction: column;
gap: 25px;
position: relative;
align-items: center;
padding: 30px 20px;
background: rgba(255, 255, 255, 0.05);
border-radius: 30px;
border: 2px dashed rgba(255, 255, 255, 0.2);
backdrop-filter: blur(5px);
}
.branch-group {
display: flex;
flex-direction: column;
gap: 20px;
position: relative;
}
.branch-row {
display: flex;
gap: 25px;
align-items: center;
position: relative;
}
.branch-connector {
width: 40px;
height: 3px;
background: linear-gradient(90deg, #ff6b9d 0%, #feca57 100%);
position: relative;
border-radius: 2px;
overflow: hidden;
}
.branch-connector::after {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg,
transparent,
rgba(255, 255, 255, 0.8),
transparent);
animation: flowConnector 2s linear infinite;
}
@keyframes flowConnector {
0% { left: -100%; }
100% { left: 100%; }
}
.branch-arrow {
width: 0;
height: 0;
border-left: 10px solid #feca57;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
position: absolute;
right: -10px;
top: 50%;
transform: translateY(-50%);
filter: drop-shadow(0 0 3px rgba(254, 202, 87, 0.5));
}
.workflow-node:hover {
transform: translateY(-15px) scale(1.1) rotate(2deg);
box-shadow:
0 20px 40px rgba(0, 0, 0, 0.3),
0 0 30px rgba(255, 255, 255, 0.3);
}
.node-icon {
font-size: 45px;
margin-bottom: 10px;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
animation: iconFloat 3s ease-in-out infinite;
}
@keyframes iconFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.node-title {
font-size: 12px;
font-weight: 700;
color: #333;
text-align: center;
padding: 0 10px;
letter-spacing: 0.5px;
}
/* 详细视图 */
.detail-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
}
.detail-nodes-area {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
transform: translateY(0);
transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
z-index: 2;
}
.detail-nodes-area.compressed {
transform: translateY(-35%) scale(0.8); /* 进一步压缩,给内容更多空间 */
}
.detail-track {
display: flex;
gap: 80px;
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
align-items: center;
position: absolute;
}
.detail-node {
width: 200px;
height: 200px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(255, 255, 255, 0.95) 100%);
border-radius: 40px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
position: relative;
box-shadow:
0 20px 50px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.5);
border: 3px solid rgba(255, 255, 255, 0.4);
overflow: hidden;
flex-shrink: 0;
}
.compressed .detail-node {
width: 160px;
height: 160px;
border-radius: 32px;
}
.detail-node.active {
box-shadow:
0 25px 50px rgba(0, 0, 0, 0.35),
0 0 50px rgba(102, 126, 234, 0.4),
inset 0 0 25px rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.8);
}
.detail-node::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg,
transparent,
rgba(255, 255, 255, 0.4),
transparent);
transform: rotate(45deg);
transition: all 0.5s;
opacity: 0;
}
.detail-node:hover::before {
animation: shimmer 0.5s ease;
opacity: 1;
}
.detail-node-icon {
font-size: 80px;
margin-bottom: 15px;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.15));
animation: iconPulse 2s ease-in-out infinite;
transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.compressed .detail-node-icon {
font-size: 60px;
margin-bottom: 12px;
}
.detail-node-title {
font-size: 18px;
font-weight: 700;
color: #333;
text-align: center;
padding: 0 20px;
letter-spacing: 0.5px;
transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.compressed .detail-node-title {
font-size: 15px;
padding: 0 15px;
}
.detail-content-area {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 70%; /* 增加高度到70% */
background: linear-gradient(135deg,
rgba(248, 248, 252, 0.98) 0%,
rgba(243, 244, 248, 0.95) 100%);
backdrop-filter: blur(20px);
border-top: 1px solid rgba(200, 200, 220, 0.3);
transform: translateY(100%);
transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
overflow: hidden; /* 改回hidden防止内容溢出容器 */
z-index: 3;
}
.detail-content-area.show {
transform: translateY(0);
}
.detail-content {
padding: 40px;
padding-bottom: 100px; /* 增加底部内边距,确保内容可以滚动到顶部 */
height: 100%;
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: thin;
scrollbar-color: rgba(120, 119, 198, 0.3) rgba(255, 255, 255, 0.05);
}
.detail-content::-webkit-scrollbar {
width: 10px;
}
.detail-content::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
}
.detail-content::-webkit-scrollbar-thumb {
background: linear-gradient(135deg, rgba(120, 119, 198, 0.3) 0%, rgba(162, 155, 254, 0.3) 100%);
border-radius: 10px;
border: 2px solid transparent;
background-clip: padding-box;
}
.detail-content::-webkit-scrollbar-thumb:hover {
background: linear-gradient(135deg, rgba(120, 119, 198, 0.5) 0%, rgba(162, 155, 254, 0.5) 100%);
background-clip: padding-box;
}
.detail-card {
width: 100%;
max-width: 1200px;
margin: 0 auto;
position: relative;
padding-bottom: 60px; /* 适当的底部内边距 */
}
.detail-header {
margin-bottom: 25px;
}
.detail-title {
font-size: 2rem;
font-weight: 700;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: -0.5px;
text-align: center;
}
.detail-description {
font-size: 1.15rem;
color: #666;
line-height: 1.8;
margin-bottom: 30px;
position: relative;
z-index: 1;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 25px;
margin-bottom: 30px;
position: relative;
z-index: 1;
}
.detail-item {
background: linear-gradient(135deg, #f8f9fc 0%, #e2e6f0 100%);
padding: 20px;
border-radius: 20px;
transition: all 0.3s ease;
cursor: pointer;
position: relative;
overflow: hidden;
}
.detail-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.detail-item:hover {
transform: translateY(-5px) scale(1.05);
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3);
}
.detail-item:hover::before {
opacity: 0.1;
}
.detail-label {
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
color: #999;
margin-bottom: 8px;
position: relative;
z-index: 1;
}
.detail-value {
font-size: 1.3rem;
font-weight: 700;
color: #333;
position: relative;
z-index: 1;
}
.results-section {
margin-top: 30px;
opacity: 0;
max-height: 0;
overflow: hidden;
transition: all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
position: relative;
z-index: 1;
}
.results-section.show {
opacity: 1;
max-height: none; /* 移除高度限制,让内容完全展开 */
overflow: visible; /* 允许内容显示 */
}
.show-results-btn {
padding: 15px 40px;
background: linear-gradient(135deg, #ff6b9d 0%, #feca57 100%);
border: none;
border-radius: 30px;
color: white;
font-size: 1.05rem;
font-weight: 700;
cursor: pointer;
transition: all 0.3s ease;
margin-bottom: 20px;
box-shadow: 0 10px 30px rgba(255, 107, 157, 0.3);
position: relative;
overflow: hidden;
text-transform: uppercase;
letter-spacing: 1px;
}
.show-results-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent);
transition: left 0.5s ease;
}
.show-results-btn:hover::before {
left: 100%;
}
.show-results-btn:hover {
transform: translateY(-3px) scale(1.05);
box-shadow: 0 15px 40px rgba(255, 107, 157, 0.4);
}
.result-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 25px;
animation: slideDown 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.result-card {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
padding: 25px;
border-radius: 25px;
cursor: default;
position: relative;
overflow: visible;
color: white;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
.result-card.code-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.result-card.prompt-card {
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
color: #333;
}
.result-card.image-card {
background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);
}
.image-gallery {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
margin-top: 20px;
}
.gallery-image {
width: 100%;
height: 150px;
object-fit: cover;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.gallery-image:hover {
transform: scale(1.05);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
}
.code-content {
background: rgba(0, 0, 0, 0.2);
padding: 20px;
border-radius: 10px;
margin-top: 15px;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
line-height: 1.6;
word-break: break-word;
white-space: pre-wrap;
max-height: 300px;
overflow-y: auto;
}
.code-content::-webkit-scrollbar {
width: 6px;
}
.code-content::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}
.code-content::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 3px;
}
.prompt-content {
background: rgba(255, 255, 255, 0.9);
color: #333;
padding: 25px;
border-radius: 15px;
margin-top: 15px;
font-size: 0.9rem;
line-height: 1.6;
white-space: pre-wrap;
max-height: none;
word-wrap: break-word;
}
.prompt-content::-webkit-scrollbar {
width: 6px;
}
.prompt-content::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.05);
border-radius: 3px;
}
.prompt-content::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 3px;
box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.1);
}
/* 文档卡片样式 */
.result-card.document-card {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.document-content {
background: rgba(255, 255, 255, 0.95);
color: #333;
padding: 30px;
border-radius: 15px;
margin-top: 15px;
font-size: 0.9rem;
line-height: 1.8;
white-space: pre-wrap;
max-height: 500px;
overflow-y: auto;
}
.document-content h1, .document-content h2, .document-content h3 {
color: #4facfe;
margin: 20px 0 10px 0;
}
.document-content h1 { font-size: 1.5rem; }
.document-content h2 { font-size: 1.3rem; }
.document-content h3 { font-size: 1.1rem; }
.document-content::-webkit-scrollbar {
width: 8px;
}
.document-content::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
.document-content::-webkit-scrollbar-thumb {
background: rgba(79, 172, 254, 0.3);
border-radius: 4px;
}
/* 文件卡片样式 */
.result-card.file-card {
background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
}
.file-info {
background: rgba(255, 255, 255, 0.95);
color: #333;
padding: 20px;
border-radius: 15px;
margin-top: 15px;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
line-height: 1.6;
white-space: pre-wrap;
}
/* Markdown预览样式 */
.markdown-preview {
background: rgba(255, 255, 255, 0.98);
color: #2c3e50;
padding: 40px;
border-radius: 20px;
margin-top: 20px;
font-size: 0.95rem;
line-height: 1.8;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.05);
}
.markdown-preview h1 {
color: #1a73e8;
font-size: 1.8rem;
margin: 30px 0 20px 0;
padding-bottom: 10px;
border-bottom: 2px solid #e8f0fe;
font-weight: 700;
}
.markdown-preview h2 {
color: #1967d2;
font-size: 1.4rem;
margin: 25px 0 15px 0;
font-weight: 600;
}
.markdown-preview h3 {
color: #1a73e8;
font-size: 1.1rem;
margin: 20px 0 10px 0;
font-weight: 600;
}
.markdown-preview p {
margin: 15px 0;
line-height: 1.8;
}
.markdown-preview ul, .markdown-preview ol {
margin: 15px 0;
padding-left: 30px;
}
.markdown-preview li {
margin: 8px 0;
line-height: 1.6;
}
.markdown-preview strong {
color: #1967d2;
font-weight: 600;
}
.markdown-preview img {
max-width: 100%;
height: auto;
border-radius: 12px;
margin: 20px 0;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.result-title {
font-size: 1.2rem;
font-weight: 700;
margin-bottom: 12px;
position: relative;
z-index: 1;
}
.result-desc {
font-size: 0.95rem;
line-height: 1.6;
opacity: 0.95;
position: relative;
z-index: 1;
}
/* 设计节点的图片网格 */
.design-images-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
padding: 20px 0;
max-height: 600px;
overflow-y: auto;
}
/* AI质检节点单图片居中 */
.design-images-grid.single-image {
display: flex;
justify-content: center;
align-items: center;
min-height: 400px;
}
.design-images-grid.single-image .design-image {
max-width: 600px;
width: auto;
}
.design-images-grid::-webkit-scrollbar {
width: 8px;
}
.design-images-grid::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
}
.design-images-grid::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 10px;
}
.design-images-grid::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.5);
}
.design-image {
width: 100%;
height: auto;
min-height: 200px;
max-height: 400px;
object-fit: contain;
background: rgba(255, 255, 255, 0.05);
border-radius: 15px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.design-image:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
/* 大图模态框 */
.image-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.95);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
animation: fadeIn 0.3s ease;
padding: 40px;
overflow: auto;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.modal-content {
position: relative;
max-width: 90vw;
max-height: 90vh;
display: flex;
align-items: center;
justify-content: center;
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
.modal-content img {
max-width: 100%;
max-height: 90vh;
width: auto;
height: auto;
object-fit: contain;
border-radius: 10px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.close-btn {
position: absolute;
top: -40px;
right: -40px;
width: 40px;
height: 40px;
background: rgba(255, 255, 255, 0.1);
border: 2px solid rgba(255, 255, 255, 0.3);
color: white;
font-size: 24px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.close-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: rotate(90deg);
}
.progress-bar {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 6px;
background: rgba(255, 255, 255, 0.1);
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #ff6b9d 0%, #feca57 100%);
transition: width 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: 0 0 10px rgba(255, 107, 157, 0.5);
}
.pulse-ring {
position: absolute;
width: 100%;
height: 100%;
border: 3px solid rgba(255, 107, 157, 0.5);
border-radius: inherit;
animation: pulse 2s linear infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.3);
opacity: 0;
}
}
</style>
</head>
<body>
<div class="floating-orb orb-1"></div>
<div class="floating-orb orb-2"></div>
<div class="floating-orb orb-3"></div>
<div id="root"></div>
<script type="text/babel">
const { useState, useCallback, useMemo } = React;
const WorkflowApp = () => {
const [viewMode, setViewMode] = useState('overview');
const [currentNode, setCurrentNode] = useState(0);
const [showResults, setShowResults] = useState({});
const [nodeClicked, setNodeClicked] = useState({});
const [selectedImage, setSelectedImage] = useState(null);
// 完整的Markdown到HTML转换函数
const renderMarkdown = (text) => {
if (!text) return null;
// 先处理图片链接转换为正确的HTML img标签
let html = text
// 替换Markdown图片语法为HTML img标签使用输出文件夹中的图片
.replace(/!\[.*?\]\((29aab970-92d1-4a79-84d3-5a29d9e299eb\.jpeg)\)/g,
'<img src="public/输出/$1" alt="杯子设计" />')
.replace(/!\[.*?\]\((20250824-121446\.jpg)\)/g,
'<img src="public/输出/$1" alt="空间设计" />')
.replace(/!\[.*?\]\((outputs_20250824_3k4iaqnnbt\.jpeg)\)/g,
'<img src="public/输出/$1" alt="海报设计" />')
.replace(/!\[.*?\]\((img_v3_02pf_f256578f-91f0-43f6-9e25-37fe423fd23g\.jpg)\)/g,
'<img src="public/输出/$1" alt="帽子设计" />');
// 处理标题
html = html
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
// 处理加粗
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
// 处理列表项
.replace(/^\d+\.\s+(.*$)/gim, '<li>$1</li>')
.replace(/^[\-\*]\s+(.*$)/gim, '<li>$1</li>');
// 处理段落和列表包装
const lines = html.split('\n');
let result = [];
let inList = false;
let listItems = [];
for (let line of lines) {
if (line.includes('<li>')) {
if (!inList) {
inList = true;
listItems = [];
}
listItems.push(line);
} else {
if (inList) {
result.push('<ul>' + listItems.join('') + '</ul>');
inList = false;
listItems = [];
}
if (line.trim() && !line.includes('<h1>') && !line.includes('<h2>') &&
!line.includes('<h3>') && !line.includes('<img')) {
if (!line.includes('<p>')) {
line = '<p>' + line + '</p>';
}
}
if (line.trim()) {
result.push(line);
}
}
}
if (inList) {
result.push('<ul>' + listItems.join('') + '</ul>');
}
return <div dangerouslySetInnerHTML={{ __html: result.join('\n') }} />;
};
const nodes = [
{ id: 'input', icon: '📝', title: '输入需求' },
{ id: 'analyze', icon: '🤖', title: '分析模型' },
{ id: 'prompt', icon: '✨', title: '生成提示词' },
{ id: 'optimize', icon: '🔧', title: '优化提示词' },
{ id: 'cup', icon: '🥤', title: '奶茶杯设计', branch: 1 },
{ id: 'cup-detect', icon: '🔍', title: 'AI检测-杯子', branch: 1 },
{ id: 'space', icon: '🏠', title: '奶茶店空间设计', branch: 2 },
{ id: 'space-detect', icon: '🔍', title: 'AI检测-空间', branch: 2 },
{ id: 'poster', icon: '📰', title: '宣传海报设计', branch: 3 },
{ id: 'poster-detect', icon: '🔍', title: 'AI检测-海报', branch: 3 },
{ id: 'merch', icon: '🧢', title: '周边帽子设计', branch: 4 },
{ id: 'merch-detect', icon: '🔍', title: 'AI检测-周边', branch: 4 },
{ id: 'document', icon: '📋', title: '归纳文档' },
{ id: 'output', icon: '✅', title: '输出结果' }
];
const nodeDetails = {
input: {
description: '为宝可梦主题的联名奶茶快闪店设计完整的主视觉KV风格方案',
details: [
{ label: '主题风格', value: '宝可梦XYZ' },
{ label: '联名元素', value: '小智/瑟琳娜/皮卡丘' },
{ label: '风格偏好', value: '二次元动漫风' },
{ label: '目标人群', value: '18-30岁动漫爱好者' }
],
results: [
{
title: '主题设定',
desc: '二次元宝可梦风格主题的联名奶茶快闪店',
content: '主题风格:二次元宝可梦风格主题的联名奶茶快闪店/小智/瑟琳娜/皮卡丘\n风格偏好二次元/宝可梦xyz/小智/瑟琳娜/皮卡丘'
}
]
},
analyze: {
description: '智能选择最适合的AI模型组合确保输出质量',
details: [
{ label: '场景分析', value: '多模态生成' },
{ label: '任务类型', value: '图文设计' },
{ label: '模型数量', value: '4个' },
{ label: '准确率', value: '98%' }
],
results: [
{
title: '豆包 1.6 深度思考',
desc: '视频理解、图片理解、工具调用、深度思考',
content: '豆包1.6系列模型支持最长256K上下文提供综合型、深度推理型和极速型三种版本均具备多模态理解与GUI操作能力。引入三种"思考模式",自适应模式可根据任务复杂度自动决定是否调用深度思考。'
},
{
title: 'TextToFlux.1.dev',
desc: '文本生成图像、图像生成视频、多模态生成',
content: '集"文生图"和"图生视频"能力于一体的多模态生成工具,能够根据文本提示先生成图像,再基于该图像进一步生成视频。'
},
{
title: 'LangGPT 结构化提示',
desc: '提示词生成、Prompt Engineering、模板化设计',
content: '将提示设计结构化为一种"提示语言",强调结构可复用、易迭代更新,降低提示工程复杂度。'
},
{
title: 'DeepseekR1 强化推理',
desc: '文本处理、深度推理、纯RL、chain-of-thought',
content: '采用纯强化学习方法训练,通过"冷启动"技术结合SFT解决了可读性差与语言混合问题表现与OpenAI-o1相当。'
}
]
},
prompt: {
description: '生成专业的AI设计提示词模板确保风格一致性',
details: [
{ label: '角色定义', value: '视觉研究专家' },
{ label: '技能范围', value: '空间/周边/KV设计' },
{ label: '输出格式', value: '结构化提示词' },
{ label: '语言要求', value: '英文提示词' }
],
results: [
{
title: '提示词模板',
desc: '完整的设计助手角色定义和工作流程',
isPrompt: true,
content: `# Role: 奶茶快闪店铺设计参考助手
## Profile
- author: LangGPT
- version: 1.0
- language: 中文
- description: 你是一位空间视觉研究专家,擅长根据主题在网络上搜索并收集与奶茶类快闪店铺相关的视觉风格素材
## Skills
1. 熟悉快闪店空间设计、周边物料与活动视觉的整体协作关系
2. 擅长在Pinterest、Behance、小红书、Instagram等平台精准检索相关奶茶风格设计内容
3. 能对视觉资料进行归类整理,并提取装修元素、配色语言、字体风格、情绪氛围等关键元素
4. 能针对不同主题风格进行细致分析并输出AI生成提示词
## Goals
- 收集符合奶茶快闪店主题的装修风格、展陈布局、海报设计与道具样式图
- 每类内容输出不少于2-3张代表图像及来源链接
- 对每组图像提取核心设计要素
- 每个风格输出10条可直接用于AI图像生成的英文提示词
## Rules
1. 所有素材需来自设计平台或社交平台风格统一主题明确适合18-30岁消费人群
2. 每张图像需包含:简短说明 + 来源链接 + 关键词标签 + 应用建议
3. 所有AI提示词需英文编写格式完整结构清晰视觉风格明确
4. 所含内容包括但不限于:奶茶店空间视觉、海报设计、杯套/纸袋/展示道具、品牌物料等
## Workflows
1. 接收用户提供的主题关键词(如"梦幻粉色奶茶快闪"、"Y2K街头茶饮店"
2. 使用关键词在Pinterest、Behance、小红书、Instagram等平台搜索相关素材
3. 对搜集到的图像内容进行归类,并提炼各自核心视觉语言
4. 为每组风格输出视觉参考包,包括:图像信息 + 元素提取 + 5条AI提示词英文
5. 可根据不同快闪场景或城市文化进行本地化调整与风格推荐
## OutputFormat
- 风格主题名称
- 图像参考2张以上每张含简要说明+来源链接)
- 样式关键词
- 视觉要素分析(颜色、字体、道具、情绪氛围)
- AI图像生成提示词5条英文
- 使用建议与应用场景
- 每条图像生成提示词之间用制表符\t隔开`
}
]
},
optimize: {
description: 'AI驱动的提示词优化生成四个设计方向的专业提示词',
details: [
{ label: '优化算法', value: 'GPT-4 Turbo' },
{ label: '风格一致性', value: '95%' },
{ label: '细节丰富度', value: '极高' },
{ label: '可用性评分', value: '9.8/10' }
],
results: [
{
title: '奶茶杯设计提示词',
desc: 'Pokemon主题奶茶杯专业设计提示词',
isCode: true,
content: 'Best quality, ultra-detailed, masterpiece, 4K, hyper detailed, japanese anime style, Pokemon themed bubble tea cup design, with Pikachu, Ash, Serena illustrations, yellow, black, blue, pink, white color scheme, cute, playful, adventure, elegant style, standard milk tea cup shape, paper or plastic material, cartoon font, in a cute, adventurous, 二次元 atmosphere, for pop-up shop, anime exhibition, themed cafe scenes, 3D rendering, high detail'
},
{
title: '空间设计提示词',
desc: 'Pokemon主题快闪店空间设计提示词',
isCode: true,
content: 'Best quality, ultra-detailed, masterpiece, 4K, hyper detailed, japanese anime style, Pokemon themed pop-up store for milk tea collaboration, exterior with yellow and red colors, featuring Pikachu and Ash, interior with Pokeball decorations and Serena\'s image, seating designed as Pokeballs, wall decor with Pokeballs and Serena, overall dreamy atmosphere with soft LED lighting, in shopping malls, shopping centers or theme parks'
},
{
title: '海报设计提示词',
desc: 'Pokemon主题宣传海报设计提示词',
isCode: true,
content: 'Best quality, ultra-detailed, masterpiece, 4K, hyper detailed, japanese anime, Pokemon, Tea Popup Store, Pikachu, Ash, Serena, bright colors, adventure, cityscape, main visual design for promotional posters and KV, centered characters, classic Pokemon color scheme, anime-style font, in the atmosphere of vitality, adventure and co-branding'
},
{
title: '帽子设计提示词',
desc: 'Pokemon主题周边帽子设计提示词',
isCode: true,
content: 'Best quality, ultra-detailed, masterpiece, 4K, hyper detailed, japanese anime style, Anime Pokemon hat design, including Ash Ketchum\'s baseball cap with his iconic hat pattern in red and white and Pokeball pattern on brim, Serena\'s beret with her classic image in pink and white and flower decoration on brim, Pikachu\'s fisherman hat with its cute image in yellow and black and lightning pattern on brim, realistic 3D render, in a cute and classic atmosphere'
}
]
},
cup: {
description: '产品包装设计方案,打造独特视觉识别',
details: [
{ label: '材质', value: '食品级PP' },
{ label: '容量', value: '500ml/700ml' },
{ label: '工艺', value: 'UV印刷+烫金' },
{ label: '特色', value: '温变油墨' }
],
results: [
{ title: '设计效果图', desc: '',
images: [
'public/images/1.杯子设计/20250824-121424.jpg',
'public/images/1.杯子设计/29aab970-92d1-4a79-84d3-5a29d9e299eb.jpeg',
'public/images/1.杯子设计/outputs_20250824_808xmsfce2.jpeg',
'public/images/1.杯子设计/outputs_20250824_alih5p1kcd.jpeg'
]
}
]
},
space: {
description: '快闪店空间规划,打造网红打卡圣地',
details: [
{ label: '总面积', value: '120㎡' },
{ label: '点单区', value: '15㎡' },
{ label: '客座区', value: '50㎡' },
{ label: '拍照区', value: '30㎡' }
],
results: [
{ title: '设计效果图', desc: '',
images: [
'public/images/2.空间设计/20250824-121446.jpg',
'public/images/2.空间设计/93469f4c-c328-47f5-9bb9-50690b8d422f.jpeg',
'public/images/2.空间设计/outputs_20250824_0xxbp18141.jpeg',
'public/images/2.空间设计/outputs_20250824_grt985ot8m.jpeg'
]
}
]
},
poster: {
description: '全渠道营销物料设计方案',
details: [
{ label: '线下投放', value: '地铁/商场' },
{ label: '线上传播', value: '社交媒体' },
{ label: '规格', value: '多规格适配' },
{ label: '数量', value: '12张' }
],
results: [
{ title: '设计效果图', desc: '',
images: [
'public/images/3.海报设计/20250824-121452.jpg',
'public/images/3.海报设计/outputs_20250824_3hrmv4jf4d.jpeg',
'public/images/3.海报设计/outputs_20250824_3k4iaqnnbt.jpeg',
'public/images/3.海报设计/outputs_20250824_7yihwahhny.jpeg'
]
}
]
},
merch: {
description: '品牌周边产品设计,增强品牌认知',
details: [
{ label: '材质', value: '100%纯棉' },
{ label: '刺绣', value: '12色渐变' },
{ label: '印花', value: '3D热转印' },
{ label: '包装', value: '定制礼盒' }
],
results: [
{ title: '设计效果图', desc: '',
images: [
'public/images/4.帽子设计/a2adf521-6de2-4a15-b6db-3f64de9e4bd6.jpeg',
'public/images/4.帽子设计/img_v3_02pf_f256578f-91f0-43f6-9e25-37fe423fd23g.jpg',
'public/images/4.帽子设计/outputs_20250824_d2z45iefud.jpeg',
'public/images/4.帽子设计/outputs_20250824_mp4q2hsfmr.jpeg'
]
}
]
},
'cup-detect': {
description: '奶茶杯设计质量检测',
details: [
{ label: '品牌一致性', value: '96%' },
{ label: '色彩准确度', value: '98%' },
{ label: '材质表现', value: '94%' },
{ label: '印刷可行性', value: '合格' }
],
results: [
{ title: '质检后效果图', desc: '',
images: [
'public/images/5.ai质检后的图片/1.杯子.jpeg'
]
}
]
},
'space-detect': {
description: '空间设计质量检测',
details: [
{ label: '空间利用率', value: '92%' },
{ label: '光线设计', value: '优秀' },
{ label: '人流动线', value: '合理' },
{ label: '视觉效果', value: '95%' }
],
results: [
{ title: '质检后效果图', desc: '',
images: [
'public/images/5.ai质检后的图片/2.空间.jpg'
]
}
]
},
'poster-detect': {
description: '海报设计质量检测',
details: [
{ label: '视觉冲击力', value: '97%' },
{ label: '信息层级', value: '清晰' },
{ label: '色彩和谐度', value: '96%' },
{ label: '品牌识别度', value: '95%' }
],
results: [
{ title: '质检后效果图', desc: '',
images: [
'public/images/5.ai质检后的图片/3.海报设计.jpeg'
]
}
]
},
'merch-detect': {
description: '周边设计质量检测',
details: [
{ label: '设计创意度', value: '93%' },
{ label: '生产可行性', value: '合格' },
{ label: '成本评估', value: '合理' },
{ label: '市场吸引力', value: '94%' }
],
results: [
{ title: '质检后效果图', desc: '',
images: [
'public/images/5.ai质检后的图片/帽子设计.jpg'
]
}
]
},
document: {
description: '宝可梦品牌青春治愈系全场景视觉与周边设计策划方案',
details: [
{ label: '文档类型', value: 'Markdown' },
{ label: '核心理念', value: '品牌生活伙伴' },
{ label: '设计风格', value: '青春治愈系' },
{ label: '覆盖场景', value: '产品/空间/传播' }
],
results: [
{
title: '设计策划方案',
desc: '完整的全场景视觉与周边设计文档',
isDocument: true,
content: `# 宝可梦品牌青春治愈系全场景视觉与周边设计策划方案
## 一、设计说明
本套设计围绕让品牌成为可触摸的生活伙伴核心理念,打造视觉统一+场景沉浸的全链路品牌表达系统。整体风格融合清新潮酷与温暖治愈,以马卡龙渐变色系+软萌IP符号为核心视觉语言串联周边产品奶茶杯、帽子、线下空间、视觉海报三大场景核心方向聚焦从视觉符号到情感连接——通过产品的实用性、空间的体验感、海报的传播力将品牌年轻、治愈、有温度的认知转化为用户可感知、可参与、可分享的生活场景强化品牌=青春治愈伙伴的心智联想。
## 二、设计亮点
1. 全场景视觉闭环从周边产品的细节图案如奶茶杯的渐变花纹、帽子的IP刺绣到空间设计的元素延续如墙面装饰呼应杯子造型再到海报的色彩体系所有设计均源于同一IP视觉库实现看海报→逛空间→买周边的认知连贯让品牌记忆点在不同场景中反复强化。
2. 情感化仪式感植入奶茶杯内置温度感应隐藏图案倒入热饮后浮现IP符号将喝奶茶变成解锁小惊喜的仪式空间设计预留奶茶杯打卡墙与周边杯子1:10比例的巨型装置满足用户拍美照、晒社交的需求帽子采用可拆卸IP徽章让用户通过DIY搭配将品牌元素融入个人风格增加互动感。
3. 年轻群体精准共鸣色彩选择浅粉、淡蓝、奶黄契合Z世代治愈系审美图案设计用简笔奶茶泡、软萌云朵等拟态符号降低认知门槛所有产品均兼顾潮流性与实用性如帽子的软顶版型适配日常穿搭、杯子的防烫材质适合高频使用让设计不仅好看更好用。
## 三、逐图展示说明
### 1. 周边奶茶杯子设计
- 图片链接:
![29aab970-92d1-4a79-84d3-5a29d9e299eb.jpeg](29aab970-92d1-4a79-84d3-5a29d9e299eb.jpeg)
- 设计解析:杯子以奶黄→浅粉渐变雾面材质为主体,杯身印刻简笔奶茶泡+软萌IP小怪兽图案与品牌IP完全一致杯盖采用半透明磨砂+小耳朵造型,强化软萌治愈属性。核心设计逻辑是将产品变成品牌的移动体验载体——用户使用时,不仅能感受到材质的细腻质感,更能通过温度感应图案的小惊喜,记住品牌的治愈感,实现用一次就爱上的情感连接。
### 2. 线下空间设计
- 图片链接:
![20250824-121446.jpg](20250824-121446.jpg)
- 设计解析空间以奶茶杯IP为核心视觉符号布局分为点单区→体验区→打卡区三大模块
- 点单区背景墙采用奶茶杯图案重复排列(与周边杯子花纹一致),搭配发光奶茶杯造型灯,强化品牌认知;
- 体验区设置奶茶杯造型沙发与周边杯子1:2比例搭配可调节马卡龙色灯光营造窝在奶茶里的治愈感
- 打卡区设计巨型奶茶杯装置1:10比例墙面贴满用户分享的温度感应杯照片实现空间→用户→品牌的社交联动。
整体空间既是消费场景,更是品牌视觉的三维展示柜,让用户逛空间=沉浸式体验品牌。
### 3. 视觉海报设计
- 图片链接:
![outputs_20250824_3k4iaqnnbt.jpeg](outputs_20250824_3k4iaqnnbt.jpeg)
- 设计解析:海报采用中心聚焦+场景延伸构图,核心元素是小智手持奶茶杯+背景迷你空间,色彩延续暖色为主色+淡蓝辅助色的马卡龙体系,文字用软萌手写体+潮酷粗体组合。设计目的是用一张海报讲清品牌所有核心信息——既展示产品(奶茶杯),又传递场景(空间),同时激发行动(到店打卡),是品牌传播的浓缩信息包。
### 4. 周边帽子设计
- 图片链接:
![img_v3_02pf_f256578f-91f0-43f6-9e25-37fe423fd23g.jpg](img_v3_02pf_f256578f-91f0-43f6-9e25-37fe423fd23g.jpg)
- 设计解析:帽子采用软顶鸭舌帽版型(适配多数头型,兼顾舒适与潮流),主体为黄色+深蓝帽檐(呼应奶茶杯渐变色系),正面刺绣精灵球图案。材质选用透气棉麻+抗皱涂层适合日常搭配卫衣、连衣裙均适配。设计亮点是把品牌元素变成可DIY的时尚单品——用户可根据穿搭风格选择是否佩戴徽章既满足个性化需求又通过小面积品牌露出让帽子成为品牌的移动宣传载体。
本方案通过视觉统一+场景沉浸+情感互动的设计逻辑,将品牌从平面符号转化为可触摸、可参与、可分享的生活场景,最终实现用户主动传播、品牌心智占领的目标。`
}
]
},
output: {
description: '项目成功交付,所有文件已打包就绪',
details: [
{ label: '交付状态', value: '已完成' },
{ label: '文件格式', value: 'ZIP压缩包' },
{ label: '包含内容', value: '设计图+文档' },
{ label: '交付方式', value: '在线下载' }
],
results: [
{
title: '项目交付文件',
desc: '完整的设计资产压缩包',
isFile: true,
fileName: '输出.zip',
fileInfo: `📦 输出.zip
包含文件:
• 4张设计效果图
- 20250824-121446.jpg (空间设计)
- 29aab970-92d1-4a79-84d3-5a29d9e299eb.jpeg (杯子设计)
- img_v3_02pf_f256578f-91f0-43f6-9e25-37fe423fd23g.jpg (帽子设计)
- outputs_20250824_3k4iaqnnbt.jpeg (海报设计)
• 1份策划文档
- 宝可梦品牌青春治愈系全场景视觉与周边设计策划方案.md
文件大小约15MB
创建时间2025-08-24`
}
]
}
};
const handleNodeClick = React.useCallback((index) => {
const node = nodes[index];
if (viewMode === 'overview') {
// 总览模式:第一次点击进入详细视图
setCurrentNode(index);
setViewMode('detail');
// 重置状态
setNodeClicked({});
setShowResults({});
} else if (viewMode === 'detail') {
// 详细视图中点击节点
if (index === currentNode) {
// 点击当前节点:切换详细内容显示
toggleResults(node.id);
} else {
// 点击其他节点:切换到该节点
setShowResults({});
setTimeout(() => {
setCurrentNode(index);
}, 100);
}
}
}, [viewMode, currentNode]);
const toggleResults = (nodeId) => {
setShowResults(prev => ({
...prev,
[nodeId]: !prev[nodeId]
}));
};
return (
<div className="app-container">
{/* 大图查看模态框 */}
{selectedImage && (
<div className="image-modal" onClick={() => setSelectedImage(null)}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<img src={selectedImage} alt="大图" />
<button className="close-btn" onClick={() => setSelectedImage(null)}>×</button>
</div>
</div>
)}
{/* 数字粒子装饰 */}
<div className="digital-particles">
{[...Array(15)].map((_, i) => (
<div
key={i}
className="particle"
style={{
left: `${Math.random() * 100}%`,
top: `${Math.random() * 100}%`,
animationDelay: `${Math.random() * 10}s`,
animationDuration: `${15 + Math.random() * 20}s`
}}
/>
))}
</div>
{/* 数据流线条 */}
<svg className="data-lines" width="100%" height="100%">
<defs>
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="rgba(120, 119, 198, 0)" />
<stop offset="50%" stopColor="rgba(120, 119, 198, 0.3)" />
<stop offset="100%" stopColor="rgba(120, 119, 198, 0)" />
</linearGradient>
</defs>
{[...Array(3)].map((_, i) => (
<line
key={i}
x1="0"
y1={`${30 + i * 30}%`}
x2="100%"
y2={`${30 + i * 30}%`}
stroke="url(#lineGradient)"
strokeWidth="1"
opacity="0.3"
className="data-line"
style={{
animationDelay: `${i * 2}s`
}}
/>
))}
</svg>
<div className="header">
<div className="title">
<span>🧋</span>
<span>AI Agent 奶茶快闪店设计工作流</span>
</div>
<div className="view-toggle">
<button
className={`toggle-btn ${viewMode === 'overview' ? 'active' : ''}`}
onClick={() => setViewMode('overview')}
>
流程总览
</button>
<button
className={`toggle-btn ${viewMode === 'detail' ? 'active' : ''}`}
onClick={() => setViewMode('detail')}
>
详细视图
</button>
</div>
</div>
<div className="workflow-view">
{viewMode === 'overview' ? (
<div className="overview-container">
<div className="workflow-track">
<div className="workflow-line"></div>
{nodes.map((node, index) => {
// 在优化提示词后显示四条并列分支
if (node.id === 'optimize') {
const designNodes = nodes.filter(n =>
['cup', 'space', 'poster', 'merch'].includes(n.id)
);
const detectNodes = nodes.filter(n =>
['cup-detect', 'space-detect', 'poster-detect', 'merch-detect'].includes(n.id)
);
return (
<React.Fragment key={node.id}>
<div
className="workflow-node"
onClick={() => handleNodeClick(index)}
>
<span className="pulse-ring"></span>
<div className="node-icon">{node.icon}</div>
<div className="node-title">{node.title}</div>
</div>
<div className="branch-container">
<div className="branch-group">
{designNodes.map((designNode, i) => {
const designIndex = nodes.findIndex(n => n.id === designNode.id);
const detectNode = detectNodes[i];
const detectIndex = nodes.findIndex(n => n.id === detectNode.id);
return (
<div key={designNode.id} className="branch-row">
<div
className="workflow-node small"
onClick={() => handleNodeClick(designIndex)}
>
<div className="node-icon">{designNode.icon}</div>
<div className="node-title">{designNode.title}</div>
</div>
<div className="branch-connector">
<div className="branch-arrow"></div>
</div>
<div
className="workflow-node detect"
onClick={() => handleNodeClick(detectIndex)}
>
<div className="node-icon">{detectNode.icon}</div>
<div className="node-title">{detectNode.title}</div>
</div>
</div>
);
})}
</div>
</div>
</React.Fragment>
);
}
// 跳过已经在分支中显示的节点
if (node.branch || node.id.includes('-detect')) {
return null;
}
return (
<div
key={node.id}
className="workflow-node"
onClick={() => handleNodeClick(index)}
>
{(node.id === 'input' || node.id === 'output') && <span className="pulse-ring"></span>}
<div className="node-icon">{node.icon}</div>
<div className="node-title">{node.title}</div>
</div>
);
})}
</div>
</div>
) : (
<div className="detail-container">
<div className={`detail-nodes-area ${showResults[nodes[currentNode].id] ? 'compressed' : ''}`}>
<div className="detail-track" style={{
transform: `translateX(calc(50% - ${(currentNode * 280) + 100}px))`
}}>
{nodes.map((node, index) => {
const isActive = index === currentNode;
const distance = Math.abs(index - currentNode);
const isVisible = distance <= 3;
let scale = 0.6;
let opacity = 0.2;
const isCompressed = showResults[nodes[currentNode].id];
if (isActive) {
scale = isCompressed ? 1.1 : 1.2;
opacity = 1;
} else if (distance === 1) {
scale = isCompressed ? 0.8 : 0.9;
opacity = 0.8;
} else if (distance === 2) {
scale = isCompressed ? 0.6 : 0.7;
opacity = 0.5;
} else if (distance === 3) {
scale = isCompressed ? 0.5 : 0.6;
opacity = 0.3;
}
return (
<div
key={node.id}
className={`detail-node ${isActive ? 'active' : ''} ${node.branch ? 'branch-node' : ''} ${node.id.includes('detect') ? 'detect-node' : ''}`}
onClick={() => handleNodeClick(index)}
style={{
opacity: opacity,
transform: `scale(${scale})`,
pointerEvents: isVisible ? 'auto' : 'none',
background: node.branch === 1 || node.branch === 2 || node.branch === 3 || node.branch === 4
? 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)'
: node.id.includes('detect')
? 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)'
: ''
}}
>
<div className="detail-node-icon">{node.icon}</div>
<div className="detail-node-title">{node.title}</div>
{isActive && <span className="pulse-ring"></span>}
</div>
);
})}
</div>
</div>
<div className={`detail-content-area ${showResults[nodes[currentNode].id] ? 'show' : ''}`}>
<div className="detail-content">
{(() => {
const currentNodeData = nodes[currentNode];
const detail = nodeDetails[currentNodeData.id];
// 判断是否为设计或质检节点
const isDesignOrDetectNode = ['cup', 'space', 'poster', 'merch', 'cup-detect', 'space-detect', 'poster-detect', 'merch-detect'].includes(currentNodeData.id);
// 判断是否为归纳文档节点
const isDocumentNode = currentNodeData.id === 'document';
// 收集所有图片
const allImages = [];
if (isDesignOrDetectNode && detail.results) {
detail.results.forEach(result => {
if (result.images) {
allImages.push(...result.images);
}
});
}
if (isDocumentNode) {
// 归纳文档节点只显示MD文档预览
const docResult = detail.results && detail.results[0];
return (
<div className="detail-card">
<div className="detail-header">
<div className="detail-title">{currentNodeData.title}</div>
</div>
{docResult && docResult.content && (
<div className="markdown-preview">
{renderMarkdown(docResult.content)}
</div>
)}
</div>
);
} else if (isDesignOrDetectNode && allImages.length > 0) {
// 设计和质检节点只显示图片
return (
<div className="detail-card">
<div className="detail-header">
<div className="detail-title">{currentNodeData.title}</div>
</div>
<div className={`design-images-grid ${allImages.length === 1 ? 'single-image' : ''}`}>
{allImages.map((img, idx) => (
<img
key={idx}
src={img}
alt={`效果图 ${idx + 1}`}
className="design-image"
onClick={(e) => {
e.stopPropagation();
setSelectedImage(img);
}}
/>
))}
</div>
</div>
);
} else if (isDesignOrDetectNode) {
// 没有图片的设计/质检节点
return (
<div className="detail-card">
<div className="detail-header">
<div className="detail-title">{currentNodeData.title}</div>
</div>
<p style={{textAlign: 'center', color: '#999', marginTop: '50px'}}>暂无效果图</p>
</div>
);
} else {
// 其他节点保持原样
return (
<div className="detail-card">
<div className="detail-header">
<div className="detail-title">{currentNodeData.title}</div>
</div>
<p className="detail-description">{detail.description}</p>
<div className="detail-grid">
{detail.details.map((item, i) => (
<div key={i} className="detail-item">
<div className="detail-label">{item.label}</div>
<div className="detail-value">{item.value}</div>
</div>
))}
</div>
{detail.results && (
<div className="results-section show">
<h3 style={{
fontSize: '1.3rem',
fontWeight: '700',
marginBottom: '20px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
WebkitBackgroundClip: 'text',
backgroundClip: 'text',
WebkitTextFillColor: 'transparent'
}}>设计结果</h3>
<div className="result-cards">
{detail.results.map((result, i) => (
<div key={i} className={`result-card ${result.isCode ? 'code-card' : ''} ${result.isPrompt ? 'prompt-card' : ''} ${result.isDocument ? 'document-card' : ''} ${result.isFile ? 'file-card' : ''}`}>
<div className="result-title">{result.title}</div>
{result.desc && <div className="result-desc">{result.desc}</div>}
{result.content && (
result.isCode ? (
<div className="code-content">{result.content}</div>
) : result.isPrompt ? (
<div className="prompt-content">{result.content}</div>
) : result.isDocument ? (
<div className="document-content">{result.content}</div>
) : (
<div style={{marginTop: '10px', fontSize: '0.9rem', lineHeight: '1.5'}}>
{result.content}
</div>
)
)}
{result.isFile && result.fileInfo && (
<div className="file-info">{result.fileInfo}</div>
)}
</div>
))}
</div>
</div>
)}
</div>
);
}
})()}
</div>
</div>
<div className="progress-bar">
<div
className="progress-fill"
style={{width: `${((currentNode + 1) / nodes.length) * 100}%`}}
></div>
</div>
</div>
)}
</div>
</div>
);
};
ReactDOM.createRoot(document.getElementById('root')).render(<WorkflowApp />);
</script>
</body>
</html>