Browse Source

fix(全站): OSS 迁移 + Mascot 右耳静止 + nginx no-cache

- public/ 下 10 张图片迁移至 OSS oss.baskbuddy.com/baskbuddy/
- dog.svg 迁入 src/assets/ 以 ?raw 方式内联
- Mascot 右耳 (dog-ear-r) 覆盖为静止(保留左耳轻摆)
- nginx-spa.conf: index.html 加 Cache-Control: no-cache 修复部署后偶发白屏
- 组件/文案/依赖更新
master
doublex001 4 weeks ago
parent
commit
5c5f5ef99b
  1. 3
      nginx-spa.conf
  2. 9
      package-lock.json
  3. 3
      package.json
  4. BIN
      public/baskbuddy-logo.png
  5. BIN
      public/connect-life.jpg
  6. BIN
      public/hero-bg.jpg
  7. BIN
      public/innovation-hero.jpg
  8. BIN
      public/office-warmth.jpg
  9. BIN
      public/pillar-consumer.jpg
  10. BIN
      public/pillar-enterprise.jpg
  11. BIN
      public/pillar-future.jpg
  12. BIN
      public/team-female.jpg
  13. BIN
      public/team-male.jpg
  14. 20
      src/assets/dog.svg
  15. 2
      src/components/EcosystemMap.tsx
  16. 112
      src/components/Mascot.tsx
  17. 4
      src/components/Sustainability.tsx
  18. 8
      src/i18n/hk.ts
  19. 8
      src/i18n/zh.ts
  20. 91
      src/styles/global.css

3
nginx-spa.conf

@ -45,8 +45,11 @@ server {
} }
# all other routes fall back to index.html for React Router # all other routes fall back to index.html for React Router
# index.html 必须每次回源校验(no-cache):SPA 入口引用带 hash 的 /assets 文件,
# 部署新版后旧 hash 会被删除;浏览器缓存了旧 HTML 就会请求到 404 的 JS → 白屏。
location / { location / {
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache";
} }
} }

9
package-lock.json

@ -14,7 +14,8 @@
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.28.0", "react-router-dom": "^6.28.0",
"tailwind-merge": "^3.0.0" "tailwind-merge": "^3.0.0",
"three": "^0.186.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^24.13.3", "@types/node": "^24.13.3",
@ -1815,6 +1816,12 @@
"url": "https://opencollective.com/webpack" "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": { "node_modules/tslib": {
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",

3
package.json

@ -16,7 +16,8 @@
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.28.0", "react-router-dom": "^6.28.0",
"tailwind-merge": "^3.0.0" "tailwind-merge": "^3.0.0",
"three": "^0.186.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^24.13.3", "@types/node": "^24.13.3",

BIN
public/baskbuddy-logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

BIN
public/connect-life.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

BIN
public/hero-bg.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

BIN
public/innovation-hero.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

BIN
public/office-warmth.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

BIN
public/pillar-consumer.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

BIN
public/pillar-enterprise.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

BIN
public/pillar-future.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 KiB

BIN
public/team-female.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

BIN
public/team-male.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

20
src/assets/dog.svg

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="vt-svg" xmlns="http://www.w3.org/2000/svg" class="vt-work" aria-hidden="true" viewBox="0 0 338 314" width="338" height="314">
<!-- 头部和耳朵轮廓 -->
<path d="M0 0 C0.74085846 -0.00458221 1.48171692 -0.00916443 2.24502563 -0.0138855 C17.52387889 -0.05130724 32.64293319 1.89550947 46.34765625 9.13671875 C57.5400761 14.95374868 68.9337079 16.79194675 81.28662109 18.95458984 C96.06208451 21.67401522 113.48880335 25.48842513 123.125 37.9375 C126.77833672 43.54666345 128.2060354 49.85555397 127.25 56.5 C125.2183392 63.84168336 121.87281333 70.60279479 115.26171875 74.74609375 C113.28242601 75.76369623 111.31127587 76.66198611 109.25 77.5 C108.87875 77.67982422 108.87875 77.67982422 107 78.58984375 C103.42211694 79.77400107 100.03689215 79.79149741 96.3125 79.75 C95.96735352 79.75386719 95.96735352 79.75386719 94.22070312 79.7734375 C89.85579982 79.7568881 86.30484502 79.09909381 82.25 77.5 C82.1984375 78.08265625 82.146875 78.6653125 82.09375 79.265625 C81.11267851 86.3560962 78.26886182 91.06195356 74.125 96.8359375 C72.57860372 99.03310888 71.40835448 101.09423613 70.25 103.5 C70.45625 103.68848511 70.45625 103.68848511 71.5 104.64233398 C104.86574028 135.21983787 104.86574028 135.21983787 105.8125 156 C105.50023253 164.56217244 102.55837178 170.67371654 96.3125 176.5 C90.58226254 181.03510414 85.66692165 181.72170862 78.51953125 181.765625 C76.25 181.5 76.25 181.5 73.25 179.5 C73.28480469 180.29019531 73.31960937 181.08039063 73.35546875 181.89453125 C73.6332774 193.46989183 72.00998437 204.69827824 69.46484375 215.98046875 C68.34035896 220.96994917 68.34035896 220.96994917 68.25 223.5 C70.125 226.125 70.125 226.125 72.25 228.5 C73.00839958 232.73765541 72.73448905 236.35252593 71.0625 240.3125 C66.3179722 246.03865424 60.60063933 249.08638658 53.21459961 249.78857422 C49.74238124 249.90293404 46.28635209 249.90915038 42.8125 249.875 C42.22436523 249.88080078 42.22436523 249.88080078 39.24804688 249.91015625 C30.82294254 249.88189989 24.08823329 248.96226287 16.9375 244.375 C11.81560837 238.89576709 10.29059931 232.64209758 8.25 225.5 C2.64 225.5 -2.97 225.5 -8.75 225.5 C-9.471875 227.68625 -10.19375 229.8725 -10.9375 232.125 C-13.40434885 239.17648704 -15.37141318 243.75037468 -22.25 247.3125 C-29.15592245 249.65558083 -35.63732279 249.74893726 -42.875 249.8125 C-43.95265625 249.84150391 -45.0303125 249.87050781 -46.140625 249.90039062 C-53.90927571 249.96122946 -62.31773231 249.25494401 -68.50097656 244.01660156 C-71.47554831 240.59806388 -72.63976634 237.66847681 -73.0625 233.1875 C-72.75 229.5 -72.75 229.5 -70.6875 226.4375 C-68.75 223.5 -68.75 223.5 -69.03515625 220.76953125 C-69.27105469 219.69058594 -69.50695312 218.61164063 -69.75 217.5 C-69.9871875 216.33984375 -70.224375 215.1796875 -70.46875 213.984375 C-70.7265625 212.75203125 -70.984375 211.5196875 -71.25 210.25 C-73.2804799 200.22962449 -73.90800617 190.71773217 -73.75 180.5 C-74.41 180.83 -75.07 181.16 -75.75 181.5 C-82.06111442 182.10999619 -88.28573157 181.97527472 -93.75 178.5 C-99.71993442 173.10165505 -103.06414666 168.25599938 -104.2265625 160.1953125 C-104.82936361 145.69635939 -98.22274721 134.1794666 -88.75 123.5 C-88.05003906 122.68144531 -87.35007813 121.86289063 -86.62890625 121.01953125 C-81.70848601 115.38279334 -76.45896786 110.3317033 -70.75 105.5 C-71.14832031 104.98050781 -71.54664063 104.46101563 -71.95703125 103.92578125 C-72.48683594 103.22839844 -73.01664063 102.53101563 -73.5625 101.8125 C-74.08457031 101.12800781 -74.60664062 100.44351563 -75.14453125 99.73828125 C-76.82342937 97.39762766 -78.29941178 94.98734496 -79.75 92.5 C-80.48863281 92.7165625 -81.22726563 92.933125 -81.98828125 93.15625 C-93.42491334 96.29514775 -103.4490575 96.89871461 -114.375 91.8125 C-120.25441524 88.20162625 -124.09694832 82.78757914 -126.75 76.5 C-127.82282095 67.43361117 -127.29007031 59.64995943 -122.109375 52.11328125 C-111.44492308 38.82342036 -94.11378771 33.32666775 -78.8515625 27.078125 C-71.59087733 24.06526505 -64.32693939 21.03387094 -58.125 16.125 C-51.50112003 11.38629893 -44.32375796 8.35002537 -36.75 5.5 C-36.08516602 5.23880371 -35.42033203 4.97760742 -34.73535156 4.70849609 C-23.36035863 0.40900314 -12.01399694 0.02764453 0 0 Z" transform="translate(169.75,30.5)" style="fill: #FDFDFC;"/>
<path d="M0 0 C2.20083982 1.82396398 4.25648601 3.65077613 6.3125 5.625 C6.89209473 6.17333496 7.47168945 6.72166992 8.06884766 7.28662109 C9.21180626 8.37119675 10.35156492 9.45915652 11.48779297 10.55078125 C12.70028949 11.7127734 13.92783979 12.85904877 15.16015625 14 C23.05301208 21.47933491 32.1383978 33.25685632 33.23828125 44.41796875 C33.40912517 50.79314462 32.98666932 55.83074069 29 61 C23.64652912 65.2609258 18.82876435 66.77331497 12 66 C9.93383789 65.32861328 9.93383789 65.32861328 8 64 C7.30224609 61.55737305 7.30224609 61.55737305 7.0234375 58.51171875 C6.91 57.41279297 6.7965625 56.31386719 6.6796875 55.18164062 C6.57914063 54.02857422 6.47859375 52.87550781 6.375 51.6875 C6.15989844 49.41997108 5.93875822 47.15300509 5.7109375 44.88671875 C5.66606201 44.3824939 5.66606201 44.3824939 5.43896484 41.83081055 C4.98967472 38.93341403 4.30740958 36.62215099 3 34 C0.875 33.1875 0.875 33.1875 -1 33 C-2.3744372 36.7675682 -1.5819258 39.40914388 -0.59765625 43.2265625 C1.22174159 51.27513799 1.58733865 59.14639312 1.5625 67.375 C1.56467529 68.11714752 1.56685059 68.85929504 1.5690918 69.62393188 C1.56380181 86.17342256 -1.28117053 101.91639221 -5 118 C-4.360625 118.28875 -3.72125 118.5775 -3.0625 118.875 C-1 120 -1 120 0 122 C0.38425932 125.53518573 0.48848801 127.32363198 -1.625 130.25 C-8.0155604 134.95883398 -15.30139449 134.33365532 -22.875 134.3125 C-24.02097656 134.32861328 -25.16695312 134.34472656 -26.34765625 134.36132812 C-32.9200482 134.36510971 -38.10425526 134.01723407 -44 131 C-45.86638491 128.47973826 -46.93610402 125.94248709 -48 123 C-48.34804687 122.04351562 -48.69609375 121.08703125 -49.0546875 120.1015625 C-49.7452489 118.18109611 -50.41847839 116.2542666 -51.0703125 114.3203125 C-52 112 -52 112 -54 110 C-56.29077148 109.74121094 -56.29077148 109.74121094 -59.12109375 109.734375 C-59.62995117 109.73308594 -59.62995117 109.73308594 -62.20507812 109.7265625 C-63.27177734 109.73429687 -64.33847656 109.74203125 -65.4375 109.75 C-66.50033203 109.74226563 -67.56316406 109.73453125 -68.65820312 109.7265625 C-69.16770508 109.72785156 -69.16770508 109.72785156 -71.74609375 109.734375 C-72.68122803 109.73663086 -73.6163623 109.73888672 -74.57983398 109.74121094 C-77 110 -77 110 -80 112 C-81.13240733 115.0867232 -82.05750023 118.15988639 -82.9296875 121.32617188 C-84.36828771 126.11046401 -86.04071305 128.93852319 -90 132 C-96.13469988 134.59003273 -102.41992027 134.33261027 -109 134.3125 C-110.05445313 134.32861328 -111.10890625 134.34472656 -112.1953125 134.36132812 C-119.18409472 134.36570706 -124.06601788 133.66495563 -129.9375 129.6875 C-131.65527844 126.95926365 -131.50344157 125.1465098 -131 122 C-129.33333333 120.33333333 -127.66666667 118.66666667 -126 117 C-126.22265625 114.8671875 -126.22265625 114.8671875 -127 112 C-127.31571641 110.69217853 -127.62792445 109.38350742 -127.9375 108.07421875 C-128.46717439 105.8823945 -128.99907241 103.69126079 -129.5390625 101.50195312 C-129.71179688 100.78330078 -129.88453125 100.06464844 -130.0625 99.32421875 C-130.21847656 98.68572998 -130.37445313 98.04724121 -130.53515625 97.3894043 C-132.13139641 89.18436101 -132.21853729 81.0230619 -132.24023438 72.6940918 C-132.24987279 70.46689517 -132.28093614 68.24065033 -132.3125 66.01367188 C-132.37385121 57.43841342 -131.62709002 49.60636027 -129.64746094 41.25415039 C-129.01487797 38.07477693 -128.88362351 35.23128521 -129 32 C-131.375 32.5625 -131.375 32.5625 -134 34 C-136.35660707 40.23807755 -136.85881713 46.85067278 -137.625 53.4375 C-137.7590625 54.55060547 -137.893125 55.66371094 -138.03125 56.81054688 C-138.35922918 59.53980223 -138.68199653 62.26956742 -139 65 C-143.61258965 66.53752988 -148.32051599 66.86704551 -153.00390625 65.3515625 C-156.72231017 63.47228277 -159.45120419 61.05217034 -161.33984375 57.2421875 C-163.59047851 49.59801975 -162.62496237 41.54690281 -159.3203125 34.39453125 C-154.68375456 25.98562588 -148.57814592 18.94181577 -142 12 C-141.13503906 11.07058594 -140.27007812 10.14117187 -139.37890625 9.18359375 C-138.94513672 8.73048828 -138.94513672 8.73048828 -136.75 6.4375 C-135.96109375 5.61121094 -135.1721875 4.78492188 -134.359375 3.93359375 C-131.73023692 1.77891933 -130.39228664 1.04740773 -127 1 C-124.65625 2.28125 -124.65625 2.28125 -122 4 C-94.37466614 14.20395215 -61.64489233 15.23612084 -33 9 C-31.50020075 8.70600526 -30.00019735 8.41305026 -28.5 8.12109375 C-20.43920632 6.46834109 -13.60486652 4.26066272 -6.41796875 0.07421875 C-3.582563 -1.18545263 -2.85071137 -1.01098027 0 0 Z" transform="translate(235,139)" style="fill: #FDFDFD;"/>
<g class="dog-ear dog-ear-r"><path d="M0 0 C8.84878122 1.25191176 17.542354 2.86791847 26.25 4.875 C27.35601562 5.11863281 28.46203125 5.36226562 29.6015625 5.61328125 C40.45340646 8.10069916 51.3379858 11.48283685 58 21 C60.65377886 25.56028425 60.75918949 29.84061022 60 35 C57.60727246 40.79396007 53.79026528 45.22762899 48.0703125 47.90234375 C37.17710424 52.10844018 27.68389391 49.80475713 17 46 C16.97421875 45.12859375 16.9484375 44.2571875 16.921875 43.359375 C15.97339101 23.44121117 15.97339101 23.44121117 9 17 C8.02505163 15.31008948 7.05294264 13.61817413 6.1171875 11.90625 C4.94716717 9.90985168 3.63778565 8.10038087 2.25 6.25 C0 3 0 3 0 0 Z" transform="translate(230,53)" style="fill: #FBE3C9;"/></g>
<g class="dog-ear dog-ear-l"><path d="M0 0 C0.66 0.33 1.32 0.66 2 1 C1.59007812 1.80824219 1.18015625 2.61648437 0.7578125 3.44921875 C0.21898437 4.51785156 -0.31984375 5.58648437 -0.875 6.6875 C-1.40867188 7.74324219 -1.94234375 8.79898438 -2.4921875 9.88671875 C-7.99458368 21.24788391 -9.47342381 32.75163432 -9.26977539 45.24633789 C-9.29955971 47.62884876 -9.39106757 49.69553033 -10 52 C-12.73046875 54.4609375 -12.73046875 54.4609375 -16 56 C-16.78761719 56.40347656 -17.57523438 56.80695313 -18.38671875 57.22265625 C-24.74263772 59.11328088 -33.31660829 59.23330305 -39.61328125 57.125 C-41.65957733 55.9170893 -43.27068712 54.62488577 -45 53 C-45.59554687 52.55011719 -46.19109375 52.10023437 -46.8046875 51.63671875 C-49.98991943 48.79643129 -50.90214505 46.68874828 -51.5078125 42.42578125 C-51.75732206 33.9341393 -50.77594169 29.62211658 -45.37890625 23.015625 C-37.45554568 15.31377774 -26.97992865 11.37284362 -17 7 C-16.14486816 6.62327148 -15.28973633 6.24654297 -14.40869141 5.85839844 C-12.04955863 4.82752469 -9.68416274 3.81417207 -7.3125 2.8125 C-6.60029297 2.50884521 -5.88808594 2.20519043 -5.15429688 1.89233398 C-3.46060542 1.19868123 -1.73243564 0.59026405 0 0 Z" transform="translate(101,61)" style="fill: #FAE2C8;"/></g>
<!-- 腮红(更浅的粉色,已避开眼睛) -->
<ellipse class="dog-blush" cx="118" cy="106" rx="16" ry="13" fill="#FFD1DC"/>
<ellipse class="dog-blush" cx="216" cy="104" rx="16" ry="13" fill="#FFD1DC"/>
<!-- 眼睛:外层 track 随鼠标视线位移;内层 eye 做眨眼/眯眼(瞳孔+高光整体压扁,闭合才自然)。
每只眼一颗主高光(左上)+ 一颗次高光(右下),眼神更亮更有神。 -->
<g class="dog-eye-track"><g class="dog-eye"><circle cx="138" cy="89" r="7" fill="#0C0B0B"/><circle cx="135.4" cy="86.4" r="2.3" fill="#FFFFFF"/><circle cx="140.3" cy="91.2" r="1.1" fill="#FFFFFF" opacity="0.7"/></g></g>
<g class="dog-eye-track"><g class="dog-eye"><circle cx="198.5" cy="87.5" r="7" fill="#0E0D0D"/><circle cx="195.9" cy="84.9" r="2.3" fill="#FFFFFF"/><circle cx="200.8" cy="89.7" r="1.1" fill="#FFFFFF" opacity="0.7"/></g></g>
<!-- 鼻子和嘴巴(恢复为原来的形状) -->
<path d="M0 0 C0.78503906 0.00515625 1.57007813 0.0103125 2.37890625 0.015625 C2.77013672 0.01304688 2.77013672 0.01304688 4.75 0 C6.94140625 0.265625 6.94140625 0.265625 9.94140625 2.265625 C9.61140625 3.915625 9.28140625 5.565625 8.94140625 7.265625 C7.95140625 7.595625 6.96140625 7.925625 5.94140625 8.265625 C7.12890625 10.765625 7.12890625 10.765625 8.94140625 13.265625 C11.50390625 13.765625 11.50390625 13.765625 13.94140625 13.265625 C14.60140625 12.275625 15.26140625 11.285625 15.94140625 10.265625 C17.26140625 10.595625 18.58140625 10.925625 19.94140625 11.265625 C20.69140625 13.515625 20.69140625 13.515625 20.94140625 16.265625 C19.28063086 18.98325746 17.86979272 20.03478296 14.7734375 20.8046875 C8.55798307 21.67667621 8.55798307 21.67667621 4.94140625 19.265625 C2.94140625 19.578125 2.94140625 19.578125 0.94140625 20.265625 C-2.77956841 21.50594989 -6.19916685 21.94008795 -10.05859375 21.265625 C-13.12109375 19.015625 -13.12109375 19.015625 -15.05859375 16.265625 C-14.87109375 13.953125 -14.87109375 13.953125 -14.05859375 12.265625 C-12.24609375 11.578125 -12.24609375 11.578125 -10.05859375 11.265625 C-9.58421875 11.760625 -9.10984375 12.255625 -8.62109375 12.765625 C-8.10546875 13.260625 -7.58984375 13.755625 -7.05859375 14.265625 C-4.37109375 13.953125 -4.37109375 13.953125 -2.05859375 13.265625 C-1.72859375 11.615625 -1.39859375 9.965625 -1.05859375 8.265625 C-1.71859375 8.265625 -2.37859375 8.265625 -3.05859375 8.265625 C-3.68359375 5.390625 -3.68359375 5.390625 -4.05859375 2.265625 C-2.05859375 0.265625 -2.05859375 0.265625 0 0 Z" transform="translate(166.05859375,85.734375)" style="fill: #101010;"/>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

2
src/components/EcosystemMap.tsx

@ -14,7 +14,7 @@ type Aud = { c: boolean; b: boolean; f: boolean };
const MATRIX: Aud[][] = [ const MATRIX: Aud[][] = [
// 内容社交:青核 / 音酷 / 蜜恋 // 内容社交:青核 / 音酷 / 蜜恋
[{ c: true, b: false, f: false }, { c: true, b: false, f: false }, { c: true, b: false, f: false }], [{ 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 }, { c: true, b: true, f: false }],
// 数字支付:妥哒 // 数字支付:妥哒
[{ c: true, b: true, f: false }], [{ c: true, b: true, f: false }],

112
src/components/Mascot.tsx

@ -1,6 +1,7 @@
import { useEffect, useRef, useState, useCallback } from 'react'; import { useEffect, useRef, useState, useCallback } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { getLocaleFromPathname, type Locale } from '@/i18n/utils'; import { getLocaleFromPathname, type Locale } from '@/i18n/utils';
import dogSvgRaw from '@/assets/dog.svg?raw';
type Mood = 'idle' | 'wave' | 'think' | 'cheer' | 'squeeze'; type Mood = 'idle' | 'wave' | 'think' | 'cheer' | 'squeeze';
@ -165,6 +166,35 @@ export default function Mascot() {
const hideTimerRef = useRef<number | null>(null); const hideTimerRef = useRef<number | null>(null);
const idleTimerRef = useRef<number | null>(null); const idleTimerRef = useRef<number | null>(null);
const scrollCooldownRef = useRef<number | null>(null); const scrollCooldownRef = useRef<number | null>(null);
const mascotBtnRef = useRef<HTMLButtonElement>(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 = () => { const clearAllTimers = () => {
[showTimerRef, hideTimerRef, idleTimerRef, scrollCooldownRef].forEach((r) => { [showTimerRef, hideTimerRef, idleTimerRef, scrollCooldownRef].forEach((r) => {
@ -350,6 +380,7 @@ export default function Mascot() {
<button <button
type="button" type="button"
ref={mascotBtnRef}
className="mascot-float" className="mascot-float"
data-mood={displayMood} data-mood={displayMood}
aria-label={ aria-label={
@ -380,81 +411,12 @@ export default function Mascot() {
}); });
}} }}
> >
<svg className="mascot-svg" viewBox="0 0 120 120" width="84" height="84" aria-hidden="true"> {/* 小狗吉祥物:内嵌 SVG(338×314),CSS 可选中耳朵/眼睛/腮红做灵动动效 */}
{/* 车身 */} <span
<rect className="mascot-body" x="20" y="34" width="80" height="54" rx="16" stroke="#1A1A1A" strokeWidth="3" /> className="mascot-svg mascot-dog"
{/* 顶灯 */} aria-hidden="true"
<rect className="mascot-accent" x="54" y="28" width="12" height="6" rx="3" /> dangerouslySetInnerHTML={{ __html: dogSvgRaw }}
{/* 车头灯(暖琥珀黄,像车灯发光) */} />
<circle className="mascot-light" cx="26" cy="66" r="3" />
{/* 风挡(车窗,圆角更柔)——浅色玻璃 + 细描边。
原为 #1A1A1A 实心黑窗,横在眼睛上会被看成"戴黑眼罩",故改浅玻璃。 */}
<rect
className="mascot-glass"
x="34"
y="45"
width="52"
height="22"
rx="11"
stroke="#1A1A1A"
strokeWidth="1.6"
/>
{/* 眼珠(深色,直接落在浅玻璃上;不再需要眼白托底) */}
<circle cx="47.5" cy="56.5" r="4.8" fill="#1A1A1A" />
<circle cx="73.5" cy="56.5" r="4.8" fill="#1A1A1A" />
{/* 高光(左上小白点,让眼睛有神) */}
<circle cx="45.8" cy="54.6" r="1.7" fill="#FFFFFF" />
<circle cx="71.8" cy="54.6" r="1.7" fill="#FFFFFF" />
{/* 微笑 */}
<path d="M42 70 Q60 80 78 70" fill="none" stroke="#1A1A1A" strokeWidth="3" strokeLinecap="round" />
{/* 车轮 */}
<circle cx="40" cy="90" r="9" fill="#1A1A1A" />
<circle cx="80" cy="90" r="9" fill="#1A1A1A" />
<circle cx="40" cy="90" r="3.2" fill="var(--mascot-accent, #C8C6E0)" />
<circle cx="80" cy="90" r="3.2" fill="var(--mascot-accent, #C8C6E0)" />
{/* 左手:始终自然垂在车身左侧(不参与挥手动画) */}
<g className="mascot-arm-left">
<line x1="22" y1="72" x2="12" y2="84" stroke="#1A1A1A" strokeWidth="4" strokeLinecap="round" />
<circle className="mascot-body" cx="10" cy="86" r="5" stroke="#1A1A1A" strokeWidth="2.5" />
</g>
{/* 右手:默认垂下,wave/squeeze 时举起挥手 */}
{(displayMood === 'wave' || displayMood === 'squeeze') ? (
<g className="mascot-arm">
<line x1="98" y1="58" x2="112" y2="38" stroke="#1A1A1A" strokeWidth="4" strokeLinecap="round" />
<circle className="mascot-body" cx="113" cy="36" r="6" stroke="#1A1A1A" strokeWidth="2.5" />
</g>
) : (
<g className="mascot-arm-right">
<line x1="98" y1="72" x2="108" y2="84" stroke="#1A1A1A" strokeWidth="4" strokeLinecap="round" />
<circle className="mascot-body" cx="110" cy="86" r="5" stroke="#1A1A1A" strokeWidth="2.5" />
</g>
)}
{/* 思考:气泡点 */}
{(displayMood === 'think' || displayMood === 'squeeze') && (
<g className="mascot-dots">
<circle className="mascot-accent" cx="58" cy="20" r="4" />
<circle className="mascot-accent" cx="68" cy="14" r="3" />
<circle className="mascot-accent" cx="77" cy="9" r="2.5" />
</g>
)}
{/* 欢呼:小星星(暖琥珀黄,光感闪耀) */}
{(displayMood === 'cheer' || displayMood === 'squeeze') && (
<g className="mascot-sparks">
<path
className="mascot-star"
d="M28 13 L29.75 18.25 L35 20 L29.75 21.75 L28 27 L26.25 21.75 L21 20 L26.25 18.25 Z"
/>
<path
className="mascot-star"
d="M94 10 L95.5 14.5 L100 16 L95.5 17.5 L94 22 L92.5 17.5 L88 16 L92.5 14.5 Z"
/>
</g>
)}
</svg>
</button> </button>
</div> </div>
); );

4
src/components/Sustainability.tsx

@ -17,11 +17,11 @@ export default function Sustainability({ locale }: { locale: Locale }) {
// 责任 × 产品挂钩:三方向对应 5 赛道 8 产品中的具体落点 // 责任 × 产品挂钩:三方向对应 5 赛道 8 产品中的具体落点
// ti/pi = track/product 索引,与 i18n business.tracks 顺序一致 // ti/pi = track/product 索引,与 i18n business.tracks 顺序一致
// 0 内容社交(青核/音酷/蜜恋) · 1 职场服务(职来/看山) · 2 数字支付(妥哒) · 3 人工智能(阿布AI) · 4 生活服务(听愿) // 0 内容社交(青核/音酷/蜜恋) · 1 职场服务(轻松聘/智愿通) · 2 数字支付(妥哒) · 3 人工智能(阿布AI) · 4 生活服务(听愿)
const links = [ const links = [
// 绿色低碳:阿布 AI 的算力能效 // 绿色低碳:阿布 AI 的算力能效
[{ ti: 3, pi: 0, role: tr('算力能效', '算力能效', 'Compute efficiency') }], [{ ti: 3, pi: 0, role: tr('算力能效', '算力能效', 'Compute efficiency') }],
// 数字普惠:妥哒支付普惠 · 看山知识普惠 · 职来职业流动 · 听愿心愿互助 // 数字普惠:妥哒支付普惠 · 智愿通知识普惠 · 轻松聘职业流动 · 听愿心愿互助
[ [
{ ti: 2, pi: 0, role: tr('支付普惠', '支付普惠', 'Payment inclusion') }, { ti: 2, pi: 0, role: tr('支付普惠', '支付普惠', 'Payment inclusion') },
{ ti: 1, pi: 1, role: tr('知识普惠', '知識普惠', 'Knowledge inclusion') }, { ti: 1, pi: 1, role: tr('知识普惠', '知識普惠', 'Knowledge inclusion') },

8
src/i18n/hk.ts

@ -116,7 +116,7 @@ export const hk = {
about: { about: {
title: '關於我們', title: '關於我們',
subtitle: '巴適夥伴,一生相伴', subtitle: '巴適夥伴,一生相伴',
intro: `巴適夥伴(上海)科技有限公司是一家聚焦數字生活服務領域,依託多品牌、多垂直賽道的產品佈局,面向不同用戶群體提供優質產品與服務的高科技企業,透過旗下多家獨立運營的子公司,分別深耕內容社交(青核、音酷、蜜戀)、職場服務(職來、看山)、數字支付(妥噠)、人工智能(阿布 AI)、生活服務(聽願)等多個領域,始終堅持以用戶需求為核心,堅持品質第一與技術創新,為員工創造成長空間,為用戶創造美好生活,為社會創造長期價值。`, intro: `巴適夥伴(上海)科技有限公司是一家聚焦數字生活服務領域,依託多品牌、多垂直賽道的產品佈局,面向不同用戶群體提供優質產品與服務的高科技企業,透過旗下多家獨立運營的子公司,分別深耕內容社交(青核、音酷、蜜戀)、職場服務(輕鬆聘、智願通)、數字支付(妥噠)、人工智能(阿布 AI)、生活服務(聽願)等多個領域,始終堅持以用戶需求為核心,堅持品質第一與技術創新,為員工創造成長空間,為用戶創造美好生活,為社會創造長期價值。`,
visionMission: { visionMission: {
vision: '打造全球領先的數字生活服務生態,讓不同需求的用戶都能獲得優質適配的產品體驗', vision: '打造全球領先的數字生活服務生態,讓不同需求的用戶都能獲得優質適配的產品體驗',
mission: '以創新技術連接人與服務,依託多元垂直領域產品,為不同用戶群體打造便捷高效、富有價值的美好生活', mission: '以創新技術連接人與服務,依託多元垂直領域產品,為不同用戶群體打造便捷高效、富有價值的美好生活',
@ -261,8 +261,8 @@ export const hk = {
color: '#1A1A1A', color: '#1A1A1A',
icon: 'briefcase', icon: 'briefcase',
products: [ products: [
{ name: '職來', enName: 'mydreamjob', desc: '精準高效的求職服務平台——全鏈條一站式求職服務,讓求職與成長一步到位', slogan: '職來,滿足你的所有職場願望,您求職路上最信賴的同行夥伴', role: '精準求職服務平台', audience: '求職者與招聘企業', ecosystem: '成長生態 · 雙邊市場入口', icon: 'briefcase' }, { name: '輕鬆聘', enName: 'mydreamjob', desc: '精準高效的求職服務平台——全鏈條一站式求職服務,讓求職與成長一步到位', slogan: '輕鬆聘,滿足你的所有職場願望,您求職路上最信賴的同行夥伴', role: '精準求職服務平台', audience: '求職者與招聘企業', ecosystem: '成長生態 · 雙邊市場入口', icon: 'briefcase' },
{ name: '看山', enName: 'Peaksight', desc: '精準高效的升學服務平台——中學生升學路上值得信賴的人生規劃助手', slogan: '看山,幫你看見屬於自己的高山,一步一步攀登人生高峰', role: '精準升學服務平台', audience: '中學生與家長', ecosystem: '成長生態 · 升學規劃節點', icon: 'mountain' }, { name: '智願通', enName: 'Peaksight', desc: '精準高效的升學服務平台——中學生升學路上值得信賴的人生規劃助手', slogan: '智願通,幫你看見屬於自己的高山,一步一步攀登人生高峰', role: '精準升學服務平台', audience: '中學生與家長', ecosystem: '成長生態 · 升學規劃節點', icon: 'mountain' },
], ],
}, },
{ {
@ -478,7 +478,7 @@ export const hk = {
contact: '聯繫我們', contact: '聯繫我們',
}, },
contact: { contact: {
jobs: { label: '求職諮詢', hint: '職來 · 看山團隊直招' }, jobs: { label: '求職諮詢', hint: '輕鬆聘 · 智願通團隊直招' },
biz: { label: '商務合作', hint: '產品合作 · 市場聯動' }, biz: { label: '商務合作', hint: '產品合作 · 市場聯動' },
email: 'baskbuddy@163.com', email: 'baskbuddy@163.com',
address: '中國 · 上海市靜安區康寧路288弄2號410室', address: '中國 · 上海市靜安區康寧路288弄2號410室',

8
src/i18n/zh.ts

@ -156,7 +156,7 @@ export const zh = {
about: { about: {
title: '关于我们', title: '关于我们',
subtitle: '巴适伙伴,一生相伴', subtitle: '巴适伙伴,一生相伴',
intro: `巴适伙伴(上海)科技有限公司是一家聚焦数字生活服务领域,依托多品牌、多垂直赛道的产品布局,面向不同用户群体提供优质产品与服务的高科技企业,通过旗下多家独立运营的子公司,分别深耕内容社交(青核、音酷、蜜恋)、职场服务(职来、看山)、数字支付(妥哒)、人工智能(阿布 AI)、生活服务(听愿)等多个领域,始终坚持以用户需求为核心,坚持品质第一与技术创新,为员工创造成长空间,为用户创造美好生活,为社会创造长期价值。`, intro: `巴适伙伴(上海)科技有限公司是一家聚焦数字生活服务领域,依托多品牌、多垂直赛道的产品布局,面向不同用户群体提供优质产品与服务的高科技企业,通过旗下多家独立运营的子公司,分别深耕内容社交(青核、音酷、蜜恋)、职场服务(轻松聘、智愿通)、数字支付(妥哒)、人工智能(阿布 AI)、生活服务(听愿)等多个领域,始终坚持以用户需求为核心,坚持品质第一与技术创新,为员工创造成长空间,为用户创造美好生活,为社会创造长期价值。`,
visionMission: { visionMission: {
vision: '打造全球领先的数字生活服务生态,让不同需求的用户都能获得优质适配的产品体验', vision: '打造全球领先的数字生活服务生态,让不同需求的用户都能获得优质适配的产品体验',
mission: '以创新技术连接人与服务,依托多元垂直领域产品,为不同用户群体打造便捷高效、富有价值的美好生活', mission: '以创新技术连接人与服务,依托多元垂直领域产品,为不同用户群体打造便捷高效、富有价值的美好生活',
@ -302,8 +302,8 @@ export const zh = {
color: '#1A1A1A', color: '#1A1A1A',
icon: 'briefcase', icon: 'briefcase',
products: [ products: [
{ name: '职来', enName: 'mydreamjob', desc: '精准高效的求职服务平台——全链条一站式求职服务,让求职与成长一步到位', slogan: '职来,满足你的所有职场愿望,您求职路上最信赖的同行伙伴', role: '精准求职服务平台', audience: '求职者与招聘企业', ecosystem: '成长生态 · 双边市场入口', icon: 'briefcase' }, { name: '轻松聘', enName: 'mydreamjob', desc: '精准高效的求职服务平台——全链条一站式求职服务,让求职与成长一步到位', slogan: '轻松聘,满足你的所有职场愿望,您求职路上最信赖的同行伙伴', role: '精准求职服务平台', audience: '求职者与招聘企业', ecosystem: '成长生态 · 双边市场入口', icon: 'briefcase' },
{ name: '看山', enName: 'Peaksight', desc: '精准高效的升学服务平台——中学生升学路上值得信赖的人生规划助手', slogan: '看山,帮你看见属于自己的高山,一步一步攀登人生高峰', role: '精准升学服务平台', audience: '中学生与家长', ecosystem: '成长生态 · 升学规划节点', icon: 'mountain' }, { name: '智愿通', enName: 'Peaksight', desc: '精准高效的升学服务平台——中学生升学路上值得信赖的人生规划助手', slogan: '智愿通,帮你看见属于自己的高山,一步一步攀登人生高峰', role: '精准升学服务平台', audience: '中学生与家长', ecosystem: '成长生态 · 升学规划节点', icon: 'mountain' },
], ],
}, },
{ {
@ -519,7 +519,7 @@ export const zh = {
contact: '联系我们', contact: '联系我们',
}, },
contact: { contact: {
jobs: { label: '求职咨询', hint: '职来 · 看山团队直招' }, jobs: { label: '求职咨询', hint: '轻松聘 · 智愿通团队直招' },
biz: { label: '商务合作', hint: '产品合作 · 市场联动' }, biz: { label: '商务合作', hint: '产品合作 · 市场联动' },
email: 'baskbuddy@163.com', email: 'baskbuddy@163.com',
address: '中国 · 上海市静安区康宁路288弄2号410室', address: '中国 · 上海市静安区康宁路288弄2号410室',

91
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)); 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 { .mascot-bubble {
width: min(300px, calc(100vw - 40px)); width: min(300px, calc(100vw - 40px));
background: var(--brand-white); 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="cheer"] .mascot-sparks path,
.mascot-float[data-mood="squeeze"] .mascot-arm, .mascot-float[data-mood="squeeze"] .mascot-arm,
.mascot-float[data-mood="squeeze"] .mascot-dots circle, .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; animation: none !important;
} }
.mascot-dog .dog-eye-track {
transform: none !important;
}
} }
/* HERO 左下文字(h1 / p / a)在浅底 hero-bg.jpg 上的可读阴影,保证不蒙层时也清晰 */ /* HERO 左下文字(h1 / p / a)在浅底 hero-bg.jpg 上的可读阴影,保证不蒙层时也清晰 */

Loading…
Cancel
Save