From 40384ec024e7e426a25e0860f9bde424d54db65d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?=
Date: Sat, 25 Apr 2026 08:44:23 +0800
Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E7=BD=91?=
=?UTF-8?q?=E7=AB=99=E9=A1=B5=E9=9D=A2=E7=BB=93=E6=9E=84=E5=92=8C=E6=95=B0?=
=?UTF-8?q?=E6=8D=AE=E5=B1=95=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 增强服务数据模型,添加 challenges 和 outcomes 字段
- 简化统计数据配置,改为静态定义
- 重构多个页面组件,优化代码结构
- 新增产品、服务、解决方案相关的布局和组件
- 更新样式和动画配置
- 优化测试用例和类型定义
- 修复 ESLint 错误:移除不必要的 useEffect 和未使用的导入
---
.gitignore | 5 +-
package-lock.json | 662 ++++++++++++++----
package.json | 1 +
src/app/(marketing)/about/client.tsx | 55 +-
src/app/(marketing)/about/page.test.tsx | 2 +-
src/app/(marketing)/about/page.tsx | 2 +-
src/app/(marketing)/cases/layout.tsx | 4 +-
src/app/(marketing)/cases/page.tsx | 30 +-
src/app/(marketing)/contact/layout.tsx | 4 +-
src/app/(marketing)/home-content.tsx | 17 +-
src/app/(marketing)/layout.tsx | 66 +-
.../news/[slug]/NewsDetailClient.tsx | 16 +-
src/app/(marketing)/news/layout.tsx | 14 +
src/app/(marketing)/news/page.tsx | 4 +-
src/app/(marketing)/products/[id]/page.tsx | 199 +-----
.../products/[id]/product-detail-client.tsx | 69 ++
src/app/(marketing)/products/layout.tsx | 14 +
src/app/(marketing)/products/page.tsx | 34 +-
src/app/(marketing)/services/[id]/client.tsx | 344 +++------
src/app/(marketing)/services/[id]/page.tsx | 2 +-
src/app/(marketing)/services/layout.tsx | 14 +
src/app/(marketing)/solutions/[id]/page.tsx | 31 +
.../solutions/[id]/solution-detail-client.tsx | 218 ++++++
src/app/(marketing)/solutions/layout.tsx | 4 +-
src/app/(marketing)/solutions/page.tsx | 280 ++------
src/app/(marketing)/team/client.tsx | 4 +-
src/app/(marketing)/team/page.tsx | 2 +-
src/app/globals.css | 2 +-
src/app/layout.tsx | 8 +-
src/app/not-found.tsx | 12 +-
src/app/privacy/page.tsx | 5 +-
src/app/terms/page.tsx | 6 +-
src/components/layout/footer.tsx | 6 +-
src/components/layout/header.test.tsx | 12 +-
src/components/layout/header.tsx | 51 +-
src/components/layout/product-footer.tsx | 104 +++
src/components/layout/product-header.tsx | 96 +++
src/components/layout/service-footer.tsx | 98 +++
src/components/layout/service-header.tsx | 90 +++
src/components/products/index.ts | 8 +
.../products/product-benefits-section.tsx | 68 ++
.../products/product-cta-section.tsx | 57 ++
.../products/product-features-section.tsx | 137 ++++
.../products/product-hero-section.tsx | 116 +++
.../products/product-overview-section.tsx | 38 +
.../products/product-pricing-section.tsx | 140 ++++
.../products/product-process-section.tsx | 75 ++
.../products/product-specs-section.tsx | 41 ++
src/components/sections/about-section.tsx | 76 +-
src/components/sections/cases-section.tsx | 127 ++--
.../sections/hero-section-atoms.tsx | 46 +-
src/components/sections/hero-section.test.tsx | 6 +-
src/components/sections/hero-stats-ssr.tsx | 2 +-
.../sections/home-solutions-section.tsx | 1 -
src/components/sections/products-section.tsx | 37 +-
src/components/sections/services-section.tsx | 31 +-
src/components/sections/team-section.tsx | 132 +++-
src/components/seo/structured-data.tsx | 13 +-
.../services/service-cases-section.tsx | 70 ++
.../services/service-challenges-section.tsx | 64 ++
.../services/service-cta-section.tsx | 75 ++
.../services/service-features-section.tsx | 55 ++
.../services/service-hero-section.tsx | 143 ++++
.../services/service-outcomes-section.tsx | 93 +++
.../services/service-process-section.tsx | 89 +++
.../solutions/accompany-section.tsx | 109 +++
.../solutions/consulting-section.tsx | 108 +++
.../solutions/tech-solution-section.tsx | 110 +++
src/components/ui/floating-cta.tsx | 69 ++
src/components/ui/ripple-button.tsx | 23 +-
src/lib/animations.tsx | 13 +-
src/lib/constants.test.ts | 2 +-
src/lib/constants/index.ts | 2 +-
src/lib/constants/navigation.ts | 5 +-
src/lib/constants/products.ts | 130 ++--
src/lib/constants/services.ts | 46 ++
src/lib/constants/stats.ts | 33 +-
77 files changed, 3751 insertions(+), 1226 deletions(-)
create mode 100644 src/app/(marketing)/news/layout.tsx
create mode 100644 src/app/(marketing)/products/[id]/product-detail-client.tsx
create mode 100644 src/app/(marketing)/products/layout.tsx
create mode 100644 src/app/(marketing)/services/layout.tsx
create mode 100644 src/app/(marketing)/solutions/[id]/page.tsx
create mode 100644 src/app/(marketing)/solutions/[id]/solution-detail-client.tsx
create mode 100644 src/components/layout/product-footer.tsx
create mode 100644 src/components/layout/product-header.tsx
create mode 100644 src/components/layout/service-footer.tsx
create mode 100644 src/components/layout/service-header.tsx
create mode 100644 src/components/products/index.ts
create mode 100644 src/components/products/product-benefits-section.tsx
create mode 100644 src/components/products/product-cta-section.tsx
create mode 100644 src/components/products/product-features-section.tsx
create mode 100644 src/components/products/product-hero-section.tsx
create mode 100644 src/components/products/product-overview-section.tsx
create mode 100644 src/components/products/product-pricing-section.tsx
create mode 100644 src/components/products/product-process-section.tsx
create mode 100644 src/components/products/product-specs-section.tsx
create mode 100644 src/components/services/service-cases-section.tsx
create mode 100644 src/components/services/service-challenges-section.tsx
create mode 100644 src/components/services/service-cta-section.tsx
create mode 100644 src/components/services/service-features-section.tsx
create mode 100644 src/components/services/service-hero-section.tsx
create mode 100644 src/components/services/service-outcomes-section.tsx
create mode 100644 src/components/services/service-process-section.tsx
create mode 100644 src/components/solutions/accompany-section.tsx
create mode 100644 src/components/solutions/consulting-section.tsx
create mode 100644 src/components/solutions/tech-solution-section.tsx
create mode 100644 src/components/ui/floating-cta.tsx
diff --git a/.gitignore b/.gitignore
index 0e75c60..f73c3e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -294,4 +294,7 @@ findings.md
AGENTS.md
# dogfood
-dogfood-output/
\ No newline at end of file
+dogfood-output/
+
+# docs
+docs/
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index d283ffe..85836e4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"critters": "^0.0.23",
"date-fns": "^4.1.0",
"framer-motion": "^12.34.3",
+ "jsdom": "^29.0.2",
"lucide-react": "^0.563.0",
"next": "16.1.6",
"react": "19.2.3",
@@ -320,25 +321,51 @@
}
},
"node_modules/@asamuzakjp/css-color": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
- "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
- "dev": true,
+ "version": "5.1.11",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz",
+ "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==",
"license": "MIT",
"dependencies": {
- "@csstools/css-calc": "^2.1.3",
- "@csstools/css-color-parser": "^3.0.9",
- "@csstools/css-parser-algorithms": "^3.0.4",
- "@csstools/css-tokenizer": "^3.0.3",
- "lru-cache": "^10.4.3"
+ "@asamuzakjp/generational-cache": "^1.0.1",
+ "@csstools/css-calc": "^3.2.0",
+ "@csstools/css-color-parser": "^4.1.0",
+ "@csstools/css-parser-algorithms": "^4.0.0",
+ "@csstools/css-tokenizer": "^4.0.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
- "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true,
- "license": "ISC"
+ "node_modules/@asamuzakjp/dom-selector": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz",
+ "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@asamuzakjp/generational-cache": "^1.0.1",
+ "@asamuzakjp/nwsapi": "^2.3.9",
+ "bidi-js": "^1.0.3",
+ "css-tree": "^3.2.1",
+ "is-potential-custom-element-name": "^1.0.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@asamuzakjp/generational-cache": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz",
+ "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@asamuzakjp/nwsapi": {
+ "version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
+ "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
+ "license": "MIT"
},
"node_modules/@axe-core/playwright": {
"version": "4.11.2",
@@ -2271,6 +2298,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@bramus/specificity": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz",
+ "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "^3.0.0"
+ },
+ "bin": {
+ "specificity": "bin/cli.js"
+ }
+ },
"node_modules/@commitlint/cli": {
"version": "20.5.0",
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.0.tgz",
@@ -2581,10 +2620,9 @@
}
},
"node_modules/@csstools/color-helpers": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
- "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
- "dev": true,
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz",
+ "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==",
"funding": [
{
"type": "github",
@@ -2597,14 +2635,13 @@
],
"license": "MIT-0",
"engines": {
- "node": ">=18"
+ "node": ">=20.19.0"
}
},
"node_modules/@csstools/css-calc": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz",
- "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==",
- "dev": true,
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.0.tgz",
+ "integrity": "sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==",
"funding": [
{
"type": "github",
@@ -2617,18 +2654,17 @@
],
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=20.19.0"
},
"peerDependencies": {
- "@csstools/css-parser-algorithms": "^3.0.5",
- "@csstools/css-tokenizer": "^3.0.4"
+ "@csstools/css-parser-algorithms": "^4.0.0",
+ "@csstools/css-tokenizer": "^4.0.0"
}
},
"node_modules/@csstools/css-color-parser": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
- "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
- "dev": true,
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.0.tgz",
+ "integrity": "sha512-U0KhLYmy2GVj6q4T3WaAe6NPuFYCPQoE3b0dRGxejWDgcPp8TP7S5rVdM5ZrFaqu4N67X8YaPBw14dQSYx3IyQ==",
"funding": [
{
"type": "github",
@@ -2641,22 +2677,21 @@
],
"license": "MIT",
"dependencies": {
- "@csstools/color-helpers": "^5.1.0",
- "@csstools/css-calc": "^2.1.4"
+ "@csstools/color-helpers": "^6.0.2",
+ "@csstools/css-calc": "^3.2.0"
},
"engines": {
- "node": ">=18"
+ "node": ">=20.19.0"
},
"peerDependencies": {
- "@csstools/css-parser-algorithms": "^3.0.5",
- "@csstools/css-tokenizer": "^3.0.4"
+ "@csstools/css-parser-algorithms": "^4.0.0",
+ "@csstools/css-tokenizer": "^4.0.0"
}
},
"node_modules/@csstools/css-parser-algorithms": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
- "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
- "dev": true,
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz",
+ "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==",
"funding": [
{
"type": "github",
@@ -2669,17 +2704,40 @@
],
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=20.19.0"
},
"peerDependencies": {
- "@csstools/css-tokenizer": "^3.0.4"
+ "@csstools/css-tokenizer": "^4.0.0"
+ }
+ },
+ "node_modules/@csstools/css-syntax-patches-for-csstree": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.3.tgz",
+ "integrity": "sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "peerDependencies": {
+ "css-tree": "^3.2.1"
+ },
+ "peerDependenciesMeta": {
+ "css-tree": {
+ "optional": true
+ }
}
},
"node_modules/@csstools/css-tokenizer": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
- "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
- "dev": true,
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz",
+ "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==",
"funding": [
{
"type": "github",
@@ -2692,7 +2750,7 @@
],
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=20.19.0"
}
},
"node_modules/@dimforge/rapier3d-compat": {
@@ -3263,6 +3321,23 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@exodus/bytes": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz",
+ "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "@noble/hashes": "^1.8.0 || ^2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@noble/hashes": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@floating-ui/core": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
@@ -9051,6 +9126,15 @@
"node": ">=10.0.0"
}
},
+ "node_modules/bidi-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
+ "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
+ "license": "MIT",
+ "dependencies": {
+ "require-from-string": "^2.0.2"
+ }
+ },
"node_modules/body-parser": {
"version": "1.20.4",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
@@ -9960,6 +10044,19 @@
"url": "https://github.com/sponsors/fb55"
}
},
+ "node_modules/css-tree": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
+ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.27.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
"node_modules/css-what": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
@@ -9993,6 +10090,142 @@
"node": ">=18"
}
},
+ "node_modules/cssstyle/node_modules/@asamuzakjp/css-color": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
+ "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@csstools/css-calc": "^2.1.3",
+ "@csstools/css-color-parser": "^3.0.9",
+ "@csstools/css-parser-algorithms": "^3.0.4",
+ "@csstools/css-tokenizer": "^3.0.3",
+ "lru-cache": "^10.4.3"
+ }
+ },
+ "node_modules/cssstyle/node_modules/@csstools/color-helpers": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
+ "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cssstyle/node_modules/@csstools/css-calc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz",
+ "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/cssstyle/node_modules/@csstools/css-color-parser": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
+ "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@csstools/color-helpers": "^5.1.0",
+ "@csstools/css-calc": "^2.1.4"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/cssstyle/node_modules/@csstools/css-parser-algorithms": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
+ "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/cssstyle/node_modules/@csstools/css-tokenizer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
+ "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cssstyle/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -10298,17 +10531,16 @@
}
},
"node_modules/data-urls": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
- "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
- "dev": true,
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz",
+ "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==",
"license": "MIT",
"dependencies": {
- "whatwg-mimetype": "^4.0.0",
- "whatwg-url": "^14.0.0"
+ "whatwg-mimetype": "^5.0.0",
+ "whatwg-url": "^16.0.0"
},
"engines": {
- "node": ">=18"
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/data-view-buffer": {
@@ -10407,7 +10639,6 @@
"version": "10.6.0",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
- "dev": true,
"license": "MIT"
},
"node_modules/dedent": {
@@ -12497,16 +12728,15 @@
}
},
"node_modules/html-encoding-sniffer": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
- "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
- "dev": true,
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
+ "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==",
"license": "MIT",
"dependencies": {
- "whatwg-encoding": "^3.1.1"
+ "@exodus/bytes": "^1.6.0"
},
"engines": {
- "node": ">=18"
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/html-escaper": {
@@ -13302,7 +13532,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/is-regex": {
@@ -13993,6 +14222,153 @@
}
}
},
+ "node_modules/jest-environment-jsdom/node_modules/data-urls": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
+ "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/html-encoding-sniffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
+ "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-encoding": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/jsdom": {
+ "version": "26.1.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
+ "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssstyle": "^4.2.1",
+ "data-urls": "^5.0.0",
+ "decimal.js": "^10.5.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.6",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.16",
+ "parse5": "^7.2.1",
+ "rrweb-cssom": "^0.8.0",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^5.1.1",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.1.1",
+ "ws": "^8.18.0",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "canvas": "^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/tldts": {
+ "version": "6.1.86",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
+ "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tldts-core": "^6.1.86"
+ },
+ "bin": {
+ "tldts": "bin/cli.js"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/tldts-core": {
+ "version": "6.1.86",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
+ "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-environment-jsdom/node_modules/tough-cookie": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
+ "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tldts": "^6.1.32"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/tr46": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
+ "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/jest-environment-jsdom/node_modules/whatwg-url": {
+ "version": "14.2.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
+ "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^5.1.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/jest-environment-node": {
"version": "30.3.0",
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.3.0.tgz",
@@ -14633,35 +15009,35 @@
}
},
"node_modules/jsdom": {
- "version": "26.1.0",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
- "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
- "dev": true,
+ "version": "29.0.2",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.0.2.tgz",
+ "integrity": "sha512-9VnGEBosc/ZpwyOsJBCQ/3I5p7Q5ngOY14a9bf5btenAORmZfDse1ZEheMiWcJ3h81+Fv7HmJFdS0szo/waF2w==",
"license": "MIT",
"dependencies": {
- "cssstyle": "^4.2.1",
- "data-urls": "^5.0.0",
- "decimal.js": "^10.5.0",
- "html-encoding-sniffer": "^4.0.0",
- "http-proxy-agent": "^7.0.2",
- "https-proxy-agent": "^7.0.6",
+ "@asamuzakjp/css-color": "^5.1.5",
+ "@asamuzakjp/dom-selector": "^7.0.6",
+ "@bramus/specificity": "^2.4.2",
+ "@csstools/css-syntax-patches-for-csstree": "^1.1.1",
+ "@exodus/bytes": "^1.15.0",
+ "css-tree": "^3.2.1",
+ "data-urls": "^7.0.0",
+ "decimal.js": "^10.6.0",
+ "html-encoding-sniffer": "^6.0.0",
"is-potential-custom-element-name": "^1.0.1",
- "nwsapi": "^2.2.16",
- "parse5": "^7.2.1",
- "rrweb-cssom": "^0.8.0",
+ "lru-cache": "^11.2.7",
+ "parse5": "^8.0.0",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
- "tough-cookie": "^5.1.1",
+ "tough-cookie": "^6.0.1",
+ "undici": "^7.24.5",
"w3c-xmlserializer": "^5.0.0",
- "webidl-conversions": "^7.0.0",
- "whatwg-encoding": "^3.1.1",
- "whatwg-mimetype": "^4.0.0",
- "whatwg-url": "^14.1.1",
- "ws": "^8.18.0",
+ "webidl-conversions": "^8.0.1",
+ "whatwg-mimetype": "^5.0.0",
+ "whatwg-url": "^16.0.1",
"xml-name-validator": "^5.0.0"
},
"engines": {
- "node": ">=18"
+ "node": "^20.19.0 || ^22.13.0 || >=24.0.0"
},
"peerDependencies": {
"canvas": "^3.0.0"
@@ -14672,6 +15048,39 @@
}
}
},
+ "node_modules/jsdom/node_modules/entities": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz",
+ "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=20.19.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/jsdom/node_modules/lru-cache": {
+ "version": "11.3.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
+ "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/jsdom/node_modules/parse5": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
+ "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^8.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -15757,6 +16166,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/mdn-data": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
+ "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
+ "license": "CC0-1.0"
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -17114,7 +17529,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -17467,7 +17881,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -17814,7 +18227,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"xmlchars": "^2.2.0"
@@ -18687,7 +19099,6 @@
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
- "dev": true,
"license": "MIT"
},
"node_modules/synckit": {
@@ -18886,13 +19297,12 @@
}
},
"node_modules/tldts": {
- "version": "6.1.86",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
- "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
- "dev": true,
+ "version": "7.0.28",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.28.tgz",
+ "integrity": "sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==",
"license": "MIT",
"dependencies": {
- "tldts-core": "^6.1.86"
+ "tldts-core": "^7.0.28"
},
"bin": {
"tldts": "bin/cli.js"
@@ -18902,7 +19312,6 @@
"version": "7.0.28",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.28.tgz",
"integrity": "sha512-7W5Efjhsc3chVdFhqtaU0KtK32J37Zcr9RKtID54nG+tIpcY79CQK/veYPODxtD/LJ4Lue66jvrQzIX2Z2/pUQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/tldts-icann": {
@@ -18915,13 +19324,6 @@
"tldts-core": "^7.0.28"
}
},
- "node_modules/tldts/node_modules/tldts-core": {
- "version": "6.1.86",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
- "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/tmp": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
@@ -18989,29 +19391,27 @@
}
},
"node_modules/tough-cookie": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
- "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
- "dev": true,
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz",
+ "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==",
"license": "BSD-3-Clause",
"dependencies": {
- "tldts": "^6.1.32"
+ "tldts": "^7.0.5"
},
"engines": {
"node": ">=16"
}
},
"node_modules/tr46": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
- "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
- "dev": true,
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz",
+ "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==",
"license": "MIT",
"dependencies": {
"punycode": "^2.3.1"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
},
"node_modules/tree-kill": {
@@ -19331,6 +19731,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/undici": {
+ "version": "7.25.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz",
+ "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
@@ -19582,7 +19991,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
"integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"xml-name-validator": "^5.0.0"
@@ -19616,13 +20024,12 @@
"license": "Apache-2.0"
},
"node_modules/webidl-conversions": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
- "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
- "dev": true,
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
+ "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
"license": "BSD-2-Clause",
"engines": {
- "node": ">=12"
+ "node": ">=20"
}
},
"node_modules/whatwg-encoding": {
@@ -19647,27 +20054,26 @@
"license": "MIT"
},
"node_modules/whatwg-mimetype": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
- "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
- "dev": true,
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
+ "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
},
"node_modules/whatwg-url": {
- "version": "14.2.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
- "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
- "dev": true,
+ "version": "16.0.1",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz",
+ "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==",
"license": "MIT",
"dependencies": {
- "tr46": "^5.1.0",
- "webidl-conversions": "^7.0.0"
+ "@exodus/bytes": "^1.11.0",
+ "tr46": "^6.0.0",
+ "webidl-conversions": "^8.0.1"
},
"engines": {
- "node": ">=18"
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/when-exit": {
@@ -19995,7 +20401,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
"integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
- "dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=18"
@@ -20005,7 +20410,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
- "dev": true,
"license": "MIT"
},
"node_modules/xtend": {
diff --git a/package.json b/package.json
index c955d58..2fdc12e 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"critters": "^0.0.23",
"date-fns": "^4.1.0",
"framer-motion": "^12.34.3",
+ "jsdom": "^29.0.2",
"lucide-react": "^0.563.0",
"next": "16.1.6",
"react": "19.2.3",
diff --git a/src/app/(marketing)/about/client.tsx b/src/app/(marketing)/about/client.tsx
index 4f65859..3de819a 100644
--- a/src/app/(marketing)/about/client.tsx
+++ b/src/app/(marketing)/about/client.tsx
@@ -2,58 +2,31 @@
import { motion } from 'framer-motion';
import { useInView } from 'framer-motion';
-import { useRef, useState, useEffect, useMemo } from 'react';
+import { useRef, useMemo } from 'react';
import { COMPANY_INFO, STATS } from '@/lib/constants';
import { Card, CardContent } from '@/components/ui/card';
import { PageHeader } from '@/components/ui/page-header';
-import { FlipClock } from '@/components/ui/flip-clock';
-import { Lightbulb, Users, Target, Award, MapPin, Mail } from 'lucide-react';
+import { Lightbulb, Users, Target, MapPin, Mail } from 'lucide-react';
export function AboutClient() {
const contentRef = useRef(null);
const isContentInView = useInView(contentRef, { once: true, margin: '-100px' });
- const [operationTime, setOperationTime] = useState({ days: 0, months: 0, years: 0 });
-
- useEffect(() => {
- const foundingDate = new Date('2026-01-15');
- const calculateTime = () => {
- const now = new Date();
- const diff = now.getTime() - foundingDate.getTime();
-
- const totalDays = Math.floor(diff / (1000 * 60 * 60 * 24));
- const years = Math.floor(totalDays / 365);
- const months = Math.floor((totalDays % 365) / 30);
- const days = totalDays % 30;
-
- setOperationTime({ days, months, years });
- };
-
- calculateTime();
- const timer = setInterval(calculateTime, 60000);
-
- return () => clearInterval(timer);
- }, []);
const values = useMemo(() => [
{
icon: Lightbulb,
- title: '创新驱动',
- description: '持续探索前沿技术,以创新思维解决业务挑战,为客户创造差异化价值',
+ title: '务实',
+ description: '不追逐风口,只做真正为客户创造价值的事。每一个方案都源于对业务场景的深入洞察。',
},
{
icon: Users,
- title: '客户至上',
- description: '深入理解客户需求,提供个性化解决方案,建立长期合作伙伴关系',
+ title: '陪伴',
+ description: '交付只是开始,长期陪跑才是我们的承诺。我们关注的不只是项目是否上线,更是您的业务是否真正改善。',
},
{
icon: Target,
- title: '追求卓越',
- description: '以最高标准要求自己,持续优化产品和服务质量,超越客户期望',
- },
- {
- icon: Award,
- title: '诚信为本',
- description: '坚持透明沟通,信守承诺,以诚信赢得客户信任和尊重',
+ title: '专业',
+ description: '用扎实的工程能力和行业经验赢得信任。既懂技术又懂业务,提供真正可落地的解决方案。',
},
], []);
@@ -75,8 +48,8 @@ export function AboutClient() {
},
{
date: '2026年2月',
- title: '产品发布',
- description: '自主研发的ERP、CRM等产品陆续上线,为客户提供一站式数字化服务',
+ title: '产品研发',
+ description: '启动ERP、CRM等自研产品的研发工作,致力于为企业提供一站式数字化服务',
},
], []);
@@ -154,12 +127,6 @@ export function AboutClient() {
-
-
核心价值观
-
+
{values.map((value, idx) => (
({
jest.mock('@/lib/constants', () => ({
COMPANY_INFO: {
name: '四川睿新致远科技有限公司',
- shortName: '睿新致遠',
+ shortName: '睿新致远',
description: '以智慧连接数字趋势,以伙伴身份陪您成长',
address: '四川省成都市龙泉驿区',
email: 'contact@ruixin.com',
diff --git a/src/app/(marketing)/about/page.tsx b/src/app/(marketing)/about/page.tsx
index 6d06ae2..a20f633 100644
--- a/src/app/(marketing)/about/page.tsx
+++ b/src/app/(marketing)/about/page.tsx
@@ -2,7 +2,7 @@ import { COMPANY_INFO } from '@/lib/constants';
import { AboutClient } from './client';
export const metadata = {
- title: `关于我们 - ${COMPANY_INFO.name}`,
+ title: '关于我们',
description: `了解${COMPANY_INFO.name}的品牌故事。我们不只是技术供应商,更是您数字化转型的成长伙伴。以智慧连接数字趋势,以伙伴身份陪您成长。`,
};
diff --git a/src/app/(marketing)/cases/layout.tsx b/src/app/(marketing)/cases/layout.tsx
index 16d6a3f..d9475c2 100644
--- a/src/app/(marketing)/cases/layout.tsx
+++ b/src/app/(marketing)/cases/layout.tsx
@@ -1,8 +1,8 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
- title: '客户案例 - 睿新致远',
- description: '与谁同行,决定能走多远',
+ title: '客户案例',
+ description: '了解诺瓦隆在各行业的成功案例,包括制造业、政务服务、酒店管理、智慧农业等领域的数字化转型实践。',
};
export default function CasesLayout({
diff --git a/src/app/(marketing)/cases/page.tsx b/src/app/(marketing)/cases/page.tsx
index f87c740..473bcb1 100644
--- a/src/app/(marketing)/cases/page.tsx
+++ b/src/app/(marketing)/cases/page.tsx
@@ -230,23 +230,25 @@ export default function CasesPage() {
让我们与您同行,共创美好未来
-
-
-
-
+
+
+
+
立即咨询
-
-
+
+
diff --git a/src/app/(marketing)/contact/layout.tsx b/src/app/(marketing)/contact/layout.tsx
index 3c16dfb..8f11303 100644
--- a/src/app/(marketing)/contact/layout.tsx
+++ b/src/app/(marketing)/contact/layout.tsx
@@ -1,6 +1,6 @@
export const metadata = {
- title: '联系我们 - 四川睿新致远科技有限公司',
- description: '无论您有任何问题或合作意向,我们都很乐意与您交流',
+ title: '联系我们',
+ description: '联系四川睿新致远科技有限公司(诺瓦隆)。无论您有任何关于企业数字化转型、软件开发、数据分析等方面的咨询需求,我们都期待与您交流。',
};
export default function ContactLayout({ children }: { children: React.ReactNode }) {
diff --git a/src/app/(marketing)/home-content.tsx b/src/app/(marketing)/home-content.tsx
index da64f7f..d7c1550 100644
--- a/src/app/(marketing)/home-content.tsx
+++ b/src/app/(marketing)/home-content.tsx
@@ -37,14 +37,6 @@ const ProductsSection = dynamic(
}
);
-const CasesSection = dynamic(
- () => import('@/components/sections/cases-section').then(mod => ({ default: mod.CasesSection })),
- {
- loading: () =>
,
- ssr: false
- }
-);
-
const AboutSection = dynamic(
() => import('@/components/sections/about-section').then(mod => ({ default: mod.AboutSection })),
{
@@ -69,6 +61,8 @@ const NewsSection = dynamic(
}
);
+
+
function HomeContent({ heroStats }: { heroStats: ReactNode }) {
const searchParams = useSearchParams();
@@ -108,10 +102,15 @@ function HomeContent({ heroStats }: { heroStats: ReactNode }) {
return (
+ {/* 墨韵分割线 */}
+
+ {/* 墨韵分割线 */}
+
-
+ {/* 墨韵分割线 */}
+
diff --git a/src/app/(marketing)/layout.tsx b/src/app/(marketing)/layout.tsx
index 19525e1..cf9553f 100644
--- a/src/app/(marketing)/layout.tsx
+++ b/src/app/(marketing)/layout.tsx
@@ -4,18 +4,46 @@ import { usePathname } from 'next/navigation';
import { ErrorBoundary } from '@/components/ui/error-boundary';
import { Header } from '@/components/layout/header';
import { Footer } from '@/components/layout/footer';
+import { ProductHeader } from '@/components/layout/product-header';
+import { ProductFooter } from '@/components/layout/product-footer';
+import { ServiceHeader } from '@/components/layout/service-header';
+import { ServiceFooter } from '@/components/layout/service-footer';
import { Breadcrumb } from '@/components/layout/breadcrumb';
const breadcrumbMap: Record = {
'/about': { label: '关于我们', href: '/about' },
- '/cases': { label: '成功案例', href: '/cases' },
'/services': { label: '核心业务', href: '/services' },
'/products': { label: '产品服务', href: '/products' },
- '/solutions': { label: '解决方案', href: '/solutions' },
+ '/solutions': { label: '行业方案', href: '/solutions' },
'/news': { label: '新闻动态', href: '/news' },
'/contact': { label: '联系我们', href: '/contact' },
+ '/team': { label: '核心团队', href: '/team' },
};
+/**
+ * 判断是否为产品详情页(如 /products/erp、/products/crm 等)
+ * 产品列表页 /products 本身仍使用主站布局
+ */
+function isProductDetailPage(pathname: string): boolean {
+ return /^\/products\/[^/]+$/.test(pathname);
+}
+
+/**
+ * 判断是否为服务详情页(如 /services/software、/services/data 等)
+ * 服务列表页 /services 本身仍使用主站布局
+ */
+function isServiceDetailPage(pathname: string): boolean {
+ return /^\/services\/[^/]+$/.test(pathname);
+}
+
+/**
+ * 判断是否为解决方案详情页(如 /solutions/manufacturing 等)
+ * 解决方案列表页 /solutions 本身仍使用主站布局
+ */
+function isSolutionDetailPage(pathname: string): boolean {
+ return /^\/solutions\/[^/]+$/.test(pathname);
+}
+
export default function MarketingLayout({
children,
}: {
@@ -23,7 +51,41 @@ export default function MarketingLayout({
}) {
const pathname = usePathname();
const breadcrumbItem = breadcrumbMap[pathname];
+ const isProductDetail = isProductDetailPage(pathname);
+ const isServiceDetail = isServiceDetailPage(pathname);
+ const isSolutionDetail = isSolutionDetailPage(pathname);
+ // 产品详情页使用独立布局(ProductHeader + ProductFooter)
+ if (isProductDetail || isSolutionDetail) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+ }
+
+ // 服务详情页使用独立布局(ServiceHeader + ServiceFooter)
+ if (isServiceDetail) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+ }
+
+ // 其他页面使用主站布局(Header + Footer)
return (
diff --git a/src/app/(marketing)/news/[slug]/NewsDetailClient.tsx b/src/app/(marketing)/news/[slug]/NewsDetailClient.tsx
index eb6a528..09053c8 100644
--- a/src/app/(marketing)/news/[slug]/NewsDetailClient.tsx
+++ b/src/app/(marketing)/news/[slug]/NewsDetailClient.tsx
@@ -114,17 +114,17 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
)}
-
-
+
+
返回新闻列表
-
-
-
-
+
+
+
+
联系我们
-
-
+
+
diff --git a/src/app/(marketing)/news/layout.tsx b/src/app/(marketing)/news/layout.tsx
new file mode 100644
index 0000000..5d90afc
--- /dev/null
+++ b/src/app/(marketing)/news/layout.tsx
@@ -0,0 +1,14 @@
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: '新闻动态',
+ description: '了解四川睿新致远科技有限公司(诺瓦隆)的最新动态、产品发布和行业资讯。',
+};
+
+export default function NewsLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/src/app/(marketing)/news/page.tsx b/src/app/(marketing)/news/page.tsx
index d431525..6ccb065 100644
--- a/src/app/(marketing)/news/page.tsx
+++ b/src/app/(marketing)/news/page.tsx
@@ -12,7 +12,7 @@ import { Search, Calendar, Filter, ChevronLeft, ChevronRight, ArrowRight } from
import { StaticLink } from '@/components/ui/static-link';
import { motion } from 'framer-motion';
-const categories = ['全部', '公司新闻', '产品发布'];
+const categories = ['全部', '公司新闻', '产品发布', '研发动态'];
const ITEMS_PER_PAGE = 9;
export default function NewsListPage() {
@@ -28,7 +28,7 @@ export default function NewsListPage() {
newsItem.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
newsItem.excerpt.toLowerCase().includes(searchQuery.toLowerCase());
return matchesCategory && matchesSearch;
- });
+ }).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
}, [selectedCategory, searchQuery]);
const totalPages = Math.ceil(filteredNews.length / ITEMS_PER_PAGE);
diff --git a/src/app/(marketing)/products/[id]/page.tsx b/src/app/(marketing)/products/[id]/page.tsx
index e5fb91b..08b15d9 100644
--- a/src/app/(marketing)/products/[id]/page.tsx
+++ b/src/app/(marketing)/products/[id]/page.tsx
@@ -1,9 +1,6 @@
import { notFound } from 'next/navigation';
-import { StaticLink } from '@/components/ui/static-link';
import { PRODUCTS } from '@/lib/constants';
-import { Button } from '@/components/ui/button';
-import { BackButton } from '@/components/ui/back-button';
-import { CheckCircle2, Zap, Target, Layers, CreditCard, ArrowRight } from 'lucide-react';
+import { ProductDetailClient } from './product-detail-client';
export async function generateStaticParams() {
return PRODUCTS.map((product) => ({
@@ -14,7 +11,7 @@ export async function generateStaticParams() {
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
const product = PRODUCTS.find((p) => p.id === id);
-
+
if (!product) {
return {
title: '产品未找到',
@@ -35,195 +32,5 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
notFound();
}
- return (
-
-
-
-
-
-
- {product.category}
-
-
- {product.title}
-
-
- {product.description}
-
-
-
-
-
-
-
-
- 产品概述
-
- {product.overview}
-
-
-
-
-
-
- 核心功能
-
-
- {product.features.map((feature, index) => (
-
- ))}
-
-
-
-
-
-
- 产品优势
-
-
- {product.benefits.map((benefit, index) => (
-
- ))}
-
-
-
-
-
-
- 实施流程
-
-
- {product.process.map((step, index) => (
-
-
- {index + 1}
-
-
-
{step}
- {index < product.process.length - 1 && (
-
- )}
-
-
- ))}
-
-
-
-
-
-
- 技术规格
-
-
- {product.specs.map((spec, index) => (
-
- ))}
-
-
-
-
-
-
- 价格方案
-
-
-
-
基础版
-
{product.pricing.base}
-
- -
-
- 基础功能模块
-
- -
-
- 邮件支持
-
- -
-
- 标准报表
-
-
-
-
-
- 推荐
-
-
标准版
-
{product.pricing.standard}
-
- -
-
- 全部功能模块
-
- -
-
- 电话支持
-
- -
-
- 自定义报表
-
-
-
-
-
企业版
-
{product.pricing.enterprise}
-
- -
-
- 全部功能模块
-
- -
-
- 专属客服
-
- -
-
- 定制开发
-
-
-
-
-
-
-
-
-
- 联系我们
-
-
-
-
- 立即咨询
-
-
-
-
-
-
-
- );
+ return ;
}
diff --git a/src/app/(marketing)/products/[id]/product-detail-client.tsx b/src/app/(marketing)/products/[id]/product-detail-client.tsx
new file mode 100644
index 0000000..792a8aa
--- /dev/null
+++ b/src/app/(marketing)/products/[id]/product-detail-client.tsx
@@ -0,0 +1,69 @@
+'use client';
+
+import dynamic from 'next/dynamic';
+import { PRODUCTS } from '@/lib/constants/products';
+
+const ProductHeroSection = dynamic(
+ () => import('@/components/products/product-hero-section').then(mod => ({ default: mod.ProductHeroSection })),
+ { ssr: false }
+);
+
+const ProductOverviewSection = dynamic(
+ () => import('@/components/products/product-overview-section').then(mod => ({ default: mod.ProductOverviewSection })),
+ { ssr: false }
+);
+
+const ProductFeaturesSection = dynamic(
+ () => import('@/components/products/product-features-section').then(mod => ({ default: mod.ProductFeaturesSection })),
+ { ssr: false }
+);
+
+const ProductBenefitsSection = dynamic(
+ () => import('@/components/products/product-benefits-section').then(mod => ({ default: mod.ProductBenefitsSection })),
+ { ssr: false }
+);
+
+const ProductProcessSection = dynamic(
+ () => import('@/components/products/product-process-section').then(mod => ({ default: mod.ProductProcessSection })),
+ { ssr: false }
+);
+
+const ProductSpecsSection = dynamic(
+ () => import('@/components/products/product-specs-section').then(mod => ({ default: mod.ProductSpecsSection })),
+ { ssr: false }
+);
+
+const ProductCTASection = dynamic(
+ () => import('@/components/products/product-cta-section').then(mod => ({ default: mod.ProductCTASection })),
+ { ssr: false }
+);
+
+interface ProductDetailClientProps {
+ productId: string;
+}
+
+export function ProductDetailClient({ productId }: ProductDetailClientProps) {
+ const product = PRODUCTS.find(p => p.id === productId) || null;
+
+ // 产品页已改为浅色主题,无需切换 Header 深色模式
+
+ if (!product) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/(marketing)/products/layout.tsx b/src/app/(marketing)/products/layout.tsx
new file mode 100644
index 0000000..e9edf68
--- /dev/null
+++ b/src/app/(marketing)/products/layout.tsx
@@ -0,0 +1,14 @@
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: '产品服务',
+ description: '诺瓦隆(四川睿新致远科技)自研产品矩阵,包括睿新ERP管理系统、睿新CRM客户关系管理系统、睿新内容管理系统、睿新商业智能平台等企业级数字化产品。',
+};
+
+export default function ProductsLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/src/app/(marketing)/products/page.tsx b/src/app/(marketing)/products/page.tsx
index 33a1459..51fb8e8 100644
--- a/src/app/(marketing)/products/page.tsx
+++ b/src/app/(marketing)/products/page.tsx
@@ -7,10 +7,12 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/com
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
+import { RippleButton } from '@/lib/animations';
import { PageHeader } from '@/components/ui/page-header';
import { Search, ArrowLeft, Check, TrendingUp, ChevronLeft, ChevronRight, Filter } from 'lucide-react';
import { StaticLink } from '@/components/ui/static-link';
import { motion } from 'framer-motion';
+import { InkCard } from '@/lib/animations';
const categories = ['全部', '企业软件', '数据产品'];
const ITEMS_PER_PAGE = 6;
@@ -111,15 +113,13 @@ export default function ProductsPage() {
) : (
<>
- {paginatedProducts.map((product, index) => (
- (
+
-
+
{product.category}
@@ -161,14 +161,14 @@ export default function ProductsPage() {
-
+
-
+
))}
@@ -231,16 +231,12 @@ export default function ProductsPage() {
我们的专业团队可以根据您的业务需求,提供量身定制的产品开发和系统集成服务
-
-
+
+
联系我们
-
-
-
+
+
+
diff --git a/src/app/(marketing)/services/[id]/client.tsx b/src/app/(marketing)/services/[id]/client.tsx
index 55266d5..346d873 100644
--- a/src/app/(marketing)/services/[id]/client.tsx
+++ b/src/app/(marketing)/services/[id]/client.tsx
@@ -1,277 +1,97 @@
'use client';
-import { useRef } from 'react';
-import { StaticLink } from '@/components/ui/static-link';
-import { Button } from '@/components/ui/button';
-import { Badge } from '@/components/ui/badge';
-import { BackButton } from '@/components/ui/back-button';
-import {
- CheckCircle2,
- TrendingUp,
- Users,
- Target,
- Clock,
- MessageCircle,
- ArrowRight
-} from 'lucide-react';
-import { SERVICES, CASES } from '@/lib/constants';
+import dynamic from 'next/dynamic';
+import { type Service } from '@/lib/constants/services';
+import { RippleButton, FadeUp } from '@/lib/animations';
+
+const ServiceHeroSection = dynamic(
+ () => import('@/components/services/service-hero-section').then(mod => ({ default: mod.ServiceHeroSection })),
+ { ssr: false }
+);
+
+const ServiceChallengesSection = dynamic(
+ () => import('@/components/services/service-challenges-section').then(mod => ({ default: mod.ServiceChallengesSection })),
+ { ssr: false }
+);
+
+const ServiceFeaturesSection = dynamic(
+ () => import('@/components/services/service-features-section').then(mod => ({ default: mod.ServiceFeaturesSection })),
+ { ssr: false }
+);
+
+const ServiceProcessSection = dynamic(
+ () => import('@/components/services/service-process-section').then(mod => ({ default: mod.ServiceProcessSection })),
+ { ssr: false }
+);
+
+const ServiceOutcomesSection = dynamic(
+ () => import('@/components/services/service-outcomes-section').then(mod => ({ default: mod.ServiceOutcomesSection })),
+ { ssr: false }
+);
+
+const ServiceCTASection = dynamic(
+ () => import('@/components/services/service-cta-section').then(mod => ({ default: mod.ServiceCTASection })),
+ { ssr: false }
+);
interface ServiceDetailClientProps {
- service: typeof SERVICES[number];
+ service: Service;
}
-const iconMap: Record> = {
- Code: () => (
-
- ),
- BarChart3: () => (
-
- ),
- Lightbulb: () => (
-
- ),
- Puzzle: () => (
-
- ),
-};
-
-const challenges = {
- software: [
- { title: '需求不明确', description: '业务部门提不出清晰需求,开发团队反复返工' },
- { title: '技术选型困难', description: '技术栈更新快,不知道该选什么技术方案' },
- { title: '项目延期', description: '开发进度难以把控,上线时间一拖再拖' },
- { title: '维护成本高', description: '系统上线后问题不断,运维压力巨大' },
- ],
- data: [
- { title: '数据孤岛', description: '各系统数据分散,无法整合分析' },
- { title: '决策盲区', description: '缺乏数据支撑,决策凭感觉' },
- { title: '报表滞后', description: '手工制作报表,时效性差' },
- { title: '价值难挖', description: '数据很多,但不知道怎么用' },
- ],
- consulting: [
- { title: '方向不明', description: '数字化转型不知道从哪里入手' },
- { title: '技术债务', description: '历史系统包袱重,新技术难以引入' },
- { title: '人才短缺', description: '缺乏专业的技术规划和架构人才' },
- { title: '投入浪费', description: 'IT投入不少,但看不到明显效果' },
- ],
- solutions: [
- { title: '行业壁垒', description: '不了解行业最佳实践,走弯路' },
- { title: '方案碎片化', description: '各系统各自为政,无法协同' },
- { title: '实施风险', description: '大型项目实施失败率高' },
- { title: '效果难量化', description: '投入产出比不清晰,难以评估' },
- ],
-};
-
-const outcomes = {
- software: [
- { value: '30%', label: '开发效率提升' },
- { value: '50%', label: '返工率降低' },
- { value: '100%', label: '按时交付率' },
- ],
- data: [
- { value: '70%', label: '决策效率提升' },
- { value: '实时', label: '数据更新' },
- { value: '100+', label: '可视化报表' },
- ],
- consulting: [
- { value: '60%', label: '方向明确度' },
- { value: '40%', label: '试错成本降低' },
- { value: '3x', label: '转型速度提升' },
- ],
- solutions: [
- { value: '50%', label: '实施周期缩短' },
- { value: '30%', label: '成本降低' },
- { value: '95%', label: '客户满意度' },
- ],
-};
-
-export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
- const contentRef = useRef(null);
-
- const serviceChallenges = challenges[service.id as keyof typeof challenges] ?? [];
- const serviceOutcomes = outcomes[service.id as keyof typeof outcomes] ?? [];
- const relatedCases = CASES.slice(0, 2);
-
- const Icon = iconMap[service.icon];
-
+function InlineCTABanner() {
return (
-
-
-
-
-
-
-
- {Icon && }
-
-
-
- 核心业务
-
-
- {service.title}
-
-
-
-
- {service.description}
+
-
-
-
-
-
-
-
- {serviceChallenges.map((challenge, index) => (
-
-
{challenge.title}
-
{challenge.description}
-
- ))}
-
-
-
-
-
-
- {service.overview}
+
+ 预约一次免费咨询,获取专属数字化转型建议
-
- {service.features.map((feature, index) => (
-
-
- {feature}
-
- ))}
+
+
+ 免费咨询
+
+
+ 预约演示
+
-
-
-
-
-
- {service.process.map((step, index) => (
-
- ))}
-
-
-
-
-
-
- {serviceOutcomes.map((outcome, index) => (
-
-
- {outcome.value}
-
-
{outcome.label}
-
- ))}
-
-
-
- {service.benefits.map(b => b).join(';')}
-
-
-
-
-
-
-
- {relatedCases.map((caseItem) => (
-
-
- {caseItem.industry}
-
-
- {caseItem.title}
-
-
- {caseItem.description}
-
-
- ))}
-
-
-
-
-
-
- 查看其他服务
-
-
-
-
- 开始您的转型之旅
-
-
-
-
+
);
}
+
+export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
+ if (!service) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/(marketing)/services/[id]/page.tsx b/src/app/(marketing)/services/[id]/page.tsx
index 1bc9f5d..77b15d7 100644
--- a/src/app/(marketing)/services/[id]/page.tsx
+++ b/src/app/(marketing)/services/[id]/page.tsx
@@ -1,6 +1,6 @@
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
-import { SERVICES } from '@/lib/constants';
+import { SERVICES } from '@/lib/constants/services';
import { ServiceDetailClient } from './client';
export async function generateStaticParams() {
diff --git a/src/app/(marketing)/services/layout.tsx b/src/app/(marketing)/services/layout.tsx
new file mode 100644
index 0000000..2182be4
--- /dev/null
+++ b/src/app/(marketing)/services/layout.tsx
@@ -0,0 +1,14 @@
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: '核心业务',
+ description: '诺瓦隆(四川睿新致远科技)提供软件开发、数据分析、技术咨询、解决方案四大核心业务,助力企业实现全方位数字化转型。',
+};
+
+export default function ServicesLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/src/app/(marketing)/solutions/[id]/page.tsx b/src/app/(marketing)/solutions/[id]/page.tsx
new file mode 100644
index 0000000..ac7717b
--- /dev/null
+++ b/src/app/(marketing)/solutions/[id]/page.tsx
@@ -0,0 +1,31 @@
+import { SOLUTIONS } from '@/lib/constants/solutions';
+import type { Metadata } from 'next';
+import { notFound } from 'next/navigation';
+import { SolutionDetailClient } from './solution-detail-client';
+
+interface PageProps {
+ params: Promise<{ id: string }>;
+}
+
+export async function generateStaticParams() {
+ return SOLUTIONS.map((solution) => ({
+ id: solution.id,
+ }));
+}
+
+export async function generateMetadata({ params }: PageProps): Promise
{
+ const { id } = await params;
+ const solution = SOLUTIONS.find((s) => s.id === id);
+ if (!solution) {return { title: '解决方案 - 睿新致远' };}
+ return {
+ title: `${solution.industry}数字化转型方案 - 睿新致远`,
+ description: solution.description,
+ };
+}
+
+export default async function SolutionDetailPage({ params }: PageProps) {
+ const { id } = await params;
+ const solution = SOLUTIONS.find((s) => s.id === id);
+ if (!solution) {notFound();}
+ return ;
+}
diff --git a/src/app/(marketing)/solutions/[id]/solution-detail-client.tsx b/src/app/(marketing)/solutions/[id]/solution-detail-client.tsx
new file mode 100644
index 0000000..286db2d
--- /dev/null
+++ b/src/app/(marketing)/solutions/[id]/solution-detail-client.tsx
@@ -0,0 +1,218 @@
+'use client';
+
+import { SOLUTIONS } from '@/lib/constants/solutions';
+import { PRODUCTS } from '@/lib/constants/products';
+import { StaticLink } from '@/components/ui/static-link';
+import { CheckCircle, Phone } from 'lucide-react';
+import {
+ InkReveal,
+ FadeUp,
+ RippleButton,
+ FloatingElement,
+ StaggerContainer,
+ StaggerItem,
+ InkCard,
+ SealStamp,
+} from '@/lib/animations';
+import { ScrollReveal, inkRevealVariants, slideInLeftVariants } from '@/components/ui/scroll-animations';
+
+interface SolutionDetailClientProps {
+ solutionId: string;
+}
+
+export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps) {
+ const solution = SOLUTIONS.find((s) => s.id === solutionId) || null;
+
+ if (!solution) {
+ return (
+
+ );
+ }
+
+ return (
+
+ {/* Section 1: Hero */}
+
+
+
+
+ {solution.industry}
+
+
+
+ {solution.title}
+
+
+
+ {solution.subtitle}
+
+
+
+ {solution.description}
+
+
+
+
+
+ 预约演示
+
+
+ 获取定制方案
+
+
+
+
+
+
+
+ {/* Section 2: Challenges */}
+
+
+
+ 行业痛点
+ 您是否也面临这些挑战?
+
+
+ {solution.challenges.map((challenge, index) => (
+
+
+
+
+ {index + 1}
+
+
{challenge}
+
+
+
+ ))}
+
+
+
+
+ {/* Section 3: Our Solutions */}
+
+
+
+ 我们的解决方案
+ 针对行业痛点,量身定制
+
+
+ {solution.solutions.map((item, index) => (
+
+
+
+ ))}
+
+
+
+
+ {/* Section 4: Related Products */}
+ {solution.relatedProducts.length > 0 && (
+
+
+
+
+ {solution.relatedProducts.map((productId) => {
+ const product = PRODUCTS.find((p) => p.id === productId);
+ if (!product) {return null;}
+ return (
+
+
+
+
+ {product.category}
+
+
+ {product.title}
+
+
{product.description}
+
+
+
+ );
+ })}
+
+
+
+ )}
+
+ {/* Section 6: CTA */}
+
+
+
+
+
+
+
+
+
+
+
+ 准备好开启{solution.industry}数字化转型了吗?
+
+
+
+
+ 我们的专家团队将为您量身定制专属解决方案
+
+
+
+
+
+ 免费获取方案
+
+
+
+ 电话咨询
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/(marketing)/solutions/layout.tsx b/src/app/(marketing)/solutions/layout.tsx
index cef9157..29178f7 100644
--- a/src/app/(marketing)/solutions/layout.tsx
+++ b/src/app/(marketing)/solutions/layout.tsx
@@ -1,8 +1,8 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
- title: '解决方案 - 睿新致远',
- description: '三种角色,一种身份——您的成长伙伴',
+ title: '行业方案',
+ description: '诺瓦隆为制造业、政务服务、酒店管理、智慧农业等行业提供定制化数字化转型解决方案,助力企业实现数字化升级。',
};
export default function SolutionsLayout({
diff --git a/src/app/(marketing)/solutions/page.tsx b/src/app/(marketing)/solutions/page.tsx
index 92237cf..a5e0bf0 100644
--- a/src/app/(marketing)/solutions/page.tsx
+++ b/src/app/(marketing)/solutions/page.tsx
@@ -3,11 +3,29 @@
import { motion } from 'framer-motion';
import { useInView } from 'framer-motion';
import { useRef } from 'react';
+import dynamic from 'next/dynamic';
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { PageHeader } from '@/components/ui/page-header';
-import { ArrowRight, Lightbulb, Cpu, Users, CheckCircle2 } from 'lucide-react';
+import { ArrowRight } from 'lucide-react';
import { MethodologySection } from '@/components/sections/methodology-section';
+import { SOLUTIONS } from '@/lib/constants/solutions';
+import { FadeUp } from '@/lib/animations';
+
+const ConsultingSection = dynamic(
+ () => import('@/components/solutions/consulting-section').then(mod => ({ default: mod.ConsultingSection })),
+ { ssr: false }
+);
+
+const TechSolutionSection = dynamic(
+ () => import('@/components/solutions/tech-solution-section').then(mod => ({ default: mod.TechSolutionSection })),
+ { ssr: false }
+);
+
+const AccompanySection = dynamic(
+ () => import('@/components/solutions/accompany-section').then(mod => ({ default: mod.AccompanySection })),
+ { ssr: false }
+);
export default function SolutionsPage() {
const contentRef = useRef(null);
@@ -22,221 +40,53 @@ export default function SolutionsPage() {
-
-
-
-
-
-
-
-
- 模块一:数字化转型咨询 · 参谋伙伴
-
-
- 帮您看清前路,迈对第一步
-
-
-
-
-
- 数字化转型最大的成本,是走错方向的成本。
-
-
- 我们用行业智慧帮您洞察趋势,用理性分析帮您避开陷阱。
-
-
- 不堆砌概念,只帮您想清楚:该不该做、做什么、怎么做。
-
-
-
-
-
-
-
{
- const element = document.getElementById('contact');
- if (element) {
- element.scrollIntoView({ behavior: 'smooth' });
- }
- }}
- >
- 预约一次免费诊断
-
-
-
-
-
-
-
-
-
-
-
-
- 模块二:信息技术解决方案 · 技术伙伴
-
-
- 让技术真正为业务服务
-
-
-
-
-
-
- 我们不追逐“最火”的技术,只选择“最对”的技术。
-
-
- 将前沿技术深度融入您的业务场景,让每一行代码都产生业务价值。
-
-
- 您不必懂技术原理,只需要看见业务在增长。
-
-
-
-
-
-
-
{
- const element = document.getElementById('cases');
- if (element) {
- element.scrollIntoView({ behavior: 'smooth' });
- }
- }}
- >
- 查看技术案例
-
-
-
-
-
-
-
-
-
-
-
-
- 模块三:长期陪跑服务 · 同行伙伴
-
-
- 交付只是开始,陪伴才是常态
-
-
-
-
-
-
- 项目上线那天,是我们真正成为伙伴的开始。
-
-
- 我们建立长效服务机制,定期回访、持续优化、随时响应。
-
-
- 在您需要的时候,我们始终在场。
-
-
-
-
-
-
-
{
- const element = document.getElementById('contact');
- if (element) {
- element.scrollIntoView({ behavior: 'smooth' });
- }
- }}
- >
- 了解陪跑服务
-
-
-
-
+
+
+
+ {/* 行业解决方案入口 */}
+
+
+
+
+ 行业解决方案
+
+
+ 针对不同行业的数字化痛点,提供定制化解决方案
+
+
+
+ {SOLUTIONS.map((solution, index) => (
+
+
+
+
+
+ {solution.industry}
+
+
+
+ {solution.title}
+
+
+ {solution.description}
+
+
+
+
+
+ ))}
+
+
+
+
-
联系我们
-
diff --git a/src/app/(marketing)/team/client.tsx b/src/app/(marketing)/team/client.tsx
index 15554ae..80f52ab 100644
--- a/src/app/(marketing)/team/client.tsx
+++ b/src/app/(marketing)/team/client.tsx
@@ -11,7 +11,7 @@ import { Shield, Building2, Users, Code, Target, ArrowRight } from 'lucide-react
const TEAM_PILLARS = [
{
icon: Shield,
- title: '12年+ 行业深耕',
+ title: '12+ 年行业深耕',
description: '核心团队长期从事技术咨询、企业数字化等领域,服务覆盖金融、制造、零售、政务、农业等多个行业,积累了丰富的跨行业经验和最佳实践。',
},
{
@@ -44,7 +44,7 @@ export function TeamClient() {
diff --git a/src/app/(marketing)/team/page.tsx b/src/app/(marketing)/team/page.tsx
index 71ad41c..980a81c 100644
--- a/src/app/(marketing)/team/page.tsx
+++ b/src/app/(marketing)/team/page.tsx
@@ -2,7 +2,7 @@ import { COMPANY_INFO } from '@/lib/constants';
import { TeamClient } from './client';
export const metadata = {
- title: `核心团队 - ${COMPANY_INFO.name}`,
+ title: '核心团队',
description: `了解${COMPANY_INFO.name}的核心团队。我们的团队成员拥有丰富的行业经验和技术专长,致力于为客户提供专业的数字化转型服务。`,
};
diff --git a/src/app/globals.css b/src/app/globals.css
index 4add478..eb86c8c 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -212,7 +212,7 @@
text-rendering: optimizeLegibility;
}
- /* 青柳隷書 - 仅用于品牌标题"睿新致遠" */
+ /* 青柳隷書 - 仅用于品牌标题"睿新致远" */
.font-brand {
font-family: var(--font-aoyagi-reisho), 'Aoyagi Reisho', 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif !important;
font-weight: normal;
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 2d1548e..94d95ad 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -45,9 +45,9 @@ const maShanZheng = Ma_Shan_Zheng({
preload: true,
});
-// 青柳隷書 - 仅用于品牌标题"睿新致遠"(子集版本,仅包含4个字符)
+// 青柳隷書 - 仅用于品牌标题"睿新致遠"(完整版,支持繁体字)
const aoyagiReisho = localFont({
- src: "./fonts/AoyagiReisho-subset.ttf",
+ src: "./fonts/AoyagiReisho.ttf",
variable: "--font-aoyagi-reisho",
display: "swap",
preload: true,
@@ -60,7 +60,7 @@ export const metadata: Metadata = {
template: "%s | 四川睿新致远科技有限公司",
},
description: "四川睿新致远科技有限公司成立于2026年,专注于企业数字化转型服务,提供软件开发、云计算、数据分析、信息安全等一站式解决方案。",
- keywords: ["数字化转型", "企业软件", "ERP系统", "CRM系统", "云计算", "数据分析", "软件开发", "成都科技公司", "金融科技", "诺瓦隆"],
+ keywords: ["数字化转型", "企业软件", "ERP系统", "CRM系统", "云计算", "数据分析", "软件开发", "成都科技公司", "诺瓦隆"],
authors: [{ name: "四川睿新致远科技有限公司" }],
creator: "四川睿新致远科技有限公司",
publisher: "四川睿新致远科技有限公司",
@@ -101,7 +101,7 @@ export const metadata: Metadata = {
canonical: "https://www.novalon.cn",
},
verification: {
- google: "your-google-verification-code",
+ google: "pending-verification",
},
};
diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx
index 997c357..3d6af1a 100644
--- a/src/app/not-found.tsx
+++ b/src/app/not-found.tsx
@@ -2,7 +2,7 @@
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
-import { Home, ArrowLeft, Search } from 'lucide-react';
+import { Home, ArrowLeft, Building2, Briefcase, Package, Trophy } from 'lucide-react';
export default function NotFound() {
return (
@@ -58,7 +58,7 @@ export default function NotFound() {
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
>
-
+
关于我们
@@ -71,7 +71,7 @@ export default function NotFound() {
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
>
-
+
核心业务
@@ -84,7 +84,7 @@ export default function NotFound() {
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
>
产品服务
@@ -97,10 +97,10 @@ export default function NotFound() {
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
>
-
+
diff --git a/src/app/privacy/page.tsx b/src/app/privacy/page.tsx
index e74f829..2190fc5 100644
--- a/src/app/privacy/page.tsx
+++ b/src/app/privacy/page.tsx
@@ -1,8 +1,8 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
- title: '隐私政策 - 睿新致远',
- description: '四川睿新致远科技有限公司隐私政策',
+ title: '隐私政策',
+ description: '四川睿新致远科技有限公司(诺瓦隆)隐私政策。我们重视您的隐私,致力于保护您的个人信息安全。',
};
export default function PrivacyPolicyPage() {
@@ -22,6 +22,7 @@ export default function PrivacyPolicyPage() {
+
最后更新日期:2026年4月25日
引言
diff --git a/src/app/terms/page.tsx b/src/app/terms/page.tsx
index c718a40..3defb88 100644
--- a/src/app/terms/page.tsx
+++ b/src/app/terms/page.tsx
@@ -1,8 +1,8 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
- title: '服务条款 - 睿新致远',
- description: '四川睿新致远科技有限公司服务条款',
+ title: '服务条款',
+ description: '四川睿新致远科技有限公司(诺瓦隆)服务条款。请仔细阅读以下条款,使用我们的服务即表示您同意这些条款。',
};
export default function TermsOfServicePage() {
@@ -170,7 +170,7 @@ export default function TermsOfServicePage() {
最后更新日期
- 2026年2月26日
+ 2026年4月25日
diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx
index e2330ec..0153b50 100644
--- a/src/components/layout/footer.tsx
+++ b/src/components/layout/footer.tsx
@@ -5,7 +5,9 @@ import { COMPANY_INFO, NAVIGATION } from '@/lib/constants';
export function Footer() {
return (
-