diff --git a/nginx-spa.conf b/nginx-spa.conf index ee5444e..70cd167 100644 --- a/nginx-spa.conf +++ b/nginx-spa.conf @@ -45,8 +45,11 @@ server { } # all other routes fall back to index.html for React Router + # index.html 必须每次回源校验(no-cache):SPA 入口引用带 hash 的 /assets 文件, + # 部署新版后旧 hash 会被删除;浏览器缓存了旧 HTML 就会请求到 404 的 JS → 白屏。 location / { try_files $uri $uri/ /index.html; + add_header Cache-Control "no-cache"; } } diff --git a/package-lock.json b/package-lock.json index 68e84ee..9800259 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,8 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.28.0", - "tailwind-merge": "^3.0.0" + "tailwind-merge": "^3.0.0", + "three": "^0.186.0" }, "devDependencies": { "@types/node": "^24.13.3", @@ -1815,6 +1816,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/three": { + "version": "0.186.0", + "resolved": "https://registry.npmmirror.com/three/-/three-0.186.0.tgz", + "integrity": "sha512-cr/fIM2ddMSVbYVgkfD4jLJv7Fh/8ZTjvo+7gQeSVGUZHxpx9FDwoL5iC7hUz/LiRA8wMbqfnb90xKfm1/HHkQ==", + "license": "MIT" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", diff --git a/package.json b/package.json index a993544..661affe 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.28.0", - "tailwind-merge": "^3.0.0" + "tailwind-merge": "^3.0.0", + "three": "^0.186.0" }, "devDependencies": { "@types/node": "^24.13.3", diff --git a/public/baskbuddy-logo.png b/public/baskbuddy-logo.png deleted file mode 100644 index d21ae89..0000000 Binary files a/public/baskbuddy-logo.png and /dev/null differ diff --git a/public/connect-life.jpg b/public/connect-life.jpg deleted file mode 100644 index 9f27171..0000000 Binary files a/public/connect-life.jpg and /dev/null differ diff --git a/public/hero-bg.jpg b/public/hero-bg.jpg deleted file mode 100644 index ac1abc6..0000000 Binary files a/public/hero-bg.jpg and /dev/null differ diff --git a/public/innovation-hero.jpg b/public/innovation-hero.jpg deleted file mode 100644 index 5730cb1..0000000 Binary files a/public/innovation-hero.jpg and /dev/null differ diff --git a/public/office-warmth.jpg b/public/office-warmth.jpg deleted file mode 100644 index 53eb4b5..0000000 Binary files a/public/office-warmth.jpg and /dev/null differ diff --git a/public/pillar-consumer.jpg b/public/pillar-consumer.jpg deleted file mode 100644 index 28b4ab4..0000000 Binary files a/public/pillar-consumer.jpg and /dev/null differ diff --git a/public/pillar-enterprise.jpg b/public/pillar-enterprise.jpg deleted file mode 100644 index f97c0a7..0000000 Binary files a/public/pillar-enterprise.jpg and /dev/null differ diff --git a/public/pillar-future.jpg b/public/pillar-future.jpg deleted file mode 100644 index fb6da2b..0000000 Binary files a/public/pillar-future.jpg and /dev/null differ diff --git a/public/team-female.jpg b/public/team-female.jpg deleted file mode 100644 index 10c7b64..0000000 Binary files a/public/team-female.jpg and /dev/null differ diff --git a/public/team-male.jpg b/public/team-male.jpg deleted file mode 100644 index 0176c59..0000000 Binary files a/public/team-male.jpg and /dev/null differ diff --git a/src/assets/dog.svg b/src/assets/dog.svg new file mode 100644 index 0000000..91b4c23 --- /dev/null +++ b/src/assets/dog.svg @@ -0,0 +1,20 @@ + + diff --git a/src/components/EcosystemMap.tsx b/src/components/EcosystemMap.tsx index 6b8a4eb..86f49fb 100644 --- a/src/components/EcosystemMap.tsx +++ b/src/components/EcosystemMap.tsx @@ -14,7 +14,7 @@ type Aud = { c: boolean; b: boolean; f: boolean }; const MATRIX: Aud[][] = [ // 内容社交:青核 / 音酷 / 蜜恋 [{ c: true, b: false, f: false }, { c: true, b: false, f: false }, { c: true, b: false, f: false }], - // 职场服务:职来 / 看山 + // 职场服务:轻松聘 / 智愿通 [{ c: true, b: true, f: false }, { c: true, b: true, f: false }], // 数字支付:妥哒 [{ c: true, b: true, f: false }], diff --git a/src/components/Mascot.tsx b/src/components/Mascot.tsx index 76a0937..72aa288 100644 --- a/src/components/Mascot.tsx +++ b/src/components/Mascot.tsx @@ -1,6 +1,7 @@ import { useEffect, useRef, useState, useCallback } from 'react'; import { useLocation } from 'react-router-dom'; import { getLocaleFromPathname, type Locale } from '@/i18n/utils'; +import dogSvgRaw from '@/assets/dog.svg?raw'; type Mood = 'idle' | 'wave' | 'think' | 'cheer' | 'squeeze'; @@ -165,6 +166,35 @@ export default function Mascot() { const hideTimerRef = useRef(null); const idleTimerRef = useRef(null); const scrollCooldownRef = useRef(null); + const mascotBtnRef = useRef(null); + + // 视线跟随:小狗眼睛随鼠标方向轻微转动(外层 g 位移,与眨眼动画分层不冲突)。 + // 位移上限 7 个 SVG 用户单位(缩到 90px 后约 2px 屏幕位移),克制不夸张。 + useEffect(() => { + const btn = mascotBtnRef.current; + if (!btn) return; + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; + if (window.matchMedia('(hover: none)').matches) return; // 触屏无悬停语义 + let raf = 0; + const onMove = (e: PointerEvent) => { + const r = btn.getBoundingClientRect(); + const dx = e.clientX - (r.left + r.width / 2); + const dy = e.clientY - (r.top + r.height / 2); + const dist = Math.hypot(dx, dy) || 1; + const k = Math.min(dist / 240, 1) * 7; + if (raf) return; + raf = requestAnimationFrame(() => { + raf = 0; + btn.style.setProperty('--eye-x', `${((dx / dist) * k).toFixed(2)}`); + btn.style.setProperty('--eye-y', `${((dy / dist) * k).toFixed(2)}`); + }); + }; + window.addEventListener('pointermove', onMove, { passive: true }); + return () => { + window.removeEventListener('pointermove', onMove); + if (raf) cancelAnimationFrame(raf); + }; + }, []); const clearAllTimers = () => { [showTimerRef, hideTimerRef, idleTimerRef, scrollCooldownRef].forEach((r) => { @@ -350,6 +380,7 @@ export default function Mascot() { ); diff --git a/src/components/Sustainability.tsx b/src/components/Sustainability.tsx index af56a4f..8bffd6e 100644 --- a/src/components/Sustainability.tsx +++ b/src/components/Sustainability.tsx @@ -17,11 +17,11 @@ export default function Sustainability({ locale }: { locale: Locale }) { // 责任 × 产品挂钩:三方向对应 5 赛道 8 产品中的具体落点 // ti/pi = track/product 索引,与 i18n business.tracks 顺序一致 - // 0 内容社交(青核/音酷/蜜恋) · 1 职场服务(职来/看山) · 2 数字支付(妥哒) · 3 人工智能(阿布AI) · 4 生活服务(听愿) + // 0 内容社交(青核/音酷/蜜恋) · 1 职场服务(轻松聘/智愿通) · 2 数字支付(妥哒) · 3 人工智能(阿布AI) · 4 生活服务(听愿) const links = [ // 绿色低碳:阿布 AI 的算力能效 [{ ti: 3, pi: 0, role: tr('算力能效', '算力能效', 'Compute efficiency') }], - // 数字普惠:妥哒支付普惠 · 看山知识普惠 · 职来职业流动 · 听愿心愿互助 + // 数字普惠:妥哒支付普惠 · 智愿通知识普惠 · 轻松聘职业流动 · 听愿心愿互助 [ { ti: 2, pi: 0, role: tr('支付普惠', '支付普惠', 'Payment inclusion') }, { ti: 1, pi: 1, role: tr('知识普惠', '知識普惠', 'Knowledge inclusion') }, diff --git a/src/i18n/hk.ts b/src/i18n/hk.ts index 7a147cc..0c72d14 100644 --- a/src/i18n/hk.ts +++ b/src/i18n/hk.ts @@ -116,7 +116,7 @@ export const hk = { about: { title: '關於我們', subtitle: '巴適夥伴,一生相伴', - intro: `巴適夥伴(上海)科技有限公司是一家聚焦數字生活服務領域,依託多品牌、多垂直賽道的產品佈局,面向不同用戶群體提供優質產品與服務的高科技企業,透過旗下多家獨立運營的子公司,分別深耕內容社交(青核、音酷、蜜戀)、職場服務(職來、看山)、數字支付(妥噠)、人工智能(阿布 AI)、生活服務(聽願)等多個領域,始終堅持以用戶需求為核心,堅持品質第一與技術創新,為員工創造成長空間,為用戶創造美好生活,為社會創造長期價值。`, + intro: `巴適夥伴(上海)科技有限公司是一家聚焦數字生活服務領域,依託多品牌、多垂直賽道的產品佈局,面向不同用戶群體提供優質產品與服務的高科技企業,透過旗下多家獨立運營的子公司,分別深耕內容社交(青核、音酷、蜜戀)、職場服務(輕鬆聘、智願通)、數字支付(妥噠)、人工智能(阿布 AI)、生活服務(聽願)等多個領域,始終堅持以用戶需求為核心,堅持品質第一與技術創新,為員工創造成長空間,為用戶創造美好生活,為社會創造長期價值。`, visionMission: { vision: '打造全球領先的數字生活服務生態,讓不同需求的用戶都能獲得優質適配的產品體驗', mission: '以創新技術連接人與服務,依託多元垂直領域產品,為不同用戶群體打造便捷高效、富有價值的美好生活', @@ -261,8 +261,8 @@ export const hk = { color: '#1A1A1A', icon: 'briefcase', products: [ - { name: '職來', enName: 'mydreamjob', desc: '精準高效的求職服務平台——全鏈條一站式求職服務,讓求職與成長一步到位', slogan: '職來,滿足你的所有職場願望,您求職路上最信賴的同行夥伴', role: '精準求職服務平台', audience: '求職者與招聘企業', ecosystem: '成長生態 · 雙邊市場入口', icon: 'briefcase' }, - { name: '看山', enName: 'Peaksight', desc: '精準高效的升學服務平台——中學生升學路上值得信賴的人生規劃助手', slogan: '看山,幫你看見屬於自己的高山,一步一步攀登人生高峰', role: '精準升學服務平台', audience: '中學生與家長', ecosystem: '成長生態 · 升學規劃節點', icon: 'mountain' }, + { name: '輕鬆聘', enName: 'mydreamjob', desc: '精準高效的求職服務平台——全鏈條一站式求職服務,讓求職與成長一步到位', slogan: '輕鬆聘,滿足你的所有職場願望,您求職路上最信賴的同行夥伴', role: '精準求職服務平台', audience: '求職者與招聘企業', ecosystem: '成長生態 · 雙邊市場入口', icon: 'briefcase' }, + { name: '智願通', enName: 'Peaksight', desc: '精準高效的升學服務平台——中學生升學路上值得信賴的人生規劃助手', slogan: '智願通,幫你看見屬於自己的高山,一步一步攀登人生高峰', role: '精準升學服務平台', audience: '中學生與家長', ecosystem: '成長生態 · 升學規劃節點', icon: 'mountain' }, ], }, { @@ -478,7 +478,7 @@ export const hk = { contact: '聯繫我們', }, contact: { - jobs: { label: '求職諮詢', hint: '職來 · 看山團隊直招' }, + jobs: { label: '求職諮詢', hint: '輕鬆聘 · 智願通團隊直招' }, biz: { label: '商務合作', hint: '產品合作 · 市場聯動' }, email: 'baskbuddy@163.com', address: '中國 · 上海市靜安區康寧路288弄2號410室', diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index 9c11aac..3b89711 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -156,7 +156,7 @@ export const zh = { about: { title: '关于我们', subtitle: '巴适伙伴,一生相伴', - intro: `巴适伙伴(上海)科技有限公司是一家聚焦数字生活服务领域,依托多品牌、多垂直赛道的产品布局,面向不同用户群体提供优质产品与服务的高科技企业,通过旗下多家独立运营的子公司,分别深耕内容社交(青核、音酷、蜜恋)、职场服务(职来、看山)、数字支付(妥哒)、人工智能(阿布 AI)、生活服务(听愿)等多个领域,始终坚持以用户需求为核心,坚持品质第一与技术创新,为员工创造成长空间,为用户创造美好生活,为社会创造长期价值。`, + intro: `巴适伙伴(上海)科技有限公司是一家聚焦数字生活服务领域,依托多品牌、多垂直赛道的产品布局,面向不同用户群体提供优质产品与服务的高科技企业,通过旗下多家独立运营的子公司,分别深耕内容社交(青核、音酷、蜜恋)、职场服务(轻松聘、智愿通)、数字支付(妥哒)、人工智能(阿布 AI)、生活服务(听愿)等多个领域,始终坚持以用户需求为核心,坚持品质第一与技术创新,为员工创造成长空间,为用户创造美好生活,为社会创造长期价值。`, visionMission: { vision: '打造全球领先的数字生活服务生态,让不同需求的用户都能获得优质适配的产品体验', mission: '以创新技术连接人与服务,依托多元垂直领域产品,为不同用户群体打造便捷高效、富有价值的美好生活', @@ -302,8 +302,8 @@ export const zh = { color: '#1A1A1A', icon: 'briefcase', products: [ - { name: '职来', enName: 'mydreamjob', desc: '精准高效的求职服务平台——全链条一站式求职服务,让求职与成长一步到位', slogan: '职来,满足你的所有职场愿望,您求职路上最信赖的同行伙伴', role: '精准求职服务平台', audience: '求职者与招聘企业', ecosystem: '成长生态 · 双边市场入口', icon: 'briefcase' }, - { name: '看山', enName: 'Peaksight', desc: '精准高效的升学服务平台——中学生升学路上值得信赖的人生规划助手', slogan: '看山,帮你看见属于自己的高山,一步一步攀登人生高峰', role: '精准升学服务平台', audience: '中学生与家长', ecosystem: '成长生态 · 升学规划节点', icon: 'mountain' }, + { name: '轻松聘', enName: 'mydreamjob', desc: '精准高效的求职服务平台——全链条一站式求职服务,让求职与成长一步到位', slogan: '轻松聘,满足你的所有职场愿望,您求职路上最信赖的同行伙伴', role: '精准求职服务平台', audience: '求职者与招聘企业', ecosystem: '成长生态 · 双边市场入口', icon: 'briefcase' }, + { name: '智愿通', enName: 'Peaksight', desc: '精准高效的升学服务平台——中学生升学路上值得信赖的人生规划助手', slogan: '智愿通,帮你看见属于自己的高山,一步一步攀登人生高峰', role: '精准升学服务平台', audience: '中学生与家长', ecosystem: '成长生态 · 升学规划节点', icon: 'mountain' }, ], }, { @@ -519,7 +519,7 @@ export const zh = { contact: '联系我们', }, contact: { - jobs: { label: '求职咨询', hint: '职来 · 看山团队直招' }, + jobs: { label: '求职咨询', hint: '轻松聘 · 智愿通团队直招' }, biz: { label: '商务合作', hint: '产品合作 · 市场联动' }, email: 'baskbuddy@163.com', address: '中国 · 上海市静安区康宁路288弄2号410室', diff --git a/src/styles/global.css b/src/styles/global.css index 9eb6834..90167b6 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -837,6 +837,88 @@ html:lang(en) .stat-band--pair .stat-num { font-size: clamp(26px, 5.2vw, 54px); filter: drop-shadow(0 6px 14px rgba(26, 26, 26, 0.18)); } +/* 小狗吉祥物:内嵌 SVG 尺寸与灵动微动效(眨眼 / 摆耳 / 腮红呼吸 / 思考歪头) */ +.mascot-dog svg { + display: block; + width: 90px; + height: 84px; + transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1); +} +.mascot-dog .dog-eye { + transform-box: fill-box; + transform-origin: center; + animation: dogBlink 4.6s ease-in-out infinite; +} +.mascot-dog .dog-ear { + transform-box: fill-box; + animation: dogEarSway 3.4s ease-in-out infinite; +} +.mascot-dog .dog-ear-r { transform-origin: 15% 85%; } +.mascot-dog .dog-ear-l { transform-origin: 85% 85%; animation-delay: -1.7s; } +.mascot-dog .dog-blush { + transform-box: fill-box; + transform-origin: center; + animation: dogBlush 3.8s ease-in-out infinite; +} +/* 心情联动:思考时歪头 */ +.mascot-float[data-mood="think"] .mascot-dog svg { + transform: rotate(-7deg); +} +/* 悬停:好奇地微微探头(think 歪头时让位) */ +.mascot-float:hover:not([data-mood="think"]) .mascot-dog svg { + transform: rotate(-3deg); +} +/* 视线跟随层:眼睛外层 g 位移(--eye-x/--eye-y 由 JS 写在按钮上) */ +.mascot-dog .dog-eye-track { + transform-box: fill-box; + transform: translate(var(--eye-x, 0), var(--eye-y, 0)); + transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); +} +/* 被戳:眯眼笑 */ +.mascot-float[data-mood="squeeze"] .mascot-dog .dog-eye { + animation: dogSquint 0.7s ease-in-out infinite; +} +/* 欢呼:耳朵欢快小摆 */ +.mascot-float[data-mood="cheer"] .mascot-dog .dog-ear { + animation: dogEarPerk 0.55s ease-in-out infinite; +} +/* 挥手:右耳摇得更欢 */ +.mascot-float[data-mood="wave"] .mascot-dog .dog-ear-r { + animation: dogEarHi 1.6s ease-in-out infinite; +} +/* 右耳保持静止(覆盖默认摆耳 / cheer / wave 的耳朵动画) */ +.mascot-dog .dog-ear-r, +.mascot-float[data-mood="cheer"] .mascot-dog .dog-ear-r, +.mascot-float[data-mood="wave"] .mascot-dog .dog-ear-r { + animation: none; +} + +@keyframes dogSquint { + 0%, 100% { transform: scaleY(0.45); } + 50% { transform: scaleY(0.6); } +} +@keyframes dogEarPerk { + 0%, 100% { transform: rotate(-3deg); } + 50% { transform: rotate(-10deg); } +} +@keyframes dogEarHi { + 0%, 100% { transform: rotate(-6deg); } + 50% { transform: rotate(-14deg); } +} + +@keyframes dogBlink { + 0%, 91%, 100% { transform: scaleY(1); } + 94%, 96% { transform: scaleY(0.1); } +} +@keyframes dogEarSway { + 0%, 100% { transform: rotate(0deg); } + 50% { transform: rotate(-4deg); } +} +@keyframes dogBlush { + 0%, 100% { transform: scale(1); opacity: 1; } + 50% { transform: scale(1.12); opacity: 0.72; } +} + .mascot-bubble { width: min(300px, calc(100vw - 40px)); background: var(--brand-white); @@ -1051,9 +1133,16 @@ html:lang(en) .stat-band--pair .stat-num { font-size: clamp(26px, 5.2vw, 54px); .mascot-float[data-mood="cheer"] .mascot-sparks path, .mascot-float[data-mood="squeeze"] .mascot-arm, .mascot-float[data-mood="squeeze"] .mascot-dots circle, - .mascot-float[data-mood="squeeze"] .mascot-sparks path { + .mascot-float[data-mood="squeeze"] .mascot-sparks path, + .mascot-dog .dog-eye, + .mascot-dog .dog-ear, + .mascot-dog .dog-blush, + .mascot-dog .dog-eye-track { animation: none !important; } + .mascot-dog .dog-eye-track { + transform: none !important; + } } /* HERO 左下文字(h1 / p / a)在浅底 hero-bg.jpg 上的可读阴影,保证不蒙层时也清晰 */