diff --git a/.DS_Store b/.DS_Store index 66f8b2b..c47fe17 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/src/App.css b/src/App.css index 80c0067..6a6fd4b 100644 --- a/src/App.css +++ b/src/App.css @@ -45,6 +45,7 @@ margin: 0; padding: 0; box-sizing: border-box; + min-width: 0; } body, html { @@ -54,6 +55,8 @@ body, html { color: var(--text-primary); font-weight: 400; line-height: 1.6; + word-wrap: break-word; + overflow-wrap: anywhere; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; /* 移动端优化 */ @@ -518,7 +521,7 @@ body, html { .quote-line { width: 3px; - height: 80px; + height: 60px; background: var(--primary-color); flex-shrink: 0; margin-top: 0.5rem; @@ -1032,6 +1035,314 @@ body, html { gap: 1rem; } +/* 团队滑动组件 - 科技风 */ +.team-slider { + width: 100%; + margin-top: 2rem; +} + +.team-slider-viewport { + position: relative; + width: 100%; + max-width: 1040px; + overflow: hidden; + margin: 0 auto; + padding: 1rem 0; +} + +.team-slider-track { + display: flex; + gap: 24px; + will-change: transform; +} + +.team-card { + position: relative; + width: 320px; + min-width: 320px; + height: 420px; + border-radius: 20px; + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.12); + overflow: hidden; + box-shadow: 0 8px 30px rgba(0, 245, 212, 0.12); + backdrop-filter: blur(14px); + transform-style: preserve-3d; +} + +.team-card:hover { + border-color: rgba(0, 245, 212, 0.5); + box-shadow: 0 14px 40px rgba(0, 245, 212, 0.25); +} + +/* 背景网格与扫描线增强科技感 */ +.card-bg-grid { + position: absolute; + inset: 0; + background-image: linear-gradient(rgba(0, 245, 212, 0.08) 1px, transparent 1px), + linear-gradient(90deg, rgba(0, 245, 212, 0.08) 1px, transparent 1px); + background-size: 22px 22px, 22px 22px; + opacity: 0.35; + pointer-events: none; +} + +.card-scanline { + position: absolute; + left: 0; + right: 0; + top: -100%; + height: 50%; + background: linear-gradient( + to bottom, + rgba(0, 245, 212, 0) 0%, + rgba(0, 245, 212, 0.12) 50%, + rgba(0, 245, 212, 0) 100% + ); + filter: blur(1px); + animation: scan-move 5s linear infinite; + pointer-events: none; +} + +@keyframes scan-move { + 0% { transform: translateY(0); } + 100% { transform: translateY(300%); } +} + +.card-glow { + position: absolute; + inset: -30% -30% auto -30%; + height: 60%; + background: radial-gradient(circle at 50% 50%, rgba(0, 245, 212, 0.18), transparent 60%); + filter: blur(18px); + opacity: 0.7; + pointer-events: none; +} + +.member-photo { + position: absolute; + inset: 0; + width: 100%; + height: 64%; + object-fit: contain; + object-position: 50% 10%; + background: radial-gradient(circle at 50% 20%, rgba(0, 245, 212, 0.06), rgba(5,10,20,0.6)), rgba(5,10,20,0.6); + opacity: 0.98; +} + +.member-info { + position: absolute; + left: 0; + right: 0; + bottom: 0; + padding: 1.2rem 1.2rem 1.4rem 1.2rem; + background: linear-gradient(to top, rgba(5, 10, 20, 0.85), rgba(5, 10, 20, 0.2)); +} + +.member-name { + font-size: 1.4rem; + font-weight: 700; +} + +.member-role { + margin-top: 0.2rem; + color: var(--primary-color); + font-weight: 600; +} + +.member-bio-mini { + margin-top: 0.6rem; + color: var(--text-secondary); + font-size: 0.92rem; + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + line-clamp: 2; + overflow: hidden; +} + +.slider-btn { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 40px; + height: 40px; + border-radius: 50%; + border: 1px solid rgba(255, 255, 255, 0.2); + background: rgba(255, 255, 255, 0.06); + color: var(--text-primary); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: var(--transition-smooth); + z-index: 2; + backdrop-filter: blur(8px); +} + +.slider-btn:hover { + border-color: rgba(0, 245, 212, 0.6); + background: rgba(0, 245, 212, 0.12); + box-shadow: 0 6px 20px rgba(0, 245, 212, 0.25); +} + +.slider-btn.prev { left: -10px; } +.slider-btn.next { right: -10px; } + +.slider-dots { + display: flex; + gap: 8px; + position: absolute; + left: 50%; + transform: translateX(-50%); + bottom: -10px; +} + +.slider-dots .dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.35); + border: none; + cursor: pointer; + transition: var(--transition-fast); +} + +.slider-dots .dot.active { + background: var(--primary-color); + box-shadow: 0 0 12px rgba(0, 245, 212, 0.7); + transform: scale(1.2); +} + +/* 详情面板与遮罩 */ +.team-detail-mask { + position: fixed; + inset: 0; + background: #000; + z-index: 980; +} +/* //// / */ +.team-detail-panel { + position: fixed; + right: 84px; + top: 10%; + transform: translateY(-50%); + width: min(420px, 40vw); + max-width: 92vw; + background: rgba(10, 15, 28, 0.9); + border: 1px solid rgba(255,255,255,0.1); + border-radius: 16px; + box-shadow: 0 20px 50px rgba(0,0,0,0.5); + z-index: 990; + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + padding: 1.2rem; + color: var(--text-primary); + max-height: calc(100vh - 96px); + display: flex; + flex-direction: column; + overflow: hidden; +} + +.detail-close { + position: absolute; + right: 10px; + top: 8px; + width: 32px; + height: 32px; + border-radius: 50%; + border: 1px solid rgba(255,255,255,0.2); + background: rgba(255,255,255,0.06); + color: var(--text-primary); + cursor: pointer; +} + +.detail-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 0.8rem; +} + +.detail-brand { + width: 28px; + height: 28px; + object-fit: contain; + opacity: 0.9; +} + +.detail-portrait { + width: 100%; + height: auto; + object-fit: contain; + background: transparent; + margin: 6px 0 10px 0; +} + +.detail-photo { + width: 64px; + height: 64px; + object-fit: contain; + border-radius: 10px; + background: rgba(255,255,255,0.06); +} + +.detail-name { + font-size: 1.2rem; + font-weight: 700; +} + +.detail-role { + color: var(--primary-color); + font-weight: 600; + margin-top: 2px; +} + +.detail-body p { + color: var(--text-secondary); +} + +.detail-scroller { + flex: 1 1 auto; + overflow-y: auto; + padding-right: 6px; + -webkit-overflow-scrolling: touch; + overscroll-behavior: contain; +} + +.detail-card { + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.08); + border-radius: 12px; + padding: 0.9rem 1rem; + margin-bottom: 0.8rem; +} +.detail-card h5 { + font-size: 0.95rem; + margin-bottom: 0.4rem; + color: var(--text-primary); +} +.detail-list { + padding-left: 1rem; +} +.detail-list li { + color: var(--text-secondary); + margin-bottom: 0.25rem; +} +.chip-grid { + display: flex; + flex-wrap: wrap; + gap: 6px; +} +.chip { + padding: 4px 10px; + border-radius: 999px; + background: rgba(0, 245, 212, 0.12); + color: var(--primary-color); + border: 1px solid rgba(0, 245, 212, 0.3); + font-size: 0.85rem; +} + .team-section { width: 100%; max-width: 1400px; @@ -1950,6 +2261,7 @@ body, html { .hero-left, .product-content, .team-content { + top: 80%; max-width: 100%; order: 1; display: flex; @@ -1963,7 +2275,8 @@ body, html { .product-visual, .team-visual { order: 2; - margin-top: 2rem; + margin-top: 3rem; + margin-bottom: 3rem; } .hero-main-title, @@ -1972,29 +2285,36 @@ body, html { font-size: 2.5rem; line-height: 1.2; text-align: center; - margin-bottom: 1rem; + margin-bottom: -3rem; } /* 移动端下移主标题 */ .hero-main-title { - margin-top: 1.5rem; + margin-top: 3.5rem; } .hero-subtitle { - font-size: 1.5rem; + font-size: 1rem; line-height: 1.3; text-align: center; margin-bottom: 1rem; } .hero-quote, - .product-quote, + .product-quote{ + max-width: 100%; + text-align: center; + gap: 0; + align-items: center; + margin-top: 3.7rem; + } + .team-quote { max-width: 100%; text-align: center; gap: 0; align-items: center; - margin-top: 1.5rem; + margin-top: 4.7rem; } .quote-line { @@ -2045,6 +2365,17 @@ body, html { right: -40px; } + /* 团队页:移动端隐藏右侧可视容器,避免占位 */ + .team-visual-container { + display: none; + } + + /* 同时移除父容器的固定高度与外边距,防止留白 */ + .team-visual { + height: auto; + margin-top: 0; + } + .hero-progress, .product-progress, .team-progress { @@ -2065,6 +2396,42 @@ body, html { justify-content: center; margin-top: 0.5rem; } + + /* 响应式:团队滑动卡片 */ + .team-slider-viewport { + max-width: 92vw; + padding: 0.5rem 0; + } + .team-card { + width: 84vw; + min-width: 84vw; + height: auto; + aspect-ratio: 3 / 4; + border-radius: 16px; + } + .member-photo { + height: 65%; + object-fit: contain; + object-position: 50% 12%; + } + .slider-btn.prev { left: 6px; } + .slider-btn.next { right: 6px; } + + /* 移动端:详情底部弹层 */ + .team-detail-panel { + right: 0; + left: 0; + transform: translateY(0); + bottom: 0; + top: auto; + width: 100vw; + max-width: 100vw; + border-radius: 18px 18px 0 0; + padding-bottom: calc(env(safe-area-inset-bottom, 0) + 16px); + max-height: 85vh; + overflow: hidden; + } + .team-detail-mask { opacity: 0.7; } } /* 小屏幕设备额外优化 */ @@ -2088,16 +2455,19 @@ body, html { } .hero-main-title, - .product-main-title, + .product-main-title{ + font-size: 2rem; + line-height: 1.1; + margin-bottom: -1rem; + } + .team-main-title { font-size: 2rem; line-height: 1.1; + margin-bottom: -5rem; } - /* 超小屏进一步下移主标题 */ - .hero-main-title { - margin-top: 2rem; - } + /* 保持主标题在超小屏的统一样式,避免重复覆盖 */ .hero-subtitle { font-size: 1.3rem; @@ -2114,18 +2484,21 @@ body, html { .visual-container, .team-visual-container { width: 300px; - height: 300px; + height: 200px; + } + + /* 限制详情头像高度,避免占满面板导致无可滚动空间 */ + .detail-portrait { + max-height: 36vh; + height: auto; + object-fit: contain; } .section-title .subtitle { opacity: 0.5; margin-top: 0.2rem; } - - -.hero-main-title { - margin-top: 4rem; - } + /* 移除重复的 hero-main-title 顶部外边距设置,统一用上方规则控制 */ .cube-main { width: 100px; @@ -2189,4 +2562,8 @@ body, html { width: 10px; height: 10px; } + /* 超小屏:团队滑动卡片 */ + .team-slider-viewport { max-width: 94vw; } + .team-card { width: 88vw; min-width: 88vw; aspect-ratio: 3 / 4; } + .member-photo { height: 66%; object-position: 50% 14%; } } diff --git a/src/App.js b/src/App.js index 1151bbb..ca90fae 100644 --- a/src/App.js +++ b/src/App.js @@ -14,6 +14,15 @@ const App = () => { const [isScrolling, setIsScrolling] = useState(false); const isScrollingRef = useRef(false); const currentSectionRef = useRef(0); + const isTouchInDetailPanelRef = useRef(false); + + const isEventFromDetailPanel = (target) => { + if (!target) return false; + if (typeof target.closest === 'function') { + return !!(target.closest('.team-detail-panel') || target.closest('.detail-scroller')); + } + return false; + }; const { scrollYProgress } = useScroll({ target: containerRef, @@ -40,6 +49,9 @@ const App = () => { let touchEndY = 0; const handleWheel = (e) => { + if (isEventFromDetailPanel(e.target)) { + return; + } e.preventDefault(); // 如果正在滚动中,忽略新的滚动事件 @@ -78,14 +90,22 @@ const App = () => { // 触摸事件处理 const handleTouchStart = (e) => { + isTouchInDetailPanelRef.current = isEventFromDetailPanel(e.target); touchStartY = e.touches[0].clientY; }; const handleTouchMove = (e) => { + if (isTouchInDetailPanelRef.current) { + return; + } e.preventDefault(); }; const handleTouchEnd = (e) => { + if (isTouchInDetailPanelRef.current) { + isTouchInDetailPanelRef.current = false; + return; + } if (isScrollingRef.current) { return; } diff --git a/src/components/TeamSection.js b/src/components/TeamSection.js index 4cfc423..85dc820 100644 --- a/src/components/TeamSection.js +++ b/src/components/TeamSection.js @@ -1,7 +1,105 @@ -import React from 'react'; -import { motion } from 'framer-motion'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; const TeamSection = ({ isActive }) => { + const members = useMemo(() => ([ + { + id: 'agan', + name: '阿甘', + role: '创始人', + bio: '从0到1推动产品与战略落地,专注AI与工业融合。', + avatar: '/team_image/agan.png', + portrait: '/team_image/agan.png', + brandLogo: '/asset/logo-bai.png', + education: ['本科(待补充)', '硕士(待补充)'], + experience: [ + '负责公司整体战略与产品路线', + '推动跨部门协作与商业落地' + ], + skills: ['战略规划', '产品设计', 'AI应用', '工业融合'] + }, + { + id: 'liwei', + name: '立伟', + role: '市场运营总监', + bio: '增长策略与品牌叙事负责人,连接产品与客户价值。', + avatar: '/team_image/liwei.png', + portrait: '/team_image/liwei.png', + brandLogo: '/asset/logo-bai.png', + education: ['本科(待补充)'], + experience: [ + '规划年度增长与渠道策略', + '打造品牌故事与市场活动' + ], + skills: ['增长策略', '品牌建设', '整合营销', '渠道拓展'] + }, + { + id: 'shuangji', + name: '爽吉', + role: '硬件工程师 & 硬件部门主管', + bio: '负责高可靠硬件架构设计与产线可制造性优化。', + avatar: '/team_image/shuangji.png', + portrait: '/team_image/shuangji.png', + brandLogo: '/asset/logo-bai.png', + education: ['本科(待补充)'], + experience: [ + '主导多款硬件平台架构设计', + '建立DFM/DFT标准并提升良率' + ], + skills: ['硬件架构', '嵌入式', 'DFM/DFT', '可靠性'] + }, + { + id: 'laoxv', + name: '老许', + role: '工业设计工程师 & 结构件工程师', + bio: '负责高可靠硬件架构设计与产线可制造性优化。', + avatar: '/team_image/laoxv.png', + portrait: '/team_image/laoxv.png', + brandLogo: '/asset/logo-bai.png', + education: ['本科(待补充)'], + experience: [ + '主导多款硬件平台架构设计', + '建立DFM/DFT标准并提升良率' + ], + skills: ['硬件架构', '嵌入式', 'DFM/DFT', '可靠性'] + } + + ]), []); + + const [index, setIndex] = useState(0); + const trackRef = useRef(null); + const firstCardRef = useRef(null); + const [slideStep, setSlideStep] = 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); + setSlideStep(step); + }; + measure(); + window.addEventListener('resize', measure); + return () => window.removeEventListener('resize', measure); + }, []); + + 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) { + goNext(); + } else if (info.offset.x > threshold) { + goPrev(); + } + }; + + const openDetail = (member) => setSelected(member); + const closeDetail = () => setSelected(null); + return (
{ animate={isActive ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.8, delay: 0.6 }} > - 团队专业 + 量迹AI
- 知识 + 2025
- 与经验 + Team {
+ {/* 科技感人员滑动卡片 */} + +
+ + {members.map((m, i) => ( +
openDetail(m)} + > +
+
+
+ {m.name} +
+
{m.name}
+
{m.role}
+
{m.bio}
+
+
+ ))} + + + +
+ {members.map((m, i) => ( +
+
+ + + {/* 详情面板(桌面端右侧 / 移动端底部弹层) */} + + {selected && ( + <> + + + +
+ brand +
+
{selected.name}
+
{selected.role}
+
+
+ {selected.name} +
+ {selected.bio && ( +
+
简介
+

{selected.bio}

+
+ )} + {selected.education && selected.education.length > 0 && ( +
+
毕业院校
+
    + {selected.education.map((e, i) => ( +
  • {e}
  • + ))} +
+
+ )} + {selected.experience && selected.experience.length > 0 && ( +
+
过往经历
+
    + {selected.experience.map((e, i) => ( +
  • {e}
  • + ))} +
+
+ )} + {selected.skills && selected.skills.length > 0 && ( +
+
擅长技能
+
+ {selected.skills.map((s, i) => ( + {s} + ))} +
+
+ )} +
+
+ + )} +
+ {/* 进度指示器 */}