This commit is contained in:
256
src/App.css
256
src/App.css
@@ -1002,7 +1002,7 @@ body, html {
|
|||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 5rem;
|
padding: 0 5rem;
|
||||||
gap: 4rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-content {
|
.team-content {
|
||||||
@@ -1082,7 +1082,9 @@ body, html {
|
|||||||
/* 团队滑动组件 - 科技风 */
|
/* 团队滑动组件 - 科技风 */
|
||||||
.team-slider {
|
.team-slider {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 2rem;
|
margin-top: 0;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
margin-bottom: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-slider-viewport {
|
.team-slider-viewport {
|
||||||
@@ -1096,6 +1098,7 @@ body, html {
|
|||||||
|
|
||||||
.team-slider-track {
|
.team-slider-track {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: max-content;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
@@ -1273,7 +1276,7 @@ body, html {
|
|||||||
top: 0;
|
top: 0;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
transform: none;
|
transform: none;
|
||||||
width: 500px;
|
width: 600px;
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
background: rgba(10, 15, 28, 0.95);
|
background: rgba(10, 15, 28, 0.95);
|
||||||
border-left: 1px solid rgba(255,255,255,0.1);
|
border-left: 1px solid rgba(255,255,255,0.1);
|
||||||
@@ -1350,15 +1353,40 @@ body, html {
|
|||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 限制详情头像高度,避免占满面板导致无可滚动空间 */
|
||||||
.detail-portrait {
|
.detail-portrait {
|
||||||
width: auto;
|
width: auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 280px;
|
max-height: 280px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
margin: 0 auto 2rem auto;
|
/* margin: 0 auto 2rem auto; Removed margin, handled by wrapper now */
|
||||||
filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.3));
|
|
||||||
display: block;
|
display: block;
|
||||||
|
filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.3));
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-portrait-wrapper {
|
||||||
|
position: relative;
|
||||||
|
width: fit-content;
|
||||||
|
margin: 0 auto 2rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-floating-role {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(10, 15, 28, 0.85);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
border: 1px solid rgba(0, 245, 212, 0.3);
|
||||||
|
color: var(--primary-color);
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 5;
|
||||||
|
transform: rotate(2deg);
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-body p {
|
.detail-body p {
|
||||||
@@ -1391,23 +1419,60 @@ body, html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detail-card {
|
.detail-card {
|
||||||
background: rgba(255,255,255,0.04);
|
background: rgba(255, 255, 255, 0.03);
|
||||||
border: 1px solid rgba(255,255,255,0.08);
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||||
border-radius: 12px;
|
border-radius: 16px;
|
||||||
padding: 1.2rem;
|
padding: 1.5rem;
|
||||||
margin-bottom: 1.2rem;
|
margin-bottom: 1.5rem;
|
||||||
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-card:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border-color: rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
.detail-card h5 {
|
.detail-card h5 {
|
||||||
font-size: 0.95rem;
|
font-size: 0.9rem;
|
||||||
margin-bottom: 0.4rem;
|
text-transform: uppercase;
|
||||||
color: var(--text-primary);
|
letter-spacing: 0.05em;
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-card h5::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 4px;
|
||||||
|
height: 14px;
|
||||||
|
background: var(--primary-color);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.detail-list {
|
.detail-list {
|
||||||
padding-left: 1rem;
|
padding-left: 0;
|
||||||
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-list li {
|
.detail-list li {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.6rem;
|
||||||
|
padding-left: 1.2rem;
|
||||||
|
position: relative;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-list li::before {
|
||||||
|
content: '•';
|
||||||
|
color: var(--primary-color);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.chip-grid {
|
.chip-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1415,12 +1480,24 @@ body, html {
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
.chip {
|
.chip {
|
||||||
padding: 4px 10px;
|
padding: 6px 14px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(0, 245, 212, 0.12);
|
background: rgba(0, 245, 212, 0.08);
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
border: 1px solid rgba(0, 245, 212, 0.3);
|
border: 1px solid rgba(0, 245, 212, 0.2);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip:hover {
|
||||||
|
background: rgba(0, 245, 212, 0.15);
|
||||||
|
border-color: rgba(0, 245, 212, 0.4);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 245, 212, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-section {
|
.team-section {
|
||||||
@@ -2504,12 +2581,13 @@ body, html {
|
|||||||
|
|
||||||
/* 响应式:团队滑动卡片 */
|
/* 响应式:团队滑动卡片 */
|
||||||
.team-slider-viewport {
|
.team-slider-viewport {
|
||||||
max-width: 92vw;
|
max-width: 100vw;
|
||||||
padding: 0.5rem 0;
|
padding: 0.5rem 0;
|
||||||
|
overflow: visible; /* 允许超出视口以便看到前后卡片(需配合父容器overflow控制) */
|
||||||
}
|
}
|
||||||
.team-card {
|
.team-card {
|
||||||
width: 84vw;
|
width: 80vw;
|
||||||
min-width: 84vw;
|
min-width: 80vw;
|
||||||
height: auto;
|
height: auto;
|
||||||
aspect-ratio: 3 / 4;
|
aspect-ratio: 3 / 4;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
@@ -2534,7 +2612,7 @@ body, html {
|
|||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
border-radius: 18px 18px 0 0;
|
border-radius: 18px 18px 0 0;
|
||||||
padding-bottom: calc(env(safe-area-inset-bottom, 0) + 16px);
|
padding-bottom: calc(env(safe-area-inset-bottom, 0) + 16px);
|
||||||
max-height: 85vh;
|
max-height: 95vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.team-detail-mask { opacity: 0.7; }
|
.team-detail-mask { opacity: 0.7; }
|
||||||
@@ -2599,9 +2677,15 @@ body, html {
|
|||||||
|
|
||||||
/* 限制详情头像高度,避免占满面板导致无可滚动空间 */
|
/* 限制详情头像高度,避免占满面板导致无可滚动空间 */
|
||||||
.detail-portrait {
|
.detail-portrait {
|
||||||
max-height: 36vh;
|
max-height: 25vh;
|
||||||
height: auto;
|
height: auto;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
|
/* margin handled by wrapper now */
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-portrait-wrapper {
|
||||||
|
margin: 0 auto 1rem auto; /* Consistent margin with mobile adjustment */
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-title .subtitle {
|
.section-title .subtitle {
|
||||||
@@ -2677,3 +2761,129 @@ body, html {
|
|||||||
.team-card { width: 88vw; min-width: 88vw; aspect-ratio: 3 / 4; }
|
.team-card { width: 88vw; min-width: 88vw; aspect-ratio: 3 / 4; }
|
||||||
.member-photo { height: 66%; object-position: 50% 14%; }
|
.member-photo { height: 66%; object-position: 50% 14%; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bottom Right Controls */
|
||||||
|
.team-controls-bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 3rem;
|
||||||
|
right: 5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 1.5rem;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: rgba(0, 245, 212, 0.05);
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid rgba(0, 245, 212, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
background: var(--primary-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 8px var(--primary-color);
|
||||||
|
animation: pulse-dot 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-dot {
|
||||||
|
0% { opacity: 0.5; transform: scale(1); }
|
||||||
|
50% { opacity: 1; transform: scale(1.2); }
|
||||||
|
100% { opacity: 0.5; transform: scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-numbers {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 4px;
|
||||||
|
font-family: var(--font-sans); /* Or a monospace font if available */
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-idx {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 300;
|
||||||
|
color: var(--text-primary);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 200;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-idx {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-btn {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
color: var(--text-primary);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-btn:hover {
|
||||||
|
background: rgba(0, 245, 212, 0.1);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
color: var(--primary-color);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 245, 212, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-btn svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile adjustments */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.team-controls-bottom {
|
||||||
|
bottom: 6rem; /* Above the detail panel handle area */
|
||||||
|
right: 1.5rem;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-idx { font-size: 2rem; }
|
||||||
|
.total-idx { font-size: 1.2rem; }
|
||||||
|
.bottom-btn { width: 40px; height: 40px; }
|
||||||
|
|
||||||
|
/* Hide status on small screens if too crowded */
|
||||||
|
.control-status { display: none; }
|
||||||
|
}
|
||||||
@@ -6,19 +6,19 @@ const ContactSection = ({ isActive }) => {
|
|||||||
{
|
{
|
||||||
icon: '📧',
|
icon: '📧',
|
||||||
title: '邮件联系',
|
title: '邮件联系',
|
||||||
content: 'contact@radiant-ai.com',
|
content: 'jeremygan2021@163.com',
|
||||||
description: '7x24小时响应您的咨询'
|
description: '7x24小时响应您的咨询'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: '📞',
|
icon: '📞',
|
||||||
title: '电话咨询',
|
title: '电话咨询',
|
||||||
content: '+86 400-888-9999',
|
content: '18585164448',
|
||||||
description: '专业顾问为您答疑解惑'
|
description: '专业顾问为您答疑解惑'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: '📍',
|
icon: '📍',
|
||||||
title: '公司地址',
|
title: '公司地址',
|
||||||
content: '北京市朝阳区',
|
content: '云南省昆明市西山区云纺国际商厦 B 座 1406 号',
|
||||||
description: '欢迎莅临参观交流'
|
description: '欢迎莅临参观交流'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,53 +1,180 @@
|
|||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
|
||||||
|
const SkillIcon = ({ skill }) => {
|
||||||
|
const s = skill.toLowerCase();
|
||||||
|
|
||||||
|
// Code / Tech / Dev
|
||||||
|
if (s.includes('react') || s.includes('code') || s.includes('开发') || s.includes('embedded') || s.includes('嵌入式') || s.includes('javascript') || s.includes('技术') || s.includes('stack')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<polyline points="16 18 22 12 16 6"></polyline>
|
||||||
|
<polyline points="8 6 2 12 8 18"></polyline>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Design / Art / UI
|
||||||
|
if (s.includes('photoshop') || s.includes('design') || s.includes('设计') || s.includes('art') || s.includes('ui') || s.includes('ux')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M12 19l7-7 3 3-7 7-3-3z"></path>
|
||||||
|
<path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"></path>
|
||||||
|
<path d="M2 2l7.586 7.586"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AI / Brain / Data / Algo
|
||||||
|
if (s.includes('ai') || s.includes('智能') || s.includes('data') || s.includes('算法') || s.includes('memory') || s.includes('记忆') || s.includes('交互')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M12 2a10 10 0 1 0 10 10H12V2z"></path>
|
||||||
|
<path d="M12 2a10 10 0 0 1 10 10H12V2z" opacity="0.5"></path>
|
||||||
|
<path d="M12 12L2.5 10.5M12 12l9.5-1.5M12 12V2.5"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategy / Business / Growth / Marketing
|
||||||
|
if (s.includes('战略') || s.includes('growth') || s.includes('增长') || s.includes('market') || s.includes('市场') || s.includes('brand') || s.includes('品牌') || s.includes('manage') || s.includes('管理') || s.includes('营销') || s.includes('策划') || s.includes('经营')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M2 20h20"></path>
|
||||||
|
<path d="M5 20V8h4v12"></path>
|
||||||
|
<path d="M15 20V4h4v16"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hardware / Engineering / Structure
|
||||||
|
if (s.includes('hardware') || s.includes('硬件') || s.includes('structure') || s.includes('结构') || s.includes('reliability') || s.includes('可靠性') || s.includes('dft') || s.includes('dfm')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect>
|
||||||
|
<rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect>
|
||||||
|
<line x1="6" y1="6" x2="6.01" y2="6"></line>
|
||||||
|
<line x1="6" y1="18" x2="6.01" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process / SOP / Solution
|
||||||
|
if (s.includes('sop') || s.includes('process') || s.includes('流程') || s.includes('scheme') || s.includes('方案')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<polyline points="9 11 12 14 22 4"></polyline>
|
||||||
|
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default Star
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const RoleIcon = ({ role }) => {
|
||||||
|
const r = role.toLowerCase();
|
||||||
|
|
||||||
|
// CEO / Founder / COO / Management
|
||||||
|
if (r.includes('ceo') || r.includes('coo') || r.includes('创始人') || r.includes('总监') || r.includes('主管')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M12 2l8 4-8 4-8-4 8-4z"/>
|
||||||
|
<path d="M2 14l8 4 8-4"/>
|
||||||
|
<path d="M2 10l8 4 8-4"/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CTO / Tech / Engineer / Dev
|
||||||
|
if (r.includes('cto') || r.includes('工程师') || r.includes('技术') || r.includes('开发')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<polyline points="16 18 22 12 16 6"></polyline>
|
||||||
|
<polyline points="8 6 2 12 8 18"></polyline>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Product / Manager
|
||||||
|
if (r.includes('产品') || r.includes('经理') || r.includes('manager')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Design / Art
|
||||||
|
if (r.includes('设计') || r.includes('design') || r.includes('art')) {
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
|
<path d="M14.31 8l5.74 9.94M9.69 8h11.48M7.38 12l5.74-9.94M9.69 16L3.95 6.06M14.31 16H2.83M16.62 12l-5.74 9.94"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
|
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||||
|
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const TeamSection = ({ isActive }) => {
|
const TeamSection = ({ isActive }) => {
|
||||||
const members = useMemo(() => ([
|
const members = useMemo(() => ([
|
||||||
{
|
{
|
||||||
id: 'agan',
|
id: 'agan',
|
||||||
name: '阿甘',
|
name: '阿甘',
|
||||||
role: '创始人',
|
role: 'CEO & 创始人',
|
||||||
bio: '从0到1推动产品与战略落地,专注AI与工业融合。',
|
bio: '从0到1推动产品与战略落地,专注AI与工业融合。',
|
||||||
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/agan.png',
|
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/agan.png',
|
||||||
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/agan.png',
|
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/agan.png',
|
||||||
brandLogo: '/asset/logo-bai.png',
|
brandLogo: '/asset/logo-bai.png',
|
||||||
education: ['本科(待补充)', '硕士(待补充)'],
|
education: ['SFC 西蒙菲莎数据科学系'],
|
||||||
experience: [
|
experience: [
|
||||||
'负责公司整体战略与产品路线',
|
'负责公司整体战略与产品路线',
|
||||||
'推动跨部门协作与商业落地'
|
'推动跨部门协作与商业落地'
|
||||||
],
|
],
|
||||||
skills: ['战略规划', '产品设计', 'AI应用', '工业融合']
|
skills: ['战略规划', '产品设计', 'AI智能体', '商业融资']
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'azhi',
|
||||||
|
name: '汤炜志',
|
||||||
|
role: 'CTO & 技术总监',
|
||||||
|
bio: '深耕AI智能体控制论,团队核心技术研发带头人。',
|
||||||
|
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/azhi.png',
|
||||||
|
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/azhi.png',
|
||||||
|
brandLogo: '/asset/logo-bai.png',
|
||||||
|
education: ['本科:UBC', '硕士:3D AI重建领域论文发表(3DV)'],
|
||||||
|
experience: [
|
||||||
|
'主导核心技术智能体控制技术的攻坚',
|
||||||
|
'掌握3D AI重建技术,支持硬件IP形象建模'
|
||||||
|
],
|
||||||
|
skills: ['智能体控制', '3D AI重建', '记忆调取', '多主体交互']
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'liwei',
|
id: 'liwei',
|
||||||
name: '立伟',
|
name: '立伟',
|
||||||
role: '市场运营总监',
|
role: 'COO & 市场运营总监',
|
||||||
bio: '增长策略与品牌叙事负责人,连接产品与客户价值。',
|
bio: '增长策略与品牌叙事负责人,连接产品与客户价值。',
|
||||||
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/liwei.png',
|
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/liwei.png',
|
||||||
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/liwei.png',
|
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/liwei.png',
|
||||||
brandLogo: '/asset/logo-bai.png',
|
brandLogo: '/asset/logo-bai.png',
|
||||||
education: ['本科(待补充)'],
|
|
||||||
experience: [
|
experience: [
|
||||||
'规划年度增长与渠道策略',
|
'规划年度增长与渠道策略',
|
||||||
'打造品牌故事与市场活动'
|
'打造品牌故事与市场活动'
|
||||||
],
|
],
|
||||||
skills: ['增长策略', '品牌建设', '整合营销', '渠道拓展']
|
skills: ['增长策略', '品牌建设', '整合营销', '渠道拓展']
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'shuangji',
|
|
||||||
name: '爽吉',
|
|
||||||
role: '硬件工程师 & 硬件部门主管',
|
|
||||||
bio: '负责高可靠硬件架构设计与产线可制造性优化。',
|
|
||||||
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/shuangji.png',
|
|
||||||
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/shuangji.png',
|
|
||||||
brandLogo: '/asset/logo-bai.png',
|
|
||||||
education: ['本科(待补充)'],
|
|
||||||
experience: [
|
|
||||||
'主导多款硬件平台架构设计',
|
|
||||||
'建立DFM/DFT标准并提升良率'
|
|
||||||
],
|
|
||||||
skills: ['硬件架构', '嵌入式', 'DFM/DFT', '可靠性']
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'laoxv',
|
id: 'laoxv',
|
||||||
name: '老许',
|
name: '老许',
|
||||||
@@ -56,12 +183,53 @@ const TeamSection = ({ isActive }) => {
|
|||||||
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/laoxv.png',
|
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/laoxv.png',
|
||||||
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/laoxv.png',
|
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/laoxv.png',
|
||||||
brandLogo: '/asset/logo-bai.png',
|
brandLogo: '/asset/logo-bai.png',
|
||||||
education: ['本科(待补充)'],
|
experience: [
|
||||||
|
'硬件结构件建模设计',
|
||||||
|
'前后端运维全栈工程师'
|
||||||
|
],
|
||||||
|
skills: ['3D打印', '3D结构件建模', '后端运维', '材料学']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'shuangji',
|
||||||
|
name: '爽吉',
|
||||||
|
role: '硬件工程师 & 硬件部门主管',
|
||||||
|
bio: '负责高可靠硬件架构设计与产线可制造性优化。',
|
||||||
|
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/shuangji.png',
|
||||||
|
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/shuangji.png',
|
||||||
|
brandLogo: '/asset/logo-bai.png',
|
||||||
experience: [
|
experience: [
|
||||||
'主导多款硬件平台架构设计',
|
'主导多款硬件平台架构设计',
|
||||||
'建立DFM/DFT标准并提升良率'
|
'建立PCB/DFT标准并提升良率'
|
||||||
],
|
],
|
||||||
skills: ['硬件架构', '嵌入式', 'DFM/DFT', '可靠性']
|
skills: ['PCB设计', '嵌入式', 'C++', '固件开发']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'jingwei',
|
||||||
|
name: '经纬',
|
||||||
|
role: '产品研发经理',
|
||||||
|
bio: '技术与市场的桥梁,确保AI方案精准匹配线下场景需求。',
|
||||||
|
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/jingwei.png',
|
||||||
|
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/jingwei.png',
|
||||||
|
brandLogo: '/asset/logo-bai.png',
|
||||||
|
experience: [
|
||||||
|
'主导餐饮、办公、政务等场景的AI方案设计',
|
||||||
|
'3D空间智能资深产品经理,将技术转化为可落地的商业产品'
|
||||||
|
],
|
||||||
|
skills: ['SOP流程化', '行业方案设计', '创新产品策划', '3D空间智能']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'xiaoma',
|
||||||
|
name: '小马',
|
||||||
|
role: '全栈工程师',
|
||||||
|
bio: '全链路技术开发多面手,支撑AI交互体验的流畅性与完整性。',
|
||||||
|
avatar: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/xiaoma.png',
|
||||||
|
portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/xiaoma.png',
|
||||||
|
brandLogo: '/asset/logo-bai.png',
|
||||||
|
experience: [
|
||||||
|
'负责前端页面设计,打造AI小程序、硬件配套的交互界面',
|
||||||
|
'主导后端API服务开发,保障软件与硬件的无缝对接'
|
||||||
|
],
|
||||||
|
skills: ['React', 'Photoshop', 'JavaScript', '全栈开发']
|
||||||
}
|
}
|
||||||
|
|
||||||
]), []);
|
]), []);
|
||||||
@@ -70,29 +238,51 @@ const TeamSection = ({ isActive }) => {
|
|||||||
const trackRef = useRef(null);
|
const trackRef = useRef(null);
|
||||||
const firstCardRef = useRef(null);
|
const firstCardRef = useRef(null);
|
||||||
const [slideStep, setSlideStep] = useState(0);
|
const [slideStep, setSlideStep] = useState(0);
|
||||||
|
const [centerOffset, setCenterOffset] = useState(0);
|
||||||
const CARD_GAP = 24; // 与样式中的间距保持一致
|
const CARD_GAP = 24; // 与样式中的间距保持一致
|
||||||
const [selected, setSelected] = useState(null);
|
const [selected, setSelected] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const measure = () => {
|
const measure = () => {
|
||||||
if (!firstCardRef.current) return;
|
if (!firstCardRef.current || !trackRef.current) return;
|
||||||
const rect = firstCardRef.current.getBoundingClientRect();
|
const cardRect = firstCardRef.current.getBoundingClientRect();
|
||||||
const step = Math.round(rect.width + CARD_GAP);
|
// 获取视口宽度(父容器宽度)
|
||||||
|
const viewportWidth = trackRef.current.parentElement.offsetWidth;
|
||||||
|
|
||||||
|
const step = Math.round(cardRect.width + CARD_GAP);
|
||||||
|
// 计算居中偏移量:(视口宽度 - 卡片宽度) / 2
|
||||||
|
const offset = (viewportWidth - cardRect.width) / 2;
|
||||||
|
|
||||||
setSlideStep(step);
|
setSlideStep(step);
|
||||||
|
setCenterOffset(offset);
|
||||||
};
|
};
|
||||||
|
// 初始测量
|
||||||
measure();
|
measure();
|
||||||
|
// 延时测量确保布局稳定
|
||||||
|
const timer = setTimeout(measure, 100);
|
||||||
|
|
||||||
window.addEventListener('resize', measure);
|
window.addEventListener('resize', measure);
|
||||||
return () => window.removeEventListener('resize', measure);
|
return () => {
|
||||||
|
window.removeEventListener('resize', measure);
|
||||||
|
clearTimeout(timer);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const goPrev = () => setIndex((prev) => (prev - 1 + members.length) % members.length);
|
const goPrev = () => setIndex((prev) => (prev - 1 + members.length) % members.length);
|
||||||
const goNext = () => setIndex((prev) => (prev + 1) % members.length);
|
const goNext = () => setIndex((prev) => (prev + 1) % members.length);
|
||||||
|
|
||||||
const handleDragEnd = (_e, info) => {
|
const handleDragEnd = (_e, info) => {
|
||||||
const threshold = 80;
|
const offsetThreshold = 40; // 降低滑动阈值,更容易触发
|
||||||
if (info.offset.x < -threshold) {
|
const velocityThreshold = 100; // 速度阈值,快速轻扫也能切换
|
||||||
|
|
||||||
|
const { offset, velocity } = info;
|
||||||
|
|
||||||
|
// 向左滑动 (下一张)
|
||||||
|
if (offset.x < -offsetThreshold || velocity.x < -velocityThreshold) {
|
||||||
goNext();
|
goNext();
|
||||||
} else if (info.offset.x > threshold) {
|
}
|
||||||
|
// 向右滑动 (上一张)
|
||||||
|
else if (offset.x > offsetThreshold || velocity.x > velocityThreshold) {
|
||||||
goPrev();
|
goPrev();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -185,9 +375,10 @@ const TeamSection = ({ isActive }) => {
|
|||||||
className="team-slider-track"
|
className="team-slider-track"
|
||||||
drag="x"
|
drag="x"
|
||||||
dragConstraints={{ left: 0, right: 0 }}
|
dragConstraints={{ left: 0, right: 0 }}
|
||||||
|
dragElastic={0.2}
|
||||||
onDragEnd={handleDragEnd}
|
onDragEnd={handleDragEnd}
|
||||||
animate={{ x: -index * slideStep }}
|
animate={{ x: centerOffset - index * slideStep }}
|
||||||
transition={{ type: 'spring', stiffness: 120, damping: 18 }}
|
transition={{ type: 'spring', stiffness: 150, damping: 20 }}
|
||||||
>
|
>
|
||||||
{members.map((m, i) => (
|
{members.map((m, i) => (
|
||||||
<div
|
<div
|
||||||
@@ -254,7 +445,13 @@ const TeamSection = ({ isActive }) => {
|
|||||||
<div className="detail-role">{selected.role}</div>
|
<div className="detail-role">{selected.role}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<img src={selected.portrait || selected.avatar} alt={selected.name} className="detail-portrait" />
|
<div className="detail-portrait-wrapper">
|
||||||
|
<img src={selected.portrait || selected.avatar} alt={selected.name} className="detail-portrait" />
|
||||||
|
<div className="detail-floating-role">
|
||||||
|
<RoleIcon role={selected.role} />
|
||||||
|
<span>{selected.role}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="detail-body detail-scroller">
|
<div className="detail-body detail-scroller">
|
||||||
{selected.bio && (
|
{selected.bio && (
|
||||||
<div className="detail-card">
|
<div className="detail-card">
|
||||||
@@ -274,7 +471,7 @@ const TeamSection = ({ isActive }) => {
|
|||||||
)}
|
)}
|
||||||
{selected.experience && selected.experience.length > 0 && (
|
{selected.experience && selected.experience.length > 0 && (
|
||||||
<div className="detail-card">
|
<div className="detail-card">
|
||||||
<h5>过往经历</h5>
|
<h5>职业经历</h5>
|
||||||
<ul className="detail-list">
|
<ul className="detail-list">
|
||||||
{selected.experience.map((e, i) => (
|
{selected.experience.map((e, i) => (
|
||||||
<li key={i}>{e}</li>
|
<li key={i}>{e}</li>
|
||||||
@@ -287,7 +484,10 @@ const TeamSection = ({ isActive }) => {
|
|||||||
<h5>擅长技能</h5>
|
<h5>擅长技能</h5>
|
||||||
<div className="chip-grid">
|
<div className="chip-grid">
|
||||||
{selected.skills.map((s, i) => (
|
{selected.skills.map((s, i) => (
|
||||||
<span className="chip" key={i}>{s}</span>
|
<span className="chip" key={i}>
|
||||||
|
<SkillIcon skill={s} />
|
||||||
|
{s}
|
||||||
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user