Compare commits
32 Commits
c49b5044d9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f51d3b98a4 | ||
|
|
faa50e0dd5 | ||
|
|
4cd4fc8ebd | ||
|
|
da2ded71ad | ||
|
|
4cdcafa01c | ||
|
|
fd247e8c0a | ||
|
|
086943f0d5 | ||
|
|
d9cd3769e7 | ||
|
|
e6503ea9e4 | ||
|
|
7ff83a0231 | ||
|
|
91f97d2487 | ||
|
|
b8159d45ed | ||
|
|
7a6fa9cfc8 | ||
|
|
fdd8dc0c06 | ||
|
|
38e5c377d2 | ||
|
|
97ff5e1be9 | ||
|
|
5328f88ad3 | ||
|
|
d5bdaf8b0d | ||
|
|
ea63e56f96 | ||
|
|
0aef752ea3 | ||
|
|
6472d206ee | ||
|
|
fc7b7c9b51 | ||
|
|
bf91b1c53d | ||
|
|
0a02fa0cc9 | ||
|
|
fef1f0e9ac | ||
|
|
d4bacf669a | ||
|
|
2874a7d686 | ||
|
|
f89735dda2 | ||
|
|
1262ba1f9f | ||
|
|
9fae65be6a | ||
|
|
417f282e8f | ||
|
|
eda6ac25b5 |
BIN
.gitea/.DS_Store
vendored
Normal file
BIN
.gitea/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -5,6 +5,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
@@ -13,7 +15,8 @@ jobs:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: actions/checkout@v3
|
||||
# 使用 gitea.com 镜像源以解决 GitHub 连接问题
|
||||
uses: https://gitea.com/actions/checkout@v3
|
||||
|
||||
# 1. 登录 Docker Registry (已跳过,无密码模式)1
|
||||
# - name: 登录到私有 Registry
|
||||
@@ -25,34 +28,40 @@ jobs:
|
||||
|
||||
# 2. 构建并推送镜像
|
||||
- name: 配置 Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
# 使用 gitea.com 镜像源以解决 GitHub 连接问题
|
||||
uses: https://gitea.com/docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver-opts: network=host
|
||||
buildkitd-flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
|
||||
config-inline: |
|
||||
[registry."docker.io"]
|
||||
mirrors = ["https://docker.m.daocloud.io", "https://dockerproxy.com"]
|
||||
mirrors = ["https://docker.1panel.live", "https://dockerproxy.com", "https://docker.1panel.dev"]
|
||||
[registry."121.43.104.161:6500"]
|
||||
http = true
|
||||
insecure = true
|
||||
|
||||
- name: 构建并推送 Docker 镜像
|
||||
uses: docker/build-push-action@v4
|
||||
# 使用 gitea.com 镜像源以解决 GitHub 连接问题
|
||||
uses: https://gitea.com/docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
# 镜像标签,推送到私有 Registry
|
||||
# 镜像标签,推送到私有 Registry/1
|
||||
tags: 121.43.104.161:6500/quant-speed-page:latest
|
||||
|
||||
# 3. 部署到服务器
|
||||
# 3. 部署到服务器/
|
||||
- name: 部署到服务器
|
||||
# uses: appleboy/ssh-action@master
|
||||
# 换用 garygrossgarten/github-action-ssh,它不依赖外部下载
|
||||
uses: garygrossgarten/github-action-ssh@release
|
||||
env:
|
||||
QUANT_PASSWORD: ${{ secrets.QUANT_PASSWORD }}
|
||||
with:
|
||||
host: 121.40.192.128
|
||||
port: 22
|
||||
username: root
|
||||
password: 123quant-speed
|
||||
# password: ${{ secrets.QUANT_PASSWORD }}
|
||||
command: |
|
||||
# 停止并删除旧容器
|
||||
docker stop quant-speed-page || true
|
||||
@@ -62,8 +71,15 @@ jobs:
|
||||
docker pull 121.43.104.161:6500/quant-speed-page:latest
|
||||
|
||||
# 启动新容器
|
||||
# 映射端口 3000:80 (宿主机 3000 -> 容器 80)
|
||||
# 添加日志限制防止磁盘写满
|
||||
docker run -d \
|
||||
--name quant-speed-page \
|
||||
--restart unless-stopped \
|
||||
-p 80:80 \
|
||||
--log-opt max-size=10m \
|
||||
--log-opt max-file=3 \
|
||||
-p 3000:80 \
|
||||
121.43.104.161:6500/quant-speed-page:latest
|
||||
|
||||
# 清理无用的旧镜像
|
||||
docker image prune -f
|
||||
|
||||
64
.github/workflows/deploy.yaml
vendored
Normal file
64
.github/workflows/deploy.yaml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: 构建并部署 (Docker Hub)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 设置 Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: 登录到 Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: jeremygan2021
|
||||
password: 123quant-speed
|
||||
|
||||
- name: 构建并推送 Docker 镜像
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
# 使用 Docker Hub 用户名作为镜像前缀
|
||||
tags: jeremygan2021/quant-speed-page:latest
|
||||
|
||||
- name: 部署到服务器
|
||||
uses: appleboy/ssh-action@master
|
||||
env:
|
||||
DOCKERHUB_USERNAME: jeremygan2021
|
||||
with:
|
||||
host: 121.40.192.128
|
||||
username: root
|
||||
# 建议在 GitHub Secrets 配置 SSH_PASSWORD,这里保留硬编码仅作演示
|
||||
password: 123quant-speed
|
||||
port: 22
|
||||
# 将 Docker Hub 用户名传递给 SSH 脚本
|
||||
envs: DOCKERHUB_USERNAME
|
||||
script: |
|
||||
# 停止并删除旧容器
|
||||
docker stop quant-speed-page || true
|
||||
docker rm quant-speed-page || true
|
||||
|
||||
# 拉取最新镜像 (从 Docker Hub)
|
||||
docker pull $DOCKERHUB_USERNAME/quant-speed-page:latest
|
||||
|
||||
# 启动新容器
|
||||
docker run -d \
|
||||
--name quant-speed-page \
|
||||
--restart unless-stopped \
|
||||
--log-opt max-size=10m \
|
||||
--log-opt max-file=3 \
|
||||
-p 3000:80 \
|
||||
$DOCKERHUB_USERNAME/quant-speed-page:latest
|
||||
|
||||
# 清理无用的旧镜像
|
||||
docker image prune -f
|
||||
13
.trae/documents/plan_20260213_061302.md
Normal file
13
.trae/documents/plan_20260213_061302.md
Normal file
@@ -0,0 +1,13 @@
|
||||
I will optimize the layout for `ContactSection.js` and fix the responsive issues, including the "bottom text" visibility and mobile layout.
|
||||
|
||||
### Plan:
|
||||
1. **Modify `src/App.css` to fix layout and scrolling issues:**
|
||||
* **Enable Scrolling:** Update the `.section` class to include `overflow-y: auto` and `overflow-x: hidden`. This is critical for mobile devices where content height often exceeds the viewport, ensuring the bottom text (footer) in `ContactSection` is accessible.
|
||||
* **Optimize Mobile Layout for ContactSection:**
|
||||
* Adjust `.contact-section` margins and paddings for mobile screens (`max-width: 768px`) to reduce wasted space and ensure content fits better.
|
||||
* Tweaking `.contact-footer` spacing.
|
||||
* **Verify/Fix HeroSection Video Layout:**
|
||||
* Ensure the container for the video (`.hero-right`) has appropriate sizing on mobile so the video (`stay.mp4`) displays correctly within its container, addressing the user's concern about the "responsive layout" of that element.
|
||||
|
||||
2. **Verify the changes:**
|
||||
* I will verify the CSS changes by checking the code structure and ensuring the styles logically solve the overflow and spacing issues.
|
||||
20
.trae/documents/plan_20260213_095217.md
Normal file
20
.trae/documents/plan_20260213_095217.md
Normal file
@@ -0,0 +1,20 @@
|
||||
我已找到导致“无法正确下滑与翻页”的根本原因:代码中调用了一个未定义的函数 `getActiveScroller`,导致滚动事件处理中断。此外,滚动边界的检测逻辑需要进一步放宽容差,以适配不同设备的触控精度。
|
||||
|
||||
### 修复与优化计划
|
||||
|
||||
1. **修复运行时错误**
|
||||
- 移除未定义的 `getActiveScroller` 调用。
|
||||
- 改用更稳健的 DOM 查询方式:为每个页面容器添加 `data-index` 属性,通过当前索引精确获取对应的滚动容器。
|
||||
|
||||
2. **重构滚动边界检测(解决“卡顿”与“无法翻页”)**
|
||||
- **增加容差**:将滚动到底/到顶的判断容差从 2px 增加到 5px,解决高分屏或缩放下的精度问题。
|
||||
- **智能识别内容高度**:明确区分“长内容页面”与“短内容页面”。
|
||||
- **短页面**(无滚动条):直接允许向上/向下翻页。
|
||||
- **长页面**:仅在确实滚动到边缘时才触发翻页。
|
||||
- **精准拦截**:仅在**确认要触发翻页**时才调用 `e.preventDefault()`,确保在页面中间时完全保留原生滚动的流畅度。
|
||||
|
||||
3. **优化翻页性能**
|
||||
- 保持当前的 GPU 加速样式(will-change)。
|
||||
- 确保翻页触发后的“冷却时间”逻辑正确,防止一次滑动跳多页。
|
||||
|
||||
我将直接修改 `App.js` 实现上述逻辑,无需额外创建文件。
|
||||
@@ -1,5 +1,5 @@
|
||||
# 构建阶段
|
||||
FROM node:16-alpine AS builder
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
2185
package-lock.json
generated
2185
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,9 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="AI公司官网 - 创新科技,引领未来" />
|
||||
<title>Radiant AI - 创新科技,引领未来</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
||||
<link rel="mask-icon" href="/logo.svg" color="#000000" />
|
||||
<title>量迹AI科技</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
35
public/logo.svg
Normal file
35
public/logo.svg
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_2" data-name="图层_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 989.55 925.64">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
font-family: Krungthep, Krungthep;
|
||||
font-size: 92.87px;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #020202;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="_图层_1-2" data-name="图层_1">
|
||||
<g>
|
||||
<path class="cls-2" d="M412.28,0c21.28,5.72,40.43,15.59,58.14,28.66,7.12,5.25,12.47,11.82,17.59,18.76,1.92,2.6,4.75,5.22,3.21,8.74-1.62,3.73-5.57,2.84-8.73,2.95-16.39.58-32.74-.2-49.19,2.09-42.55,5.92-78.84,24.31-111.03,52.05-48.48,41.78-82.1,94.79-111.85,150.21-30.11,56.1-56.75,113.89-72.13,176.2-11.14,45.15-19.93,90.7-19.44,137.28.31,29.14,4.18,58.21,20.59,83.77,1.77,2.75,3.54,5.55,5.67,8.02,10.44,12.13,10.23,13.09-5.05,19.39-53.28,21.97-109.47-4.38-130.35-60.79-4.59-12.4-5.9-25.5-9.73-38.02v-27.12c2.91-18.86,3.06-37.98,4.31-56.94,2.44-36.98,12.09-72.25,22.29-107.44,19.91-68.68,49.59-132.98,88.75-192.85,18.68-28.57,39.12-55.93,62.76-80.53,35.21-36.64,68.51-75.39,113.61-101.27,23.59-13.53,48.25-21.17,75.24-21.91,2.01-.06,4.13.36,5.82-1.23h39.5Z"/>
|
||||
<path class="cls-2" d="M792.19,131.3c-16.86,4.02-33.77,6.89-49.92,12.11-60.19,19.46-111.99,51.88-154.93,98.96-55.08,60.4-107.14,123.35-158.47,186.84-48.14,59.56-99.58,115.86-154.96,168.6-22.57,21.49-45.48,42.8-71.8,59.89-22.13,14.36-41.19,9.39-52.67-14.17-11.63-23.86-13.51-49.64-13.52-75.67,0-4.89,2.35-8.34,6.05-11.5,47.42-40.54,94.77-81.15,142.07-121.83,43.56-37.47,87.81-74.19,130.38-112.76,75.92-68.77,157.11-129.65,250.52-172.89,36.83-17.05,76.31-22.18,116.48-22.94,3.81-.07,8.38-.48,10.77,5.37Z"/>
|
||||
<path class="cls-2" d="M795.46,490.45c-20.17-4.55-38.34-12.09-54.96-22.98-44.94-29.47-80.24-68.78-112.48-111.11-8.45-11.1-16-22.91-24.58-33.91-5.85-7.5-4.36-12.69,2.13-18.88,15.17-14.45,30.01-29.27,44.46-44.45,6.64-6.98,11.38-6.99,18.18-.06,24.18,24.64,49.97,47.41,78.35,67.31,34.67,24.31,72.81,39.36,114.51,45.94,8.93,1.41,17.75,3.48,26.67,4.93,7.45,1.21,10.05,4.16,6.34,11.67-20.49,41.45-48.2,76.2-90.04,98.03-2.86,1.49-5.98,2.47-8.57,3.52Z"/>
|
||||
<path class="cls-2" d="M874.18,155.7c17.01,14.01,30.76,29.06,43.52,44.96,31.34,39.05,54.92,81.89,61.08,132.44,5.37,44.12-2.85,86.74-30.05,121.33-25.28,32.16-62,47.85-104.39,45.61-4.25-.22-10.55,0-11.8-4.7-1.41-5.29,5.19-6.47,8.54-9.01,46.66-35.45,80.06-80.91,87.6-139.08,8.67-66.91-6.32-129.76-51.65-182.74-1.54-1.8-3.86-3.24-2.84-8.8Z"/>
|
||||
<path class="cls-2" d="M393.2,88.88c29.32-14.72,57.46-19.83,87.21-16.33,3.67.43,7.31,1.12,10.99,1.51,19.26,2.03,35.26,8.92,46,26.49,6.81,11.15,15.5,21.23,23.97,31.26,5.93,7.03,3.97,11.44-2.86,15.78-13.88,8.82-27.81,17.57-41.36,26.87-6.79,4.66-10.95,2.94-15.26-3.19-19.76-28.08-45.74-49.27-75.28-66.2-9.89-5.67-20.53-10.01-33.4-16.19Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-2" d="M642.58,733.79c.17,2.58.53,4.27.34,5.88-1.29,10.63-1.84,11.14-12.88,11.16-28.21.04-56.41,0-84.62.06-3.05,0-6.28.09-9.09,1.09-1.33.48-2.39,3.16-2.52,4.92-.07.87,2.12,2.52,3.49,2.77,2.67.5,5.48.32,8.22.32,28.89.02,57.79.01,86.68.02,2.41,0,4.82.11,7.22.04,5.04-.15,6.34,2.43,6.2,7.12-.43,15.28-2,16.99-17.13,16.99-88.4,0-176.81-.05-265.21.05-16.7.02-14.53-1.71-12.47-14.02,1.68-10.04,1.54-10.14,12.36-10.16,30.27-.04,60.54,0,90.81-.04,3.08,0,6.23.02,9.22-.61,1.25-.27,3.14-2.35,2.99-3.35-.24-1.64-1.63-4.01-3.02-4.41-2.89-.83-6.1-.73-9.18-.73-25.45-.04-50.91-.03-76.36-.03-2.41,0-4.82.05-7.22-.02-7.95-.25-8.85-.92-8.95-6.56-.15-8.44,1.77-10.89,9.63-10.93,28.21-.12,56.41-.05,84.62-.07,3.1,0,6.19.02,9.28-.13,2.92-.15,5.62-.87,5.47-4.61-.15-3.75-3.08-4.1-5.87-4.28-2.74-.18-5.5-.12-8.25-.13-23.05,0-46.09,0-69.14,0-2.41,0-4.82.07-7.22-.03-7.8-.33-8.69-1.35-7.79-9.4.46-4.08,1.25-8.12,1.82-12.19,1.85-13.22,3.54-26.47,5.56-39.67,1.48-9.68,1.67-9.77,11.82-9.8,24.76-.07,49.53-.02,74.29-.02,55.72,0,111.45,0,167.17,0,2.75,0,5.51.13,8.25.02,4.93-.19,6.92,2.06,6.23,6.91-2.74,19.32-5.51,38.64-8.1,57.98-.56,4.21-2.71,6.05-6.76,6.09-4.81.04-9.63.1-14.45.1-22.7.01-45.41,0-68.11.02-2.75,0-5.66-.38-8.19.4-1.9.58-3.3,2.75-4.93,4.2,1.56,1.45,2.89,3.61,4.72,4.16,2.54.76,5.45.37,8.19.37,27.17.02,54.35,0,81.52.03,3.68,0,7.35.31,11.35.5ZM455.08,670.86c-6.47,0-12.98-.37-19.4.21-2.05.19-5.2,2.68-5.5,4.49-.61,3.7,3.08,3.81,5.74,3.84,10.56.13,21.13.1,31.69.08,2.04,0,4.39.35,6.03-.52,1.78-.94,2.89-3.12,4.3-4.75-1.49-1.12-2.92-3.11-4.47-3.2-6.11-.37-12.25-.15-18.39-.16ZM568.87,679.4v.1c5.11,0,10.22.09,15.33-.04,2.01-.05,4.37-.05,5.89-1.08,1.37-.93,2.31-3.18,2.45-4.93.06-.77-2.3-2.49-3.58-2.51-12.94-.17-25.89-.23-38.83.12-1.75.05-4.55,2.23-4.91,3.86-.82,3.65,2.44,4.37,5.25,4.44,6.13.15,12.26.05,18.4.05ZM448.88,706.09s0,.06,0,.09c5.83,0,11.66.09,17.49-.04,3.45-.08,7.64-.22,7.54-4.87-.09-4.28-4.23-3.76-7.17-3.79-10.63-.12-21.26-.08-31.89-.03-1.7,0-3.72-.16-5.01.66-1.52.96-3.2,2.87-3.28,4.45-.06,1.11,2.39,3.27,3.82,3.36,6.15.38,12.33.16,18.5.16ZM564.82,706.13c0-.07,0-.13,0-.2,6.52,0,13.07.31,19.56-.21,1.66-.13,3.1-2.91,4.64-4.47-1.66-1.25-3.27-3.5-4.99-3.58-8.23-.4-16.49-.27-24.74-.23-4.46.02-8.99-.2-13.35.53-1.79.3-3.19,2.85-4.77,4.37,1.7,1.27,3.32,3.49,5.1,3.62,6.15.45,12.36.17,18.54.17Z"/>
|
||||
<path class="cls-2" d="M868.37,736.34c.93-2.22,1.01-3.06,1.46-3.4,12.08-9.08,14.69-22.06,16.41-36.11,3.71-30.24,8.49-60.36,12.83-90.52.2-1.36.44-2.7.64-4.06.49-3.35.06-6.38-3.88-7.18-3.4-.69-7.06-1.04-9.18,2.61-1.19,2.05-1.99,4.37-2.64,6.66-11.58,40.52-23.16,81.03-34.64,121.58-2.94,10.37-2.8,10.46-14.05,10.52-10.91.06-21.82.01-34.19.01,3.56-12.77,6.6-23.89,9.76-34.99,9.17-32.29,18.43-64.56,27.56-96.87,2.22-7.86.78-9.72-7.81-9.94-9.28-.24-18.57-.03-27.86-.1-3.38-.02-6.75-.28-10.77-.47-1.09-9.14.84-17.37,2.71-25.55,1.05-4.59,5.14-3.82,8.47-3.83,16.51-.07,33.02-.04,49.54-.04,2.41,0,4.82.03,7.22-.01,10.21-.18,14.44-7.01,9.93-16.18-1.15-2.34-2.73-4.48-4.59-7.48,2.77-.7,4.63-1.57,6.5-1.58,16.17-.12,32.34-.22,48.5-.02,7.51.09,8.2,1.23,7.24,8.67q-2.15,16.59,14.3,16.61c12.04,0,24.08-.03,36.12.03,3.36.02,6.73.31,11.61.56-1.25,8.79-2.38,16.77-3.51,24.75-.58,4.08-3.6,4.52-6.87,4.53-7.57.03-15.14-.09-22.7.1-7.82.19-8.56.8-9.73,8.79-4.84,33.21-9.54,66.43-14.35,99.65-1.83,12.66-6.05,24.01-18.32,30.38-2.67,1.39-5.76,2.69-8.69,2.77-11.99.31-23.98.13-37.02.13Z"/>
|
||||
<path class="cls-2" d="M971.24,753.75c-1.38,9.62-2.64,17.36-3.55,25.14-.54,4.61-2.77,6.73-7.38,6.6-2.75-.08-5.5.03-8.25.03-48.49,0-96.98-.46-145.45.24-17.85.26-34.82-2.54-51.64-7.68-1.97-.6-3.94-1.22-5.92-1.79-5.09-1.46-9.24-.84-12.55,4.08-1.51,2.24-4.61,4.76-7.05,4.83-15.41.44-30.83.22-46.48.22-1.46-5.71,1.81-9.4,4.11-12.69,8.56-12.25,11.46-26.01,13.27-40.48,3.4-27.17,7.57-54.24,11.39-81.36.33-2.37.54-4.76.72-7.15.35-4.67-.75-8.27-6.45-8.21-5.25.06-6.35-3.05-5.79-7.44.31-2.37.68-4.74,1.06-7.11q2.55-15.9,19.17-15.91c13.76,0,27.51-.1,41.26.05,9.64.1,10.77,1.29,9.45,11-3.59,26.45-7.42,52.88-11.17,79.31-1.54,10.85-3.22,21.67-4.63,32.54-1.32,10.15-.37,11.46,9.82,14.39,10.24,2.95,20.42,6.14,30.79,8.52,6.96,1.59,14.2,2.7,21.32,2.74,46.77.24,93.53.12,140.3.12,4.06,0,8.13,0,13.66,0Z"/>
|
||||
<path class="cls-2" d="M386.62,616.93c1.7-14.64,3.11-27.81,4.81-40.94,1.05-8.13,2.62-16.19,3.84-24.3.76-5.11,3.03-8.23,8.76-7.58,1.36.15,2.75,0,4.12,0,81.07,0,162.13,0,243.2.02,3.67,0,7.33.35,12.14.6-1.25,9.12-2.35,17.17-3.45,25.23-1.8,13.21-3.71,26.41-5.33,39.64-.67,5.47-3.29,7.89-8.82,7.35-2.04-.2-4.12-.02-6.18-.02-80.04,0-160.07,0-240.11,0-4.01,0-8.02,0-12.97,0ZM523.06,590.31c-22.98,0-45.96,0-68.94.01-2.74,0-5.59-.25-8.18.44-1.6.42-3.75,2.3-3.88,3.69-.11,1.29,1.88,3.34,3.41,4.03,1.76.79,4.03.56,6.08.56,47.68.02,95.36.02,143.03,0,2.05,0,4.33.26,6.08-.53,1.52-.69,3.45-2.76,3.36-4.09-.1-1.36-2.26-3.25-3.84-3.67-2.59-.68-5.44-.42-8.18-.42-22.98-.02-45.96-.01-68.94-.01ZM526.45,570.84c24.39,0,48.78.04,73.17-.05,3.23-.01,8.18.98,8.19-3.73,0-4.9-5.06-3.51-8.17-3.54-16.13-.14-32.27-.03-48.4-.03-31.26,0-62.52-.04-93.78-.04-2.74,0-5.56-.1-8.19.51-1.31.3-3.05,2.05-3.13,3.25-.07,1.02,1.79,2.87,3.07,3.15,2.64.58,5.45.46,8.19.46,23.02.03,46.03.01,69.05,0Z"/>
|
||||
<path class="cls-2" d="M664.1,626.08c.35,2.15.7,3.13.65,4.09-.72,13.47-.79,13.54-14.36,13.56-68.72.09-137.44.18-206.16.22-21.6.01-43.19-.1-64.79-.24-9.57-.07-12.19-3.9-8.35-12.73.89-2.03,3.57-3.94,5.81-4.58,2.87-.81,6.13-.31,9.22-.32,59.78,0,119.56,0,179.34,0,29.21,0,58.41,0,87.62,0,3.68,0,7.37,0,11.02,0Z"/>
|
||||
<path class="cls-2" d="M951.96,661.67c0-10.27-.11-20.54.03-30.8.12-8.74.54-9.1,9.52-9.28,5.49-.11,10.99.02,16.49.09,3.73.05,5.71,1.93,5.76,5.7.03,2.74.15,5.48.06,8.21-.56,18.79-1.12,37.58-1.77,56.37-.32,9.24-.43,9.31-9.23,9.51-4.81.11-9.62-.12-14.43,0-4.9.12-6.67-2.33-6.63-6.94.1-10.95.03-21.9.03-32.86.05,0,.11,0,.16,0Z"/>
|
||||
<path class="cls-2" d="M769.69,700.98c2.74-10.45,5-19.3,7.4-28.12,4.14-15.17,8.28-30.34,12.59-45.46,2.46-8.64,3.22-9.12,12.08-9.24,6.07-.09,12.13-.02,19.5-.02-1.06,4.9-1.61,8.18-2.48,11.38-5.76,21.1-11.57,42.2-17.42,63.28-2.35,8.46-2.41,8.57-11.24,8.65-6.35.06-12.7-.28-20.42-.47Z"/>
|
||||
<path class="cls-2" d="M778.14,586.16c-8.58,0-15.33,0-22.09,0-7.56,0-15.12-.07-22.68-.02-3.38.03-6.1-.8-7.29-4.34-3.77-11.29-7.54-22.59-11.52-34.5,2.84-.76,4.7-1.68,6.58-1.7,12.03-.14,24.06-.1,36.08-.07,3.48,0,7.16,0,8.57,4.09,3.98,11.56,7.84,23.16,12.35,36.53Z"/>
|
||||
</g>
|
||||
<text class="cls-1" transform="translate(360.91 887.84)"><tspan x="0" y="0">QUANT SPEED</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.1 KiB |
558
src/App.css
558
src/App.css
@@ -104,10 +104,54 @@ body, html {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
padding-top: 6rem;
|
||||
transform-style: preserve-3d;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scroll-behavior: smooth;
|
||||
will-change: transform, opacity;
|
||||
backface-visibility: hidden;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
|
||||
.section::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
.section::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
.section::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(180deg, rgba(0, 245, 212, 0.8), rgba(0, 212, 170, 0.8));
|
||||
border-radius: 999px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
.section {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(0, 245, 212, 0.7) transparent;
|
||||
}
|
||||
|
||||
/* 顶/底部渐隐发光,提高滚动品质感 */
|
||||
.section::before,
|
||||
.section::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 40px;
|
||||
pointer-events: none;
|
||||
z-index: 5;
|
||||
}
|
||||
.section::before {
|
||||
top: 0;
|
||||
background: linear-gradient(to bottom, rgba(0, 245, 212, 0.08), transparent);
|
||||
}
|
||||
.section::after {
|
||||
bottom: 0;
|
||||
background: linear-gradient(to top, rgba(0, 245, 212, 0.08), transparent);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@@ -958,7 +1002,7 @@ body, html {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: center;
|
||||
padding: 0 5rem;
|
||||
gap: 4rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.team-content {
|
||||
@@ -1038,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 {
|
||||
@@ -1052,6 +1098,7 @@ body, html {
|
||||
|
||||
.team-slider-track {
|
||||
display: flex;
|
||||
width: max-content;
|
||||
gap: 24px;
|
||||
will-change: transform;
|
||||
}
|
||||
@@ -1218,27 +1265,27 @@ body, html {
|
||||
.team-detail-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: #000;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(4px);
|
||||
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);
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
transform: none;
|
||||
width: 600px;
|
||||
max-width: 90vw;
|
||||
background: rgba(10, 15, 28, 0.95);
|
||||
border-left: 1px solid rgba(255,255,255,0.1);
|
||||
box-shadow: -10px 0 40px rgba(0,0,0,0.5);
|
||||
z-index: 990;
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
padding: 1.2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
padding: 2.5rem;
|
||||
color: var(--text-primary);
|
||||
max-height: calc(100vh - 96px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@@ -1246,56 +1293,101 @@ body, html {
|
||||
|
||||
.detail-close {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 8px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
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;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.detail-close:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 0.8rem;
|
||||
gap: 16px;
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.detail-brand {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
object-fit: contain;
|
||||
opacity: 0.9;
|
||||
opacity: 1;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
padding: 8px;
|
||||
border-radius: 12px;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
.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-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.detail-name {
|
||||
font-size: 1.2rem;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.detail-role {
|
||||
color: var(--primary-color);
|
||||
font-weight: 600;
|
||||
margin-top: 2px;
|
||||
font-size: 1rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* 限制详情头像高度,避免占满面板导致无可滚动空间 */
|
||||
.detail-portrait {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
max-height: 280px;
|
||||
object-fit: contain;
|
||||
background: transparent;
|
||||
/* 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 {
|
||||
@@ -1310,24 +1402,78 @@ body, html {
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
/* 自定义右侧详情面板滚动条样式(更精致) */
|
||||
.detail-scroller::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
.detail-scroller::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
.detail-scroller::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(180deg, rgba(0, 245, 212, 0.8), rgba(0, 212, 170, 0.8));
|
||||
border-radius: 999px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.detail-scroller {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(0, 245, 212, 0.7) transparent;
|
||||
}
|
||||
|
||||
.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;
|
||||
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;
|
||||
@@ -1335,12 +1481,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 {
|
||||
@@ -1650,36 +1808,37 @@ body, html {
|
||||
.contact-section {
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
margin-top: 8rem;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.contact-header {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.contact-header h2 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.contact-header p {
|
||||
font-size: 1.2rem;
|
||||
font-size: 1rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.contact-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 3rem;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.contact-methods {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
gap: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.contact-method {
|
||||
@@ -1687,11 +1846,11 @@ body, html {
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 2rem;
|
||||
padding: 1.5rem;
|
||||
transition: var(--transition-smooth);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
gap: 1.2rem;
|
||||
}
|
||||
|
||||
.contact-method:hover {
|
||||
@@ -1726,30 +1885,31 @@ body, html {
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 2rem;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.contact-social h4 {
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 1rem;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.social-link {
|
||||
background: var(--gradient-primary);
|
||||
color: white;
|
||||
padding: 0.8rem 1.2rem;
|
||||
border-radius: 15px;
|
||||
padding: 0.6rem 1rem;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: var(--transition-smooth);
|
||||
text-align: center;
|
||||
min-width: 80px;
|
||||
min-width: 70px;
|
||||
box-shadow: var(--shadow-soft);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.social-link:hover {
|
||||
@@ -1762,12 +1922,12 @@ body, html {
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 3rem;
|
||||
padding: 2rem;
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
@@ -1840,32 +2000,89 @@ body, html {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
z-index: 50;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 20px;
|
||||
padding: 1rem 0.5rem;
|
||||
background: rgba(10, 15, 28, 0.65);
|
||||
backdrop-filter: blur(12px) saturate(160%);
|
||||
-webkit-backdrop-filter: blur(12px) saturate(160%);
|
||||
border: 1px solid rgba(0, 245, 212, 0.18);
|
||||
border-radius: 16px;
|
||||
padding: 1rem 0.6rem;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
|
||||
overflow: hidden;
|
||||
}
|
||||
.section-indicators::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: 12px;
|
||||
bottom: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: linear-gradient(180deg, rgba(0, 245, 212, 0.25), rgba(0, 212, 170, 0.15));
|
||||
}
|
||||
|
||||
/* 移动端页面指示器优化 */
|
||||
@media (max-width: 768px) {
|
||||
.section-indicators {
|
||||
right: 1rem;
|
||||
padding: 0.8rem 0.4rem;
|
||||
gap: 0.8rem;
|
||||
border-radius: 15px;
|
||||
right: 1.5rem;
|
||||
padding: 1.2rem 0.8rem; /* 放大容器 */
|
||||
gap: 1.5rem; /* 增加间距 */
|
||||
border-radius: 20px;
|
||||
background: rgba(10, 15, 28, 0.8);
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.indicator {
|
||||
width: 16px; /* 放大圆点 */
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* 移动端显示标签 */
|
||||
.indicator::after {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
right: 35px; /* 文字在圆点左侧 */
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: rgba(10, 15, 28, 0.9);
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
padding: 4px 10px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
opacity: 0; /* 默认隐藏,保持界面清爽 */
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 激活项始终显示标签 */
|
||||
.indicator.active::after {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
color: var(--primary-color);
|
||||
border-color: rgba(0, 245, 212, 0.3);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 触摸/点击指示器区域时显示所有标签,方便用户预览跳转 */
|
||||
.section-indicators:active .indicator::after,
|
||||
.section-indicators:hover .indicator::after {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-smooth);
|
||||
position: relative;
|
||||
border: 2px solid transparent;
|
||||
border: 2px solid rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.indicator::before {
|
||||
@@ -1883,9 +2100,9 @@ body, html {
|
||||
|
||||
.indicator.active {
|
||||
background: var(--primary-color);
|
||||
transform: scale(1.3);
|
||||
box-shadow: 0 0 20px rgba(0, 245, 212, 0.6);
|
||||
border-color: rgba(0, 245, 212, 0.4);
|
||||
transform: scale(1.28);
|
||||
box-shadow: 0 0 18px rgba(0, 245, 212, 0.55);
|
||||
border-color: rgba(0, 245, 212, 0.5);
|
||||
}
|
||||
|
||||
.indicator.active::before {
|
||||
@@ -1895,8 +2112,8 @@ body, html {
|
||||
|
||||
.indicator:hover {
|
||||
background: var(--primary-color);
|
||||
transform: scale(1.2);
|
||||
box-shadow: 0 0 15px rgba(0, 245, 212, 0.4);
|
||||
transform: scale(1.18);
|
||||
box-shadow: 0 0 14px rgba(0, 245, 212, 0.45);
|
||||
}
|
||||
|
||||
.indicator:hover::before {
|
||||
@@ -2107,9 +2324,18 @@ body, html {
|
||||
}
|
||||
|
||||
.contact-section {
|
||||
margin-top: 5rem;
|
||||
padding: 0 1.5rem;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0;
|
||||
padding: 0 1rem;
|
||||
padding-bottom: 4rem; /* Ensure footer has space */
|
||||
}
|
||||
|
||||
.contact-footer {
|
||||
margin-top: 2rem;
|
||||
padding-top: 1.5rem;
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
|
||||
.contact-header h2 {
|
||||
font-size: 2rem;
|
||||
@@ -2399,12 +2625,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;
|
||||
@@ -2424,14 +2651,19 @@ body, html {
|
||||
transform: translateY(0);
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
height: 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;
|
||||
max-height: 95vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
.team-detail-mask { opacity: 0.7; }
|
||||
|
||||
.detail-portrait {
|
||||
margin: 0 auto 1rem auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* 小屏幕设备额外优化 */
|
||||
@@ -2489,9 +2721,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 {
|
||||
@@ -2567,3 +2805,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; }
|
||||
}
|
||||
173
src/App.js
173
src/App.js
@@ -15,6 +15,20 @@ const App = () => {
|
||||
const isScrollingRef = useRef(false);
|
||||
const currentSectionRef = useRef(0);
|
||||
const isTouchInDetailPanelRef = useRef(false);
|
||||
const sectionScrollRef = useRef(null);
|
||||
const lastFlipAtRef = useRef(0);
|
||||
|
||||
/**
|
||||
* 获取当前激活的滚动容器
|
||||
*/
|
||||
const getActiveScroller = (evtTarget) => {
|
||||
if (sectionScrollRef.current) return sectionScrollRef.current;
|
||||
if (evtTarget && typeof evtTarget.closest === 'function') {
|
||||
const el = evtTarget.closest('.section');
|
||||
if (el) return el;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const isEventFromDetailPanel = (target) => {
|
||||
if (!target) return false;
|
||||
@@ -39,6 +53,7 @@ const App = () => {
|
||||
|
||||
// 同步 ref 值
|
||||
useEffect(() => {
|
||||
document.title = "量迹AI科技";
|
||||
isScrollingRef.current = isScrolling;
|
||||
currentSectionRef.current = currentSection;
|
||||
}, [isScrolling, currentSection]);
|
||||
@@ -48,59 +63,93 @@ const App = () => {
|
||||
let touchStartY = 0;
|
||||
let touchEndY = 0;
|
||||
|
||||
/**
|
||||
* 桌面端滚轮:允许各页自然滚动;
|
||||
* 当滚动到顶部/底部继续滚动时,触发上一页/下一页翻页
|
||||
*/
|
||||
const handleWheel = (e) => {
|
||||
// 允许右侧详情面板自身滚动
|
||||
if (isEventFromDetailPanel(e.target)) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
// 获取当前激活的 section 容器
|
||||
const scroller = containerRef.current?.querySelector(`.section[data-index="${currentSectionRef.current}"]`);
|
||||
if (!scroller) return;
|
||||
|
||||
const tolerance = 5; // 增加容差
|
||||
const isScrollable = scroller.scrollHeight > scroller.clientHeight + 1;
|
||||
const atTop = scroller.scrollTop <= tolerance;
|
||||
const atBottom = Math.abs(scroller.scrollHeight - scroller.clientHeight - scroller.scrollTop) <= tolerance;
|
||||
|
||||
// 如果正在滚动中,忽略新的滚动事件
|
||||
if (isScrollingRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置滚动状态
|
||||
isScrollingRef.current = true;
|
||||
setIsScrolling(true);
|
||||
|
||||
// 计算新的section索引
|
||||
// 计算新的section索引(仅在边界继续滚动时触发)
|
||||
let newSection = currentSectionRef.current;
|
||||
if (e.deltaY > 0 && currentSectionRef.current < sections.length - 1) {
|
||||
newSection = currentSectionRef.current + 1;
|
||||
} else if (e.deltaY < 0 && currentSectionRef.current > 0) {
|
||||
newSection = currentSectionRef.current - 1;
|
||||
let shouldFlip = false;
|
||||
|
||||
if (e.deltaY > 0) {
|
||||
// 向下滚动
|
||||
if (currentSectionRef.current < sections.length - 1) {
|
||||
// 如果不可滚动,或者已经到底部,则翻页
|
||||
if (!isScrollable || atBottom) {
|
||||
shouldFlip = true;
|
||||
newSection = currentSectionRef.current + 1;
|
||||
}
|
||||
}
|
||||
} else if (e.deltaY < 0) {
|
||||
// 向上滚动
|
||||
if (currentSectionRef.current > 0) {
|
||||
// 如果不可滚动,或者已经到顶部,则翻页
|
||||
if (!isScrollable || atTop) {
|
||||
shouldFlip = true;
|
||||
newSection = currentSectionRef.current - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果section有变化,更新状态
|
||||
if (newSection !== currentSectionRef.current) {
|
||||
|
||||
if (shouldFlip) {
|
||||
e.preventDefault();
|
||||
|
||||
// 设置滚动状态
|
||||
isScrollingRef.current = true;
|
||||
setIsScrolling(true);
|
||||
setCurrentSection(newSection);
|
||||
lastFlipAtRef.current = Date.now();
|
||||
|
||||
// 清除之前的超时
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
// 设置超时来重置滚动状态(匹配翻页动画)
|
||||
timeout = setTimeout(() => {
|
||||
isScrollingRef.current = false;
|
||||
setIsScrolling(false);
|
||||
}, 900);
|
||||
}
|
||||
|
||||
// 清除之前的超时
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
// 设置超时来重置滚动状态
|
||||
timeout = setTimeout(() => {
|
||||
isScrollingRef.current = false;
|
||||
setIsScrolling(false);
|
||||
}, 1200); // 增加到1.2秒,与动画时间匹配
|
||||
};
|
||||
|
||||
// 触摸事件处理
|
||||
/**
|
||||
* 移动端触摸开始:记录起点并标记是否在详情面板内
|
||||
*/
|
||||
const handleTouchStart = (e) => {
|
||||
isTouchInDetailPanelRef.current = isEventFromDetailPanel(e.target);
|
||||
touchStartY = e.touches[0].clientY;
|
||||
};
|
||||
|
||||
const handleTouchMove = (e) => {
|
||||
if (isTouchInDetailPanelRef.current) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
};
|
||||
/**
|
||||
* 移动端触摸移动:允许各页自然滚动,不拦截
|
||||
*/
|
||||
const handleTouchMove = () => {};
|
||||
|
||||
/**
|
||||
* 移动端触摸结束:在滚动到顶部/底部时,依据滑动方向触发翻页
|
||||
*/
|
||||
const handleTouchEnd = (e) => {
|
||||
if (isTouchInDetailPanelRef.current) {
|
||||
isTouchInDetailPanelRef.current = false;
|
||||
@@ -112,33 +161,53 @@ const App = () => {
|
||||
|
||||
touchEndY = e.changedTouches[0].clientY;
|
||||
const deltaY = touchStartY - touchEndY;
|
||||
const minSwipeDistance = 50; // 最小滑动距离
|
||||
const minSwipeDistance = 30; // 降低滑动阈值,提高灵敏度 (原 50)
|
||||
|
||||
// 获取当前激活的 section 容器
|
||||
const scroller = containerRef.current?.querySelector(`.section[data-index="${currentSectionRef.current}"]`);
|
||||
|
||||
const tolerance = 10; // 增加边界容差 (原 5)
|
||||
const isScrollable = scroller ? scroller.scrollHeight > scroller.clientHeight + 1 : false;
|
||||
const atTop = scroller ? scroller.scrollTop <= tolerance : true;
|
||||
const atBottom = scroller ? Math.abs(scroller.scrollHeight - scroller.clientHeight - scroller.scrollTop) <= tolerance : true;
|
||||
|
||||
if (Math.abs(deltaY) > minSwipeDistance) {
|
||||
isScrollingRef.current = true;
|
||||
setIsScrolling(true);
|
||||
|
||||
let newSection = currentSectionRef.current;
|
||||
if (deltaY > 0 && currentSectionRef.current < sections.length - 1) {
|
||||
// 向上滑动,下一页
|
||||
newSection = currentSectionRef.current + 1;
|
||||
} else if (deltaY < 0 && currentSectionRef.current > 0) {
|
||||
// 向下滑动,上一页
|
||||
newSection = currentSectionRef.current - 1;
|
||||
let shouldFlip = false;
|
||||
|
||||
if (deltaY > 0) {
|
||||
// 上滑(手指向上,内容向下),看下一页
|
||||
if (currentSectionRef.current < sections.length - 1) {
|
||||
if (!isScrollable || atBottom) {
|
||||
shouldFlip = true;
|
||||
newSection = currentSectionRef.current + 1;
|
||||
}
|
||||
}
|
||||
} else if (deltaY < 0) {
|
||||
// 下滑(手指向下,内容向上),看上一页
|
||||
if (currentSectionRef.current > 0) {
|
||||
if (!isScrollable || atTop) {
|
||||
shouldFlip = true;
|
||||
newSection = currentSectionRef.current - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newSection !== currentSectionRef.current) {
|
||||
if (shouldFlip) {
|
||||
isScrollingRef.current = true;
|
||||
setIsScrolling(true);
|
||||
setCurrentSection(newSection);
|
||||
}
|
||||
lastFlipAtRef.current = Date.now();
|
||||
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
isScrollingRef.current = false;
|
||||
setIsScrolling(false);
|
||||
}, 1200);
|
||||
timeout = setTimeout(() => {
|
||||
isScrollingRef.current = false;
|
||||
setIsScrolling(false);
|
||||
}, 900);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -189,13 +258,14 @@ const App = () => {
|
||||
<motion.div
|
||||
key={section.id}
|
||||
className="section"
|
||||
data-index={index}
|
||||
initial={{ opacity: 0, scale: 0.8, rotateX: 15 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
rotateX: 0,
|
||||
transition: {
|
||||
duration: 1.2,
|
||||
duration: 0.9,
|
||||
ease: [0.25, 0.1, 0.25, 1],
|
||||
staggerChildren: 0.1
|
||||
}
|
||||
@@ -204,7 +274,7 @@ const App = () => {
|
||||
opacity: 0,
|
||||
scale: 1.1,
|
||||
rotateX: -15,
|
||||
transition: { duration: 0.8 }
|
||||
transition: { duration: 0.6 }
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
@@ -233,6 +303,7 @@ const App = () => {
|
||||
key={index}
|
||||
className={`indicator ${index === currentSection ? 'active' : ''}`}
|
||||
onClick={() => setCurrentSection(index)}
|
||||
title={sections[index].title}
|
||||
whileHover={{ scale: 1.2 }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
/>
|
||||
|
||||
35
src/asset/logo.svg
Normal file
35
src/asset/logo.svg
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_2" data-name="图层_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 989.55 925.64">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
font-family: Krungthep, Krungthep;
|
||||
font-size: 92.87px;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #020202;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="_图层_1-2" data-name="图层_1">
|
||||
<g>
|
||||
<path class="cls-2" d="M412.28,0c21.28,5.72,40.43,15.59,58.14,28.66,7.12,5.25,12.47,11.82,17.59,18.76,1.92,2.6,4.75,5.22,3.21,8.74-1.62,3.73-5.57,2.84-8.73,2.95-16.39.58-32.74-.2-49.19,2.09-42.55,5.92-78.84,24.31-111.03,52.05-48.48,41.78-82.1,94.79-111.85,150.21-30.11,56.1-56.75,113.89-72.13,176.2-11.14,45.15-19.93,90.7-19.44,137.28.31,29.14,4.18,58.21,20.59,83.77,1.77,2.75,3.54,5.55,5.67,8.02,10.44,12.13,10.23,13.09-5.05,19.39-53.28,21.97-109.47-4.38-130.35-60.79-4.59-12.4-5.9-25.5-9.73-38.02v-27.12c2.91-18.86,3.06-37.98,4.31-56.94,2.44-36.98,12.09-72.25,22.29-107.44,19.91-68.68,49.59-132.98,88.75-192.85,18.68-28.57,39.12-55.93,62.76-80.53,35.21-36.64,68.51-75.39,113.61-101.27,23.59-13.53,48.25-21.17,75.24-21.91,2.01-.06,4.13.36,5.82-1.23h39.5Z"/>
|
||||
<path class="cls-2" d="M792.19,131.3c-16.86,4.02-33.77,6.89-49.92,12.11-60.19,19.46-111.99,51.88-154.93,98.96-55.08,60.4-107.14,123.35-158.47,186.84-48.14,59.56-99.58,115.86-154.96,168.6-22.57,21.49-45.48,42.8-71.8,59.89-22.13,14.36-41.19,9.39-52.67-14.17-11.63-23.86-13.51-49.64-13.52-75.67,0-4.89,2.35-8.34,6.05-11.5,47.42-40.54,94.77-81.15,142.07-121.83,43.56-37.47,87.81-74.19,130.38-112.76,75.92-68.77,157.11-129.65,250.52-172.89,36.83-17.05,76.31-22.18,116.48-22.94,3.81-.07,8.38-.48,10.77,5.37Z"/>
|
||||
<path class="cls-2" d="M795.46,490.45c-20.17-4.55-38.34-12.09-54.96-22.98-44.94-29.47-80.24-68.78-112.48-111.11-8.45-11.1-16-22.91-24.58-33.91-5.85-7.5-4.36-12.69,2.13-18.88,15.17-14.45,30.01-29.27,44.46-44.45,6.64-6.98,11.38-6.99,18.18-.06,24.18,24.64,49.97,47.41,78.35,67.31,34.67,24.31,72.81,39.36,114.51,45.94,8.93,1.41,17.75,3.48,26.67,4.93,7.45,1.21,10.05,4.16,6.34,11.67-20.49,41.45-48.2,76.2-90.04,98.03-2.86,1.49-5.98,2.47-8.57,3.52Z"/>
|
||||
<path class="cls-2" d="M874.18,155.7c17.01,14.01,30.76,29.06,43.52,44.96,31.34,39.05,54.92,81.89,61.08,132.44,5.37,44.12-2.85,86.74-30.05,121.33-25.28,32.16-62,47.85-104.39,45.61-4.25-.22-10.55,0-11.8-4.7-1.41-5.29,5.19-6.47,8.54-9.01,46.66-35.45,80.06-80.91,87.6-139.08,8.67-66.91-6.32-129.76-51.65-182.74-1.54-1.8-3.86-3.24-2.84-8.8Z"/>
|
||||
<path class="cls-2" d="M393.2,88.88c29.32-14.72,57.46-19.83,87.21-16.33,3.67.43,7.31,1.12,10.99,1.51,19.26,2.03,35.26,8.92,46,26.49,6.81,11.15,15.5,21.23,23.97,31.26,5.93,7.03,3.97,11.44-2.86,15.78-13.88,8.82-27.81,17.57-41.36,26.87-6.79,4.66-10.95,2.94-15.26-3.19-19.76-28.08-45.74-49.27-75.28-66.2-9.89-5.67-20.53-10.01-33.4-16.19Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-2" d="M642.58,733.79c.17,2.58.53,4.27.34,5.88-1.29,10.63-1.84,11.14-12.88,11.16-28.21.04-56.41,0-84.62.06-3.05,0-6.28.09-9.09,1.09-1.33.48-2.39,3.16-2.52,4.92-.07.87,2.12,2.52,3.49,2.77,2.67.5,5.48.32,8.22.32,28.89.02,57.79.01,86.68.02,2.41,0,4.82.11,7.22.04,5.04-.15,6.34,2.43,6.2,7.12-.43,15.28-2,16.99-17.13,16.99-88.4,0-176.81-.05-265.21.05-16.7.02-14.53-1.71-12.47-14.02,1.68-10.04,1.54-10.14,12.36-10.16,30.27-.04,60.54,0,90.81-.04,3.08,0,6.23.02,9.22-.61,1.25-.27,3.14-2.35,2.99-3.35-.24-1.64-1.63-4.01-3.02-4.41-2.89-.83-6.1-.73-9.18-.73-25.45-.04-50.91-.03-76.36-.03-2.41,0-4.82.05-7.22-.02-7.95-.25-8.85-.92-8.95-6.56-.15-8.44,1.77-10.89,9.63-10.93,28.21-.12,56.41-.05,84.62-.07,3.1,0,6.19.02,9.28-.13,2.92-.15,5.62-.87,5.47-4.61-.15-3.75-3.08-4.1-5.87-4.28-2.74-.18-5.5-.12-8.25-.13-23.05,0-46.09,0-69.14,0-2.41,0-4.82.07-7.22-.03-7.8-.33-8.69-1.35-7.79-9.4.46-4.08,1.25-8.12,1.82-12.19,1.85-13.22,3.54-26.47,5.56-39.67,1.48-9.68,1.67-9.77,11.82-9.8,24.76-.07,49.53-.02,74.29-.02,55.72,0,111.45,0,167.17,0,2.75,0,5.51.13,8.25.02,4.93-.19,6.92,2.06,6.23,6.91-2.74,19.32-5.51,38.64-8.1,57.98-.56,4.21-2.71,6.05-6.76,6.09-4.81.04-9.63.1-14.45.1-22.7.01-45.41,0-68.11.02-2.75,0-5.66-.38-8.19.4-1.9.58-3.3,2.75-4.93,4.2,1.56,1.45,2.89,3.61,4.72,4.16,2.54.76,5.45.37,8.19.37,27.17.02,54.35,0,81.52.03,3.68,0,7.35.31,11.35.5ZM455.08,670.86c-6.47,0-12.98-.37-19.4.21-2.05.19-5.2,2.68-5.5,4.49-.61,3.7,3.08,3.81,5.74,3.84,10.56.13,21.13.1,31.69.08,2.04,0,4.39.35,6.03-.52,1.78-.94,2.89-3.12,4.3-4.75-1.49-1.12-2.92-3.11-4.47-3.2-6.11-.37-12.25-.15-18.39-.16ZM568.87,679.4v.1c5.11,0,10.22.09,15.33-.04,2.01-.05,4.37-.05,5.89-1.08,1.37-.93,2.31-3.18,2.45-4.93.06-.77-2.3-2.49-3.58-2.51-12.94-.17-25.89-.23-38.83.12-1.75.05-4.55,2.23-4.91,3.86-.82,3.65,2.44,4.37,5.25,4.44,6.13.15,12.26.05,18.4.05ZM448.88,706.09s0,.06,0,.09c5.83,0,11.66.09,17.49-.04,3.45-.08,7.64-.22,7.54-4.87-.09-4.28-4.23-3.76-7.17-3.79-10.63-.12-21.26-.08-31.89-.03-1.7,0-3.72-.16-5.01.66-1.52.96-3.2,2.87-3.28,4.45-.06,1.11,2.39,3.27,3.82,3.36,6.15.38,12.33.16,18.5.16ZM564.82,706.13c0-.07,0-.13,0-.2,6.52,0,13.07.31,19.56-.21,1.66-.13,3.1-2.91,4.64-4.47-1.66-1.25-3.27-3.5-4.99-3.58-8.23-.4-16.49-.27-24.74-.23-4.46.02-8.99-.2-13.35.53-1.79.3-3.19,2.85-4.77,4.37,1.7,1.27,3.32,3.49,5.1,3.62,6.15.45,12.36.17,18.54.17Z"/>
|
||||
<path class="cls-2" d="M868.37,736.34c.93-2.22,1.01-3.06,1.46-3.4,12.08-9.08,14.69-22.06,16.41-36.11,3.71-30.24,8.49-60.36,12.83-90.52.2-1.36.44-2.7.64-4.06.49-3.35.06-6.38-3.88-7.18-3.4-.69-7.06-1.04-9.18,2.61-1.19,2.05-1.99,4.37-2.64,6.66-11.58,40.52-23.16,81.03-34.64,121.58-2.94,10.37-2.8,10.46-14.05,10.52-10.91.06-21.82.01-34.19.01,3.56-12.77,6.6-23.89,9.76-34.99,9.17-32.29,18.43-64.56,27.56-96.87,2.22-7.86.78-9.72-7.81-9.94-9.28-.24-18.57-.03-27.86-.1-3.38-.02-6.75-.28-10.77-.47-1.09-9.14.84-17.37,2.71-25.55,1.05-4.59,5.14-3.82,8.47-3.83,16.51-.07,33.02-.04,49.54-.04,2.41,0,4.82.03,7.22-.01,10.21-.18,14.44-7.01,9.93-16.18-1.15-2.34-2.73-4.48-4.59-7.48,2.77-.7,4.63-1.57,6.5-1.58,16.17-.12,32.34-.22,48.5-.02,7.51.09,8.2,1.23,7.24,8.67q-2.15,16.59,14.3,16.61c12.04,0,24.08-.03,36.12.03,3.36.02,6.73.31,11.61.56-1.25,8.79-2.38,16.77-3.51,24.75-.58,4.08-3.6,4.52-6.87,4.53-7.57.03-15.14-.09-22.7.1-7.82.19-8.56.8-9.73,8.79-4.84,33.21-9.54,66.43-14.35,99.65-1.83,12.66-6.05,24.01-18.32,30.38-2.67,1.39-5.76,2.69-8.69,2.77-11.99.31-23.98.13-37.02.13Z"/>
|
||||
<path class="cls-2" d="M971.24,753.75c-1.38,9.62-2.64,17.36-3.55,25.14-.54,4.61-2.77,6.73-7.38,6.6-2.75-.08-5.5.03-8.25.03-48.49,0-96.98-.46-145.45.24-17.85.26-34.82-2.54-51.64-7.68-1.97-.6-3.94-1.22-5.92-1.79-5.09-1.46-9.24-.84-12.55,4.08-1.51,2.24-4.61,4.76-7.05,4.83-15.41.44-30.83.22-46.48.22-1.46-5.71,1.81-9.4,4.11-12.69,8.56-12.25,11.46-26.01,13.27-40.48,3.4-27.17,7.57-54.24,11.39-81.36.33-2.37.54-4.76.72-7.15.35-4.67-.75-8.27-6.45-8.21-5.25.06-6.35-3.05-5.79-7.44.31-2.37.68-4.74,1.06-7.11q2.55-15.9,19.17-15.91c13.76,0,27.51-.1,41.26.05,9.64.1,10.77,1.29,9.45,11-3.59,26.45-7.42,52.88-11.17,79.31-1.54,10.85-3.22,21.67-4.63,32.54-1.32,10.15-.37,11.46,9.82,14.39,10.24,2.95,20.42,6.14,30.79,8.52,6.96,1.59,14.2,2.7,21.32,2.74,46.77.24,93.53.12,140.3.12,4.06,0,8.13,0,13.66,0Z"/>
|
||||
<path class="cls-2" d="M386.62,616.93c1.7-14.64,3.11-27.81,4.81-40.94,1.05-8.13,2.62-16.19,3.84-24.3.76-5.11,3.03-8.23,8.76-7.58,1.36.15,2.75,0,4.12,0,81.07,0,162.13,0,243.2.02,3.67,0,7.33.35,12.14.6-1.25,9.12-2.35,17.17-3.45,25.23-1.8,13.21-3.71,26.41-5.33,39.64-.67,5.47-3.29,7.89-8.82,7.35-2.04-.2-4.12-.02-6.18-.02-80.04,0-160.07,0-240.11,0-4.01,0-8.02,0-12.97,0ZM523.06,590.31c-22.98,0-45.96,0-68.94.01-2.74,0-5.59-.25-8.18.44-1.6.42-3.75,2.3-3.88,3.69-.11,1.29,1.88,3.34,3.41,4.03,1.76.79,4.03.56,6.08.56,47.68.02,95.36.02,143.03,0,2.05,0,4.33.26,6.08-.53,1.52-.69,3.45-2.76,3.36-4.09-.1-1.36-2.26-3.25-3.84-3.67-2.59-.68-5.44-.42-8.18-.42-22.98-.02-45.96-.01-68.94-.01ZM526.45,570.84c24.39,0,48.78.04,73.17-.05,3.23-.01,8.18.98,8.19-3.73,0-4.9-5.06-3.51-8.17-3.54-16.13-.14-32.27-.03-48.4-.03-31.26,0-62.52-.04-93.78-.04-2.74,0-5.56-.1-8.19.51-1.31.3-3.05,2.05-3.13,3.25-.07,1.02,1.79,2.87,3.07,3.15,2.64.58,5.45.46,8.19.46,23.02.03,46.03.01,69.05,0Z"/>
|
||||
<path class="cls-2" d="M664.1,626.08c.35,2.15.7,3.13.65,4.09-.72,13.47-.79,13.54-14.36,13.56-68.72.09-137.44.18-206.16.22-21.6.01-43.19-.1-64.79-.24-9.57-.07-12.19-3.9-8.35-12.73.89-2.03,3.57-3.94,5.81-4.58,2.87-.81,6.13-.31,9.22-.32,59.78,0,119.56,0,179.34,0,29.21,0,58.41,0,87.62,0,3.68,0,7.37,0,11.02,0Z"/>
|
||||
<path class="cls-2" d="M951.96,661.67c0-10.27-.11-20.54.03-30.8.12-8.74.54-9.1,9.52-9.28,5.49-.11,10.99.02,16.49.09,3.73.05,5.71,1.93,5.76,5.7.03,2.74.15,5.48.06,8.21-.56,18.79-1.12,37.58-1.77,56.37-.32,9.24-.43,9.31-9.23,9.51-4.81.11-9.62-.12-14.43,0-4.9.12-6.67-2.33-6.63-6.94.1-10.95.03-21.9.03-32.86.05,0,.11,0,.16,0Z"/>
|
||||
<path class="cls-2" d="M769.69,700.98c2.74-10.45,5-19.3,7.4-28.12,4.14-15.17,8.28-30.34,12.59-45.46,2.46-8.64,3.22-9.12,12.08-9.24,6.07-.09,12.13-.02,19.5-.02-1.06,4.9-1.61,8.18-2.48,11.38-5.76,21.1-11.57,42.2-17.42,63.28-2.35,8.46-2.41,8.57-11.24,8.65-6.35.06-12.7-.28-20.42-.47Z"/>
|
||||
<path class="cls-2" d="M778.14,586.16c-8.58,0-15.33,0-22.09,0-7.56,0-15.12-.07-22.68-.02-3.38.03-6.1-.8-7.29-4.34-3.77-11.29-7.54-22.59-11.52-34.5,2.84-.76,4.7-1.68,6.58-1.7,12.03-.14,24.06-.1,36.08-.07,3.48,0,7.16,0,8.57,4.09,3.98,11.56,7.84,23.16,12.35,36.53Z"/>
|
||||
</g>
|
||||
<text class="cls-1" transform="translate(360.91 887.84)"><tspan x="0" y="0">QUANT SPEED</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.1 KiB |
@@ -7,33 +7,43 @@ const CaseSection = ({ isActive }) => {
|
||||
const cases = [
|
||||
{
|
||||
id: 1,
|
||||
title: '智能金融风控系统',
|
||||
client: '某大型银行',
|
||||
category: '金融科技',
|
||||
description: '基于机器学习的实时风险评估系统,将欺诈检测准确率提升至99.8%',
|
||||
results: ['风险识别提升85%', '处理速度提高300%', '年节省成本2000万'],
|
||||
image: '🏦',
|
||||
technologies: ['深度学习', '实时计算', '大数据分析']
|
||||
title: '智慧茶桌·小盏',
|
||||
client: '餐饮商户',
|
||||
category: '餐饮场景',
|
||||
description: '定制小盖3D立体IP茶宠硬件,搭载声识WiFi语音交互与2寸显示屏,实现语音问答点餐、多语言支持与菜品推荐。',
|
||||
results: ['兼顾情绪价值与实用价值', '硬件成本低至200元/个', '实现“交互-解决-沉淀”闭环'],
|
||||
image: '☕',
|
||||
technologies: ['声识WiFi语音交互', '3D打印IP', '硬件电量管理']
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '智能医疗诊断助手',
|
||||
client: '顶级三甲医院',
|
||||
category: '医疗健康',
|
||||
description: 'AI辅助医生进行疾病诊断,显著提高诊断效率和准确性',
|
||||
results: ['诊断准确率提升20%', '诊疗时间缩短40%', '患者满意度95%'],
|
||||
image: '🏥',
|
||||
technologies: ['计算机视觉', '自然语言处理', '知识图谱']
|
||||
title: '幂次科技小秘书',
|
||||
client: '办公企业',
|
||||
category: '办公场景',
|
||||
description: '将智能体技术与办公OA平台深度结合,通过语音控制办公系统,实现智慧周报总结与任务自动跟进。',
|
||||
results: ['显著提升办公效率', '语音对话发布任务', '下发任务自动跟进'],
|
||||
image: '💼',
|
||||
technologies: ['智能体OA结合', '语音控制', '智慧周报']
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '智能制造优化平台',
|
||||
client: '制造业龙头企业',
|
||||
category: '工业4.0',
|
||||
description: '通过AI优化生产流程,实现智能化生产管理和质量控制',
|
||||
results: ['生产效率提升45%', '次品率降低90%', 'ROI达到280%'],
|
||||
image: '🏭',
|
||||
technologies: ['预测性维护', 'IoT集成', '优化算法']
|
||||
title: '万达双塔智慧引导',
|
||||
client: '万达双塔',
|
||||
category: '商业楼宇',
|
||||
description: '打造AI小程序+智慧前台硬件组合方案,满足楼内商户信息检索、对话式模糊推荐与智慧楼层引导需求。',
|
||||
results: ['适配客流引导需求', '对话式模糊推荐', '提升商户检索效率'],
|
||||
image: '🏢',
|
||||
technologies: ['AI小程序', '智慧前台硬件', '模糊推荐算法']
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '红河州工商联“小红”',
|
||||
client: '红河州工商联',
|
||||
category: '政务场景',
|
||||
description: '定制政务人偶硬件,搭载麦克风与显示屏,实现直接语音唤醒与服务器直连,简化政务查询操作。',
|
||||
results: ['对老年人友好', '短询问链路响应快', '支持扫码通话/软件访问'],
|
||||
image: '🏛',
|
||||
technologies: ['语音唤醒', '服务器直连', 'AI大模型']
|
||||
}
|
||||
];
|
||||
|
||||
@@ -126,8 +136,9 @@ const CaseSection = ({ isActive }) => {
|
||||
className="case-cta"
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={() => window.location.href = 'https://market.quant-speed.com'}
|
||||
>
|
||||
查看详细案例
|
||||
加入量迹商城
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
|
||||
@@ -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: '欢迎莅临参观交流'
|
||||
}
|
||||
];
|
||||
@@ -159,7 +159,7 @@ const ContactSection = ({ isActive }) => {
|
||||
animate={isActive ? { opacity: 1 } : {}}
|
||||
transition={{ duration: 1, delay: 1.2 }}
|
||||
>
|
||||
<p>© 2024 Radiant AI. 创新科技,引领未来。</p>
|
||||
<p>© 2024 量迹AI. 创新科技,引领未来。</p>
|
||||
<p>
|
||||
<a href="https://beian.miit.gov.cn" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--text-secondary)', textDecoration: 'none', fontSize: '0.9rem' }}>
|
||||
滇ICP备2025071546号-1
|
||||
|
||||
@@ -58,10 +58,25 @@ const HeroSection = ({ isActive }) => {
|
||||
boxShadow: "0 10px 30px rgba(0, 245, 212, 0.3)"
|
||||
}}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
window.open('https://market.quant-speed.com', '_blank');
|
||||
}}
|
||||
>
|
||||
<span className="btn-text">了解更多</span>
|
||||
<div className="btn-glow"></div>
|
||||
<div className="btn-arrow">→</div>
|
||||
<img
|
||||
src="/logo.svg"
|
||||
alt="logo"
|
||||
style={{
|
||||
height: '20px',
|
||||
marginRight: '8px',
|
||||
filter: 'brightness(0) invert(1)',
|
||||
position: 'relative',
|
||||
zIndex: 2
|
||||
}}
|
||||
/>
|
||||
<span className="btn-text" style={{ position: 'relative', zIndex: 2 }}>量迹商城</span>
|
||||
<div className="btn-glow" style={{ pointerEvents: 'none' }}></div>
|
||||
<div className="btn-arrow" style={{ position: 'relative', zIndex: 2 }}>→</div>
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
|
||||
|
||||
@@ -245,10 +245,31 @@ const ProductSection = ({ isActive }) => {
|
||||
boxShadow: "0 10px 30px rgba(0, 245, 212, 0.3)"
|
||||
}}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
const urls = {
|
||||
v3: 'https://market.quant-speed.com/product/2',
|
||||
mini: 'https://market.quant-speed.com/product/1',
|
||||
v2: 'https://market.quant-speed.com/product/3'
|
||||
};
|
||||
const targetUrl = urls[modelKey] || 'https://market.quant-speed.com';
|
||||
window.open(targetUrl, '_blank');
|
||||
}}
|
||||
>
|
||||
<span className="btn-text">了解更多</span>
|
||||
<div className="btn-glow"></div>
|
||||
<div className="btn-arrow">→</div>
|
||||
<img
|
||||
src="/logo.svg"
|
||||
alt="logo"
|
||||
style={{
|
||||
height: '20px',
|
||||
marginRight: '8px',
|
||||
filter: 'brightness(0) invert(1)',
|
||||
position: 'relative',
|
||||
zIndex: 2
|
||||
}}
|
||||
/>
|
||||
<span className="btn-text" style={{ position: 'relative', zIndex: 2 }}>量迹商城</span>
|
||||
<div className="btn-glow" style={{ pointerEvents: 'none' }}></div>
|
||||
<div className="btn-arrow" style={{ position: 'relative', zIndex: 2 }}>→</div>
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
|
||||
|
||||
@@ -1,53 +1,181 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import logoBai from '../asset/logo-bai.png';
|
||||
|
||||
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 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: ['本科(待补充)', '硕士(待补充)'],
|
||||
brandLogo: logoBai,
|
||||
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: logoBai,
|
||||
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: ['本科(待补充)'],
|
||||
brandLogo: logoBai,
|
||||
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: '老许',
|
||||
@@ -55,13 +183,54 @@ const TeamSection = ({ isActive }) => {
|
||||
bio: '负责高可靠硬件架构设计与产线可制造性优化。',
|
||||
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: ['本科(待补充)'],
|
||||
brandLogo: logoBai,
|
||||
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: logoBai,
|
||||
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: logoBai,
|
||||
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: logoBai,
|
||||
experience: [
|
||||
'负责前端页面设计,打造AI小程序、硬件配套的交互界面',
|
||||
'主导后端API服务开发,保障软件与硬件的无缝对接'
|
||||
],
|
||||
skills: ['React', 'Photoshop', 'JavaScript', '全栈开发']
|
||||
}
|
||||
|
||||
]), []);
|
||||
@@ -70,29 +239,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 +376,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) => (
|
||||
<div
|
||||
@@ -254,7 +446,13 @@ const TeamSection = ({ isActive }) => {
|
||||
<div className="detail-role">{selected.role}</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">
|
||||
{selected.bio && (
|
||||
<div className="detail-card">
|
||||
@@ -274,7 +472,7 @@ const TeamSection = ({ isActive }) => {
|
||||
)}
|
||||
{selected.experience && selected.experience.length > 0 && (
|
||||
<div className="detail-card">
|
||||
<h5>过往经历</h5>
|
||||
<h5>职业经历</h5>
|
||||
<ul className="detail-list">
|
||||
{selected.experience.map((e, i) => (
|
||||
<li key={i}>{e}</li>
|
||||
@@ -287,7 +485,10 @@ const TeamSection = ({ isActive }) => {
|
||||
<h5>擅长技能</h5>
|
||||
<div className="chip-grid">
|
||||
{selected.skills.map((s, i) => (
|
||||
<span className="chip" key={i}>{s}</span>
|
||||
<span className="chip" key={i}>
|
||||
<SkillIcon skill={s} />
|
||||
{s}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -318,6 +519,38 @@ const TeamSection = ({ isActive }) => {
|
||||
<span className="progress-total">00:18</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* 右下角控制区域 */}
|
||||
<motion.div
|
||||
className="team-controls-bottom"
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
animate={isActive ? { opacity: 1, x: 0 } : {}}
|
||||
transition={{ duration: 0.8, delay: 1.5 }}
|
||||
>
|
||||
<div className="control-status">
|
||||
<span className="status-dot"></span>
|
||||
<span className="status-text">SYSTEM ONLINE</span>
|
||||
</div>
|
||||
<div className="control-group">
|
||||
<div className="control-numbers">
|
||||
<span className="current-idx">{String(index + 1).padStart(2, '0')}</span>
|
||||
<span className="divider">/</span>
|
||||
<span className="total-idx">{String(members.length).padStart(2, '0')}</span>
|
||||
</div>
|
||||
<div className="control-buttons">
|
||||
<button className="bottom-btn" onClick={goPrev}>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path d="M19 12H5M12 19l-7-7 7-7"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button className="bottom-btn" onClick={goNext}>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user