From faa50e0dd573fbe3426800055ac878b205ce6bf7 Mon Sep 17 00:00:00 2001 From: jeremygan2021 Date: Fri, 13 Feb 2026 23:17:54 +0800 Subject: [PATCH] test --- src/App.css | 256 ++++++++++++++++++++++++++--- src/components/ContactSection.js | 6 +- src/components/TeamSection.js | 270 +++++++++++++++++++++++++++---- 3 files changed, 471 insertions(+), 61 deletions(-) diff --git a/src/App.css b/src/App.css index 9d818d3..1b3414f 100644 --- a/src/App.css +++ b/src/App.css @@ -1002,7 +1002,7 @@ body, html { grid-template-columns: 1fr 1fr; align-items: center; padding: 0 5rem; - gap: 4rem; + gap: 1rem; } .team-content { @@ -1082,7 +1082,9 @@ body, html { /* 团队滑动组件 - 科技风 */ .team-slider { width: 100%; - margin-top: 2rem; + margin-top: 0; + grid-column: 1 / -1; + margin-bottom: 4rem; } .team-slider-viewport { @@ -1096,6 +1098,7 @@ body, html { .team-slider-track { display: flex; + width: max-content; gap: 24px; will-change: transform; } @@ -1273,7 +1276,7 @@ body, html { top: 0; height: 100vh; transform: none; - width: 500px; + width: 600px; max-width: 90vw; background: rgba(10, 15, 28, 0.95); border-left: 1px solid rgba(255,255,255,0.1); @@ -1350,15 +1353,40 @@ body, html { opacity: 0.9; } +/* 限制详情头像高度,避免占满面板导致无可滚动空间 */ .detail-portrait { width: auto; max-width: 100%; max-height: 280px; object-fit: contain; background: transparent; - margin: 0 auto 2rem auto; - filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.3)); + /* margin: 0 auto 2rem auto; Removed margin, handled by wrapper now */ 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 { @@ -1391,23 +1419,60 @@ body, html { } .detail-card { - background: rgba(255,255,255,0.04); - border: 1px solid rgba(255,255,255,0.08); - border-radius: 12px; - padding: 1.2rem; - margin-bottom: 1.2rem; + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 16px; + padding: 1.5rem; + 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 { - font-size: 0.95rem; - margin-bottom: 0.4rem; - color: var(--text-primary); + font-size: 0.9rem; + text-transform: uppercase; + 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 { - padding-left: 1rem; + padding-left: 0; + list-style: none; } + .detail-list li { 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 { display: flex; @@ -1415,12 +1480,24 @@ body, html { gap: 6px; } .chip { - padding: 4px 10px; + padding: 6px 14px; border-radius: 999px; - background: rgba(0, 245, 212, 0.12); + background: rgba(0, 245, 212, 0.08); 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; + 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 { @@ -2504,12 +2581,13 @@ body, html { /* 响应式:团队滑动卡片 */ .team-slider-viewport { - max-width: 92vw; + max-width: 100vw; padding: 0.5rem 0; + overflow: visible; /* 允许超出视口以便看到前后卡片(需配合父容器overflow控制) */ } .team-card { - width: 84vw; - min-width: 84vw; + width: 80vw; + min-width: 80vw; height: auto; aspect-ratio: 3 / 4; border-radius: 16px; @@ -2534,7 +2612,7 @@ body, html { max-width: 100vw; border-radius: 18px 18px 0 0; padding-bottom: calc(env(safe-area-inset-bottom, 0) + 16px); - max-height: 85vh; + max-height: 95vh; overflow: hidden; } .team-detail-mask { opacity: 0.7; } @@ -2599,9 +2677,15 @@ body, html { /* 限制详情头像高度,避免占满面板导致无可滚动空间 */ .detail-portrait { - max-height: 36vh; + max-height: 25vh; height: auto; 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 { @@ -2677,3 +2761,129 @@ body, html { .team-card { width: 88vw; min-width: 88vw; aspect-ratio: 3 / 4; } .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; } +} \ No newline at end of file diff --git a/src/components/ContactSection.js b/src/components/ContactSection.js index 9996c26..9f87ef3 100644 --- a/src/components/ContactSection.js +++ b/src/components/ContactSection.js @@ -6,19 +6,19 @@ const ContactSection = ({ isActive }) => { { icon: '📧', title: '邮件联系', - content: 'contact@radiant-ai.com', + content: 'jeremygan2021@163.com', description: '7x24小时响应您的咨询' }, { icon: '📞', title: '电话咨询', - content: '+86 400-888-9999', + content: '18585164448', description: '专业顾问为您答疑解惑' }, { icon: '📍', title: '公司地址', - content: '北京市朝阳区', + content: '云南省昆明市西山区云纺国际商厦 B 座 1406 号', description: '欢迎莅临参观交流' } ]; diff --git a/src/components/TeamSection.js b/src/components/TeamSection.js index bef59e6..f80ad77 100644 --- a/src/components/TeamSection.js +++ b/src/components/TeamSection.js @@ -1,53 +1,180 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; 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 ( + + + + + ); + } + + // Design / Art / UI + if (s.includes('photoshop') || s.includes('design') || s.includes('设计') || s.includes('art') || s.includes('ui') || s.includes('ux')) { + return ( + + + + + + ); + } + + // AI / Brain / Data / Algo + if (s.includes('ai') || s.includes('智能') || s.includes('data') || s.includes('算法') || s.includes('memory') || s.includes('记忆') || s.includes('交互')) { + return ( + + + + + + ); + } + + // 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 ( + + + + + + ); + } + + // 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 ( + + + + + + + ); + } + + // Process / SOP / Solution + if (s.includes('sop') || s.includes('process') || s.includes('流程') || s.includes('scheme') || s.includes('方案')) { + return ( + + + + + ); + } + + // Default Star + return ( + + + + ); +}; + +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 ( + + + + + + ); + } + + // CTO / Tech / Engineer / Dev + if (r.includes('cto') || r.includes('工程师') || r.includes('技术') || r.includes('开发')) { + return ( + + + + + ); + } + + // Product / Manager + if (r.includes('产品') || r.includes('经理') || r.includes('manager')) { + return ( + + + + ); + } + + // Design / Art + if (r.includes('设计') || r.includes('design') || r.includes('art')) { + return ( + + + + + ); + } + + return ( + + + + + + ); +}; + const TeamSection = ({ isActive }) => { const members = useMemo(() => ([ { id: 'agan', name: '阿甘', - role: '创始人', + role: 'CEO & 创始人', bio: '从0到1推动产品与战略落地,专注AI与工业融合。', 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', brandLogo: '/asset/logo-bai.png', - education: ['本科(待补充)', '硕士(待补充)'], + education: ['SFC 西蒙菲莎数据科学系'], 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', name: '立伟', - role: '市场运营总监', + role: 'COO & 市场运营总监', bio: '增长策略与品牌叙事负责人,连接产品与客户价值。', 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', brandLogo: '/asset/logo-bai.png', - education: ['本科(待补充)'], experience: [ '规划年度增长与渠道策略', '打造品牌故事与市场活动' ], 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', 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', portrait: 'https://tangledup-ai-staging.oss-cn-shanghai.aliyuncs.com/web/quant-speed_page/public/team_image/laoxv.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: [ '主导多款硬件平台架构设计', - '建立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 firstCardRef = useRef(null); const [slideStep, setSlideStep] = useState(0); + const [centerOffset, setCenterOffset] = useState(0); const CARD_GAP = 24; // 与样式中的间距保持一致 const [selected, setSelected] = useState(null); useEffect(() => { const measure = () => { - if (!firstCardRef.current) return; - const rect = firstCardRef.current.getBoundingClientRect(); - const step = Math.round(rect.width + CARD_GAP); + if (!firstCardRef.current || !trackRef.current) return; + const cardRect = firstCardRef.current.getBoundingClientRect(); + // 获取视口宽度(父容器宽度) + const viewportWidth = trackRef.current.parentElement.offsetWidth; + + const step = Math.round(cardRect.width + CARD_GAP); + // 计算居中偏移量:(视口宽度 - 卡片宽度) / 2 + const offset = (viewportWidth - cardRect.width) / 2; + setSlideStep(step); + setCenterOffset(offset); }; + // 初始测量 measure(); + // 延时测量确保布局稳定 + const timer = setTimeout(measure, 100); + 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 goNext = () => setIndex((prev) => (prev + 1) % members.length); const handleDragEnd = (_e, info) => { - const threshold = 80; - if (info.offset.x < -threshold) { + const offsetThreshold = 40; // 降低滑动阈值,更容易触发 + const velocityThreshold = 100; // 速度阈值,快速轻扫也能切换 + + const { offset, velocity } = info; + + // 向左滑动 (下一张) + if (offset.x < -offsetThreshold || velocity.x < -velocityThreshold) { goNext(); - } else if (info.offset.x > threshold) { + } + // 向右滑动 (上一张) + else if (offset.x > offsetThreshold || velocity.x > velocityThreshold) { goPrev(); } }; @@ -185,9 +375,10 @@ const TeamSection = ({ isActive }) => { className="team-slider-track" drag="x" dragConstraints={{ left: 0, right: 0 }} + dragElastic={0.2} onDragEnd={handleDragEnd} - animate={{ x: -index * slideStep }} - transition={{ type: 'spring', stiffness: 120, damping: 18 }} + animate={{ x: centerOffset - index * slideStep }} + transition={{ type: 'spring', stiffness: 150, damping: 20 }} > {members.map((m, i) => (
{
{selected.role}
- {selected.name} +
+ {selected.name} +
+ + {selected.role} +
+
{selected.bio && (
@@ -274,7 +471,7 @@ const TeamSection = ({ isActive }) => { )} {selected.experience && selected.experience.length > 0 && (
-
过往经历
+
职业经历
    {selected.experience.map((e, i) => (
  • {e}
  • @@ -287,7 +484,10 @@ const TeamSection = ({ isActive }) => {
    擅长技能
    {selected.skills.map((s, i) => ( - {s} + + + {s} + ))}