首页页面

This commit is contained in:
2025-03-11 14:57:23 +08:00
parent 9b36ab40f2
commit 5e3ade9aba
38 changed files with 1092 additions and 182 deletions

View File

@@ -1,36 +1,23 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## 功能布局
## Getting Started
### 首页
First, run the development server:
- 页头
- LOGO
- 菜单
- 登录/注册
- 正文
- 优势介绍
- 数据展示
- 产品推荐
- 客户案例
- 合作伙伴
- 新闻动态
- 页脚
- 关于我们
- 网站地图
- 备案/版权信息
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
### 后台
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
### 授权

View File

@@ -11,6 +11,12 @@ const compat = new FlatCompat({
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
{
rules: {
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
},
];
export default eslintConfig;

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev -H 0.0.0.0 --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
@@ -14,6 +14,8 @@
"next": "15.2.1"
},
"devDependencies": {
"@next/eslint-plugin-next": "^15.2.1",
"eslint-plugin-react-hooks": "^5.2.0",
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",

30
pnpm-lock.yaml generated
View File

@@ -21,6 +21,9 @@ importers:
'@eslint/eslintrc':
specifier: ^3
version: 3.3.0
'@next/eslint-plugin-next':
specifier: ^15.2.1
version: 15.2.1
'@tailwindcss/postcss':
specifier: ^4
version: 4.0.9
@@ -39,6 +42,9 @@ importers:
eslint-config-next:
specifier: 15.2.1
version: 15.2.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
eslint-plugin-react-hooks:
specifier: ^5.2.0
version: 5.2.0(eslint@9.21.0(jiti@2.4.2))
tailwindcss:
specifier: ^4
version: 4.0.9
@@ -135,67 +141,79 @@ packages:
resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-arm@1.0.5':
resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.0.4':
resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-x64@1.0.4':
resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-linux-arm64@0.33.5':
resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-arm@0.33.5':
resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-linux-s390x@0.33.5':
resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-linux-x64@0.33.5':
resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.33.5':
resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-linuxmusl-x64@0.33.5':
resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-wasm32@0.33.5':
resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
@@ -237,24 +255,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@next/swc-linux-arm64-musl@15.2.1':
resolution: {integrity: sha512-3v0pF/adKZkBWfUffmB/ROa+QcNTrnmYG4/SS+r52HPwAK479XcWoES2I+7F7lcbqc7mTeVXrIvb4h6rR/iDKg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@next/swc-linux-x64-gnu@15.2.1':
resolution: {integrity: sha512-RbsVq2iB6KFJRZ2cHrU67jLVLKeuOIhnQB05ygu5fCNgg8oTewxweJE8XlLV+Ii6Y6u4EHwETdUiRNXIAfpBww==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@next/swc-linux-x64-musl@15.2.1':
resolution: {integrity: sha512-QHsMLAyAIu6/fWjHmkN/F78EFPKmhQlyX5C8pRIS2RwVA7z+t9cTb0IaYWC3EHLOTjsU7MNQW+n2xGXr11QPpg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
'@next/swc-win32-arm64-msvc@15.2.1':
resolution: {integrity: sha512-Gk42XZXo1cE89i3hPLa/9KZ8OuupTjkDmhLaMKFohjf9brOeZVEa3BQy1J9s9TWUqPhgAEbwv6B2+ciGfe54Vw==}
@@ -334,24 +356,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.0.9':
resolution: {integrity: sha512-3eMjyTC6HBxh9nRgOHzrc96PYh1/jWOwHZ3Kk0JN0Kl25BJ80Lj9HEvvwVDNTgPg154LdICwuFLuhfgH9DULmg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.0.9':
resolution: {integrity: sha512-v0D8WqI/c3WpWH1kq/HP0J899ATLdGZmENa2/emmNjubT0sWtEke9W9+wXeEoACuGAhF9i3PO5MeyditpDCiWQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.0.9':
resolution: {integrity: sha512-Kvp0TCkfeXyeehqLJr7otsc4hd/BUPfcIGrQiwsTVCfaMfjQZCG7DjI+9/QqPZha8YapLA9UoIcUILRYO7NE1Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-win32-arm64-msvc@4.0.9':
resolution: {integrity: sha512-m3+60T/7YvWekajNq/eexjhV8z10rswcz4BC9bioJ7YaN+7K8W2AmLmG0B79H14m6UHE571qB0XsPus4n0QVgQ==}
@@ -1128,24 +1154,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-musl@1.29.1:
resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-gnu@1.29.1:
resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-musl@1.29.1:
resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-win32-arm64-msvc@1.29.1:
resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==}

BIN
public/banner.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

4
public/check.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="24" rx="2" fill="#2470F9"/>
<path d="M9.42868 17.6575C9.15888 17.6491 8.90283 17.5364 8.71438 17.3432L4.45011 13.1003C4.25501 12.898 4.146 12.6278 4.146 12.3467C4.146 12.0656 4.25501 11.7955 4.45011 11.5932C4.54836 11.4942 4.66521 11.4157 4.79393 11.3622C4.92265 11.3086 5.06069 11.281 5.20011 11.281C5.33952 11.281 5.47757 11.3086 5.60628 11.3622C5.735 11.4157 5.85185 11.4942 5.95011 11.5932L9.42868 15.0932L18.3144 7.31458C18.4115 7.21501 18.5276 7.13588 18.6558 7.08186C18.784 7.02783 18.9217 7 19.0608 7C19.1999 7 19.3376 7.02783 19.4658 7.08186C19.594 7.13588 19.7101 7.21501 19.8072 7.31458C19.9061 7.41284 19.9846 7.52969 20.0382 7.65841C20.0918 7.78712 20.1194 7.92517 20.1194 8.06458C20.1194 8.204 20.0918 8.34204 20.0382 8.47076C19.9846 8.59948 19.9061 8.71633 19.8072 8.81458L10.1787 17.3432C9.98014 17.5431 9.71043 17.6561 9.42868 17.6575Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 997 B

BIN
public/earth.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -1 +0,0 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 391 B

View File

@@ -1 +0,0 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

BIN
public/map.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -1 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
<svg width="44" height="78" viewBox="0 0 44 78" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Vector" d="M42.1191 35.139C43.2285 36.231 44.2588 37.7129 43.9418 39.117C44.1795 40.521 43.07 41.847 42.1191 42.939L7.6472 76.713C5.90387 78.429 3.05096 78.429 1.30753 76.713C-0.435894 74.997 -0.435796 72.189 1.30753 70.4731L34.1153 39.039L1.30763 7.52691C-0.435794 5.81098 -0.435794 3.00291 1.30763 1.28699C3.05106 -0.42894 5.90387 -0.429039 7.6472 1.28699L42.1191 35.139Z" fill="#E3E3E3"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 505 B

BIN
public/s1-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

BIN
public/s1-2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
public/s1-3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

BIN
public/s1-4.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

10
public/s1-check.svg Normal file
View File

@@ -0,0 +1,10 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#229;&#183;&#178;&#229;&#139;&#190;&#233;&#128;&#137;32 12" clip-path="url(#clip0_77_98)">
<path id="Vector" d="M3.46154 0H14.5385C15.4565 0 16.337 0.364697 16.9861 1.01386C17.6353 1.66303 18 2.54348 18 3.46154V14.5385C18 15.4565 17.6353 16.337 16.9861 16.9861C16.337 17.6353 15.4565 18 14.5385 18H3.46154C2.54348 18 1.66303 17.6353 1.01386 16.9861C0.364697 16.337 0 15.4565 0 14.5385L0 3.46154C0 2.54348 0.364697 1.66303 1.01386 1.01386C1.66303 0.364697 2.54348 0 3.46154 0ZM3.46154 1.38462C2.9107 1.38462 2.38243 1.60343 1.99293 1.99293C1.60343 2.38243 1.38462 2.9107 1.38462 3.46154V14.5385C1.38462 14.8112 1.43834 15.0813 1.54271 15.3333C1.64709 15.5852 1.80007 15.8142 1.99293 16.0071C2.18579 16.1999 2.41475 16.3529 2.66673 16.4573C2.91872 16.5617 3.18879 16.6154 3.46154 16.6154H14.5385C14.8112 16.6154 15.0813 16.5617 15.3333 16.4573C15.5852 16.3529 15.8142 16.1999 16.0071 16.0071C16.1999 15.8142 16.3529 15.5852 16.4573 15.3333C16.5617 15.0813 16.6154 14.8112 16.6154 14.5385V3.46154C16.6154 3.18879 16.5617 2.91872 16.4573 2.66673C16.3529 2.41475 16.1999 2.18579 16.0071 1.99293C15.8142 1.80007 15.5852 1.64709 15.3333 1.54271C15.0813 1.43834 14.8112 1.38462 14.5385 1.38462H3.46154ZM13.743 5.92338C13.8041 5.98151 13.8531 6.0511 13.8873 6.12818C13.9214 6.20526 13.9401 6.28831 13.9421 6.3726C13.9442 6.45689 13.9296 6.54076 13.8993 6.61941C13.8689 6.69806 13.8233 6.76996 13.7652 6.831L8.50085 12.3348C8.49877 12.3376 8.49392 12.339 8.48977 12.3432L8.48285 12.3528C8.44477 12.3902 8.39977 12.4096 8.35615 12.4359C8.32846 12.4512 8.307 12.474 8.27862 12.4858C8.20213 12.5178 8.12007 12.5345 8.03714 12.5347C7.95421 12.5349 7.87205 12.5188 7.79538 12.4872C7.77323 12.4782 7.75523 12.4588 7.73308 12.447C7.68462 12.4214 7.63477 12.3972 7.59185 12.357C7.58838 12.3542 7.587 12.3494 7.58285 12.3452C7.57938 12.3432 7.57592 12.3418 7.57315 12.339L4.92162 9.58638C4.86293 9.5258 4.81679 9.45421 4.78585 9.37574C4.75491 9.29727 4.73978 9.21346 4.74132 9.12912C4.74287 9.04479 4.76106 8.96159 4.79485 8.8843C4.82864 8.80702 4.87737 8.73717 4.93823 8.67877C4.99877 8.62 5.07035 8.57379 5.14882 8.5428C5.2273 8.5118 5.31113 8.49664 5.3955 8.49819C5.47986 8.49973 5.56308 8.51795 5.64037 8.5518C5.71766 8.58564 5.78749 8.63444 5.84585 8.69538L8.03354 10.9648L12.834 5.94415C12.8923 5.88305 12.9621 5.83404 13.0393 5.79992C13.1166 5.7658 13.1998 5.74724 13.2842 5.74532C13.3686 5.74339 13.4526 5.75812 13.5313 5.78868C13.6101 5.81923 13.682 5.86501 13.743 5.92338Z" fill="#FF6B00"/>
</g>
<defs>
<clipPath id="clip0_77_98">
<rect width="18" height="18" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/s2-1-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
public/s2-1-2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
public/s2-1-3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
public/s2-1-main.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
public/s2-2-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
public/s2-2-2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/s2-2-3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
public/s2-2-main.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
public/s3-main.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

View File

@@ -1 +0,0 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 128 B

View File

@@ -1 +0,0 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

Before

Width:  |  Height:  |  Size: 385 B

View File

@@ -0,0 +1,243 @@
import {ReactNode} from 'react'
export type DashboardPageProps = {
}
export default function DashboardPage(props: DashboardPageProps) {
return (
<div className="flex gap-6">
{/* 左侧主要内容区域 */}
<div className="flex-1">
{/* 页面标题 */}
<div className="mb-8 bg-gradient-to-r from-blue-50 to-indigo-50 p-6 rounded-xl border border-blue-100">
<div className="flex items-center gap-4">
<div className="p-3 bg-blue-600 rounded-lg">
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
</div>
<div>
<h1 className="text-3xl font-bold text-gray-900">IP资源监控中心</h1>
<p className="mt-2 text-gray-600">IP资源使用情况和系统性能指标</p>
</div>
</div>
</div>
{/* 数据卡片网格 */}
<div className="grid grid-cols-3 gap-4 mb-6">
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<div className="flex items-center">
<div className="p-3 bg-blue-100 rounded-lg">
<svg className="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
</svg>
</div>
<div className="ml-4">
<h2 className="text-sm font-medium text-gray-600">IP数</h2>
<p className="text-2xl font-semibold text-gray-900">8,721</p>
<p className="text-sm text-green-600">12% </p>
</div>
</div>
</div>
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<div className="flex items-center">
<div className="p-3 bg-green-100 rounded-lg">
<svg className="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div className="ml-4">
<h2 className="text-sm font-medium text-gray-600">IP可用率</h2>
<p className="text-2xl font-semibold text-gray-900">99.9%</p>
<p className="text-sm text-green-600">SLA标准</p>
</div>
</div>
</div>
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<div className="flex items-center">
<div className="p-3 bg-purple-100 rounded-lg">
<svg className="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<div className="ml-4">
<h2 className="text-sm font-medium text-gray-600"></h2>
<p className="text-2xl font-semibold text-gray-900">47ms</p>
<p className="text-sm text-green-600"></p>
</div>
</div>
</div>
</div>
{/* 监控指标区域 */}
<div className="grid grid-cols-2 gap-4 mb-6">
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<h3 className="text-lg font-medium text-gray-900 mb-4">使</h3>
<div className="h-64 bg-gray-50 rounded-lg flex items-center justify-center">
使
</div>
<div className="mt-4 grid grid-cols-3 gap-4 text-center text-sm">
<div>
<p className="text-gray-600"></p>
<p className="font-semibold">1.2 Gbps</p>
</div>
<div>
<p className="text-gray-600"></p>
<p className="font-semibold">2.5 Gbps</p>
</div>
<div>
<p className="text-gray-600"></p>
<p className="font-semibold">800 Mbps</p>
</div>
</div>
</div>
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<h3 className="text-lg font-medium text-gray-900 mb-4">IP地理分布</h3>
<div className="h-64 bg-gray-50 rounded-lg flex items-center justify-center">
</div>
<div className="mt-4 grid grid-cols-3 gap-4 text-center text-sm">
<div>
<p className="text-gray-600"></p>
<p className="font-semibold">45%</p>
</div>
<div>
<p className="text-gray-600"></p>
<p className="font-semibold">35%</p>
</div>
<div>
<p className="text-gray-600"></p>
<p className="font-semibold">20%</p>
</div>
</div>
</div>
</div>
{/* 告警信息 */}
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-medium text-gray-900"></h3>
<span className="text-sm text-blue-600 cursor-pointer hover:text-blue-700"></span>
</div>
<div className="space-y-3">
<div className="flex items-center p-4 bg-red-50 rounded-lg">
<div className="p-2 bg-red-100 rounded-lg mr-4">
<svg className="w-5 h-5 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div>
<h4 className="text-sm font-medium text-red-900">使</h4>
<p className="text-xs text-red-600 mt-1">5</p>
</div>
</div>
<div className="flex items-center p-4 bg-yellow-50 rounded-lg">
<div className="p-2 bg-yellow-100 rounded-lg mr-4">
<svg className="w-5 h-5 text-yellow-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div>
<h4 className="text-sm font-medium text-yellow-900">IP资源池使用率达到80%</h4>
<p className="text-xs text-yellow-600 mt-1">20</p>
</div>
</div>
</div>
</div>
</div>
{/* 右侧边栏 */}
<div className="w-80 space-y-6">
{/* 用户信息卡片 */}
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<div className="flex items-center space-x-4">
<div className="relative">
<div className="w-14 h-14 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center">
<span className="text-xl font-bold text-white">A</span>
</div>
<div className="absolute -bottom-1 -right-1 w-4 h-4 bg-green-500 rounded-full border-2 border-white"></div>
</div>
<div>
<h4 className="font-semibold text-gray-900"></h4>
<p className="text-sm text-gray-600">admin@example.com</p>
</div>
</div>
<div className="mt-6 pt-4 border-t border-gray-100">
<div className="grid grid-cols-2 gap-4 text-center">
<div className="bg-blue-50 p-3 rounded-lg">
<p className="text-sm font-medium text-gray-600">线</p>
<p className="text-lg font-semibold text-blue-600">4.5h</p>
</div>
<div className="bg-green-50 p-3 rounded-lg">
<p className="text-sm font-medium text-gray-600"></p>
<p className="text-lg font-semibold text-green-600">12</p>
</div>
</div>
</div>
</div>
{/* 快捷操作 */}
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<h3 className="text-lg font-semibold text-gray-900 mb-4"></h3>
<div className="grid grid-cols-2 gap-3">
<button className="flex items-center justify-center space-x-2 bg-blue-50 text-blue-700 p-3 rounded-lg hover:bg-blue-100 transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
<span></span>
</button>
<button className="flex items-center justify-center space-x-2 bg-purple-50 text-purple-700 p-3 rounded-lg hover:bg-purple-100 transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
<span></span>
</button>
<button className="flex items-center justify-center space-x-2 bg-green-50 text-green-700 p-3 rounded-lg hover:bg-green-100 transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<span></span>
</button>
<button className="flex items-center justify-center space-x-2 bg-orange-50 text-orange-700 p-3 rounded-lg hover:bg-orange-100 transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span></span>
</button>
</div>
</div>
{/* 系统公告 */}
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow transition-shadow">
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-semibold text-gray-900"></h3>
<span className="text-sm text-blue-600 hover:text-blue-700 cursor-pointer"></span>
</div>
<div className="space-y-4">
<div className="flex items-start space-x-3">
<div className="w-2 h-2 mt-2 bg-red-500 rounded-full"></div>
<div>
<p className="text-sm text-gray-900">2</p>
<p className="text-xs text-gray-500 mt-1">2024-01-20 10:00</p>
</div>
</div>
<div className="flex items-start space-x-3">
<div className="w-2 h-2 mt-2 bg-blue-500 rounded-full"></div>
<div>
<p className="text-sm text-gray-900">IP资源管理系统V2.0</p>
<p className="text-xs text-gray-500 mt-1">2024-01-18 15:30</p>
</div>
</div>
</div>
</div>
</div>
</div>
)
}

198
src/app/(admin)/layout.tsx Normal file
View File

@@ -0,0 +1,198 @@
import Link from 'next/link'
import {ReactNode} from 'react'
export type AdminLayoutProps = {
children: ReactNode
}
export default function AdminLayout(props: AdminLayoutProps) {
return (
<div className="min-w-[1200px] overflow-auto bg-gray-50 flex">
{/* 左侧导航栏 */}
<aside className="w-64 h-screen overflow-y-auto bg-white border-r border-gray-200">
{/* Logo区域 */}
<div className="h-16 flex items-center px-6">
<svg className="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
<h1 className="ml-3 text-xl font-bold text-gray-900"></h1>
</div>
{/* 导航菜单 */}
<nav className="mt-4 px-4">
<div className="space-y-6">
{/* 概览 */}
<div>
<div className="px-3 mb-2 text-xs font-medium text-gray-500 uppercase tracking-wider"></div>
<Link
href="/dashboard"
className="flex items-center px-3 py-2 text-sm font-medium text-blue-600 bg-blue-50 rounded-md">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</svg>
</Link>
</div>
{/* 用户管理 */}
<div>
<div className="px-3 mb-2 text-xs font-medium text-gray-500 uppercase tracking-wider"></div>
<div className="space-y-1">
<a
href="/users"
className="flex items-center px-3 py-2 text-sm font-medium text-gray-700 rounded-md hover:bg-gray-50">
<svg className="w-5 h-5 mr-2 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"/>
</svg>
</a>
<a
href="/users/roles"
className="flex items-center px-3 py-2 text-sm font-medium text-gray-700 rounded-md hover:bg-gray-50">
<svg className="w-5 h-5 mr-2 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"/>
</svg>
</a>
</div>
</div>
{/* 订单管理 */}
<div>
<div className="px-3 mb-2 text-xs font-medium text-gray-500 uppercase tracking-wider"></div>
<div className="space-y-1">
<a
href="/orders"
className="flex items-center px-3 py-2 text-sm font-medium text-gray-700 rounded-md hover:bg-gray-50">
<svg className="w-5 h-5 mr-2 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
</svg>
</a>
<a
href="/orders/refunds"
className="flex items-center px-3 py-2 text-sm font-medium text-gray-700 rounded-md hover:bg-gray-50">
<svg className="w-5 h-5 mr-2 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M16 15v-1a4 4 0 00-4-4H8m0 0l3 3m-3-3l3-3m9 14V5a2 2 0 00-2-2H6a2 2 0 00-2 2v16l4-2 4 2 4-2 4 2z"/>
</svg>
退
</a>
</div>
</div>
{/* 系统设置 */}
<div>
<div className="px-3 mb-2 text-xs font-medium text-gray-500 uppercase tracking-wider"></div>
<a
href="/settings"
className="flex items-center px-3 py-2 text-sm font-medium text-gray-700 rounded-md hover:bg-gray-50">
<svg className="w-5 h-5 mr-2 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
</a>
</div>
</div>
</nav>
</aside>
{/* 右侧主内容区 */}
<div className="flex-1 h-screen flex flex-col">
{/* 顶部导航栏 */}
<header className="h-16 bg-white border-b border-gray-200 px-6 flex items-center justify-between">
{/* 面包屑导航 */}
<div className="flex items-center">
<a href="/dashboard" className="text-gray-600 hover:text-blue-600"></a>
<svg className="w-4 h-4 mx-2 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7"/>
</svg>
<span className="text-gray-400"></span>
</div>
{/* 右侧工具栏 */}
<div className="flex items-center space-x-3">
{/* 搜索框 */}
<div className="w-56">
<div className="relative">
<input
type="text"
placeholder="搜索..."
className="w-full h-10 pl-10 pr-4 text-sm bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500"
/>
<svg
className="w-5 h-5 text-gray-400 absolute left-3 top-2.5" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
</div>
</div>
{/* 全屏切换 */}
<button
className="p-2 text-gray-500 hover:text-gray-600 hover:bg-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"/>
</svg>
</button>
{/* 通知 */}
<button
className="relative p-2 text-gray-500 hover:text-gray-600 hover:bg-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/>
</svg>
<span className="absolute top-2 right-2 w-2 h-2 bg-red-500 rounded-full"></span>
</button>
{/* 用户菜单 */}
<div className="relative">
<button
className="flex items-center space-x-3 p-1.5 rounded-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">
<img
src="/images/avatar.jpg"
alt="用户头像"
className="w-9 h-9 rounded-full object-cover border-2 border-gray-200"
/>
<div className="text-left">
<div className="font-medium text-gray-800"></div>
<div className="text-gray-500 text-xs"></div>
</div>
<svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7"/>
</svg>
</button>
</div>
</div>
</header>
{/* 主内容区域 */}
<main className={`flex-1 overflow-auto p-6`}>
{props.children}
</main>
</div>
</div>
)
}

View File

@@ -0,0 +1,102 @@
import {ReactNode} from 'react'
export type LoginPageProps = {}
export default function LoginPage(props: LoginPageProps) {
return (
<div className="flex h-screen w-screen">
{/* 左侧背景图 */}
<div className="relative flex-1 hidden lg:block">
<img
src="/images/login-bg.jpg"
alt="登录背景"
className="object-cover w-full h-full"
/>
<div className="absolute inset-0 bg-black/30">
<div className="flex items-center justify-center h-full">
<h1 className="text-4xl font-bold text-white">
</h1>
</div>
</div>
</div>
{/* 右侧登录表单 */}
<div className="w-[600px] flex items-center justify-center p-8">
<div className="w-full space-y-8">
<div className="text-center">
<h2 className="text-3xl font-bold text-gray-900">
</h2>
<p className="mt-2 text-sm text-gray-600">
{' '}
<a href="#" className="font-medium text-blue-600 hover:text-blue-500">
14
</a>
</p>
</div>
<form className="mt-8 space-y-6">
<div className="space-y-4">
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700">
</label>
<input
id="email"
name="email"
type="email"
autoComplete="email"
required
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-gray-700">
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
/>
</div>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center">
<input
id="remember-me"
name="remember-me"
type="checkbox"
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<label htmlFor="remember-me" className="ml-2 block text-sm text-gray-900">
</label>
</div>
<div className="text-sm">
<a href="#" className="font-medium text-blue-600 hover:text-blue-500">
</a>
</div>
</div>
<button
type="submit"
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
</button>
</form>
</div>
</div>
</div>
)
}

106
src/app/(home)/footer.tsx Normal file
View File

@@ -0,0 +1,106 @@
import Wrap from '@/components/wrap'
export type FooterProps = {}
export default function Footer(props: FooterProps) {
return (
<footer className="h-[500px] bg-gray-900 p-12 text-white overflow-hidden">
<Wrap className="flex flex-col">
<div className={`flex-auto overflow-hidden flex justify-between`}>
<div className="flex">
<div className="flex flex-col items-center">
<img src="/logo.svg" alt="logo" className="w-44 h-44 bg-gray-100"/>
<span className="text-sm font-light mt-6"></span>
</div>
</div>
<div className={`flex flex-col gap-4`}>
<h3></h3>
<p className={`text-sm text-gray-400 font-light`}>大客户经理:张经理</p>
<p className={`text-sm text-gray-400 font-light`}>/微信:18751847847</p>
<p className={`text-sm text-gray-400 font-light`}>QQ号:800180559</p>
<h3></h3>
<p className={`text-sm text-gray-400 font-light`}></p>
<p className={`text-sm text-gray-400 font-light`}></p>
</div>
<div>
<h3></h3>
<ul className={`mt-4 flex flex-col gap-4 font-light`}>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}>广</a></li>
</ul>
</div>
<div>
<h3></h3>
<ul className={`mt-4 flex flex-col gap-4 font-light`}>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}>IP代理</a></li>
</ul>
</div>
<div>
<h3></h3>
<ul className={`mt-4 flex flex-col gap-4 font-light`}>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
</ul>
</div>
<div>
<h3>使</h3>
<ul className={`mt-4 h-[184px] flex flex-col flex-wrap gap-4 gap-x-6 font-light`}>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}>广</a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}>SEO优化</a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
</ul>
</div>
<div>
<h3></h3>
<ul className={`mt-4 flex flex-col gap-4 font-light`}>
<li><a href="#" className={`text-sm text-gray-400`}>API提取</a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
</ul>
</div>
<div>
<h3></h3>
<ul className={`mt-4 flex flex-col gap-4 font-light`}>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
<li><a href="#" className={`text-sm text-gray-400`}>使</a></li>
<li><a href="#" className={`text-sm text-gray-400`}></a></li>
</ul>
</div>
</div>
<div className={`flex-none mt-6 pt-6 border-t border-gray-300 flex flex-col items-center`}>
<p className={`text-sm font-light`}>
HTTP仅提供代理IP服务使HTTP从事任何违法犯罪行为HTTP不承担任何法律责任
<a href="#"></a>
</p>
<p className={`text-sm mt-3 font-light`}>
577404-405</p>
<p className={`text-sm mt-3 font-light`}>
B1-11111111
ICP备111111111号-1
11111111111111
</p>
</div>
</Wrap>
</footer>
)
}

101
src/app/(home)/header.tsx Normal file
View File

@@ -0,0 +1,101 @@
'use client'
import {ReactNode, useEffect, useState} from 'react'
import Link from 'next/link'
import Wrap from '@/components/wrap'
export type HeaderProps = {}
export default function Header(props: HeaderProps) {
const [isScrolled, setIsScrolled] = useState(window.scrollY > 0)
const handleScroll = () => {
setIsScrolled(window.scrollY > 0)
}
useEffect(() => {
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
return (
<header
className={[
`w-full h-24 fixed top-0 shadow-lg`,
`transition-shadow duration-200 ${isScrolled ? 'bg-white' : 'bg-transparent shadow-transparent'}`,
].join(' ')}>
<Wrap className="flex items-center justify-between">
{/* 菜单 */}
<div className="flex items-center justify-between gap-8">
{/* logo */}
<Link href="/">
<img alt={`logo`} className={`w-16 h-16 rounded-full bg-gray-100`}/>
</Link>
{/* 菜单 */}
<nav className={`flex items-center`}>
<ul className="flex items-center gap-4 text-xl">
<NavItemTop>
<Link href={`/`}></Link>
</NavItemTop>
<NavItemTop>
<button></button>
<SvgDown/>
</NavItemTop>
<NavItemTop>
<button></button>
<SvgDown/>
</NavItemTop>
<NavItemTop>
<button></button>
<SvgDown/>
</NavItemTop>
<NavItemTop>
<Link href={`#`}></Link>
</NavItemTop>
<NavItemTop>
<Link href={`#`}>广</Link>
</NavItemTop>
</ul>
</nav>
</div>
{/* 登录 */}
<div className={`flex items-center`}>
<a
href="#"
className={`w-24 h-12 flex items-center justify-center text-xl font-medium`}>
<span></span>
</a>
<a
href="#"
className={`w-24 h-12 bg-gradient-to-r from-blue-500 to-cyan-400 rounded-sm flex items-center justify-center text-xl font-medium text-white`}>
<span></span>
</a>
</div>
</Wrap>
</header>
)
}
type NavItemTopProps = {
children: ReactNode
}
function NavItemTop(props: NavItemTopProps) {
return (
<li className={`flex items-center text-xl px-2`}>
{props.children}
</li>
)
}
function SvgDown() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6 9L12 15L18 9" stroke="currentColor" strokeWidth="2" strokeLinecap="round"
strokeLinejoin="round"/>
</svg>
)
}

240
src/app/(home)/page.tsx Normal file
View File

@@ -0,0 +1,240 @@
import {ReactNode} from 'react'
import Link from 'next/link'
import Header from '@/app/(home)/header'
import Wrap from '@/components/wrap'
import Image from 'next/image'
import Footer from './footer'
export default function Home() {
return (
<div className={`overflow-auto flex flex-col items-stretch relative`}>
{/* 页头 */}
<Header/>
{/* 正文 */}
<main>
{/* banner */}
<section className={`w-full h-[800px] bg-[url('/banner.webp')] bg-cover`}>
<Wrap className={`overflow-hidden`}>
<h1 className={`mt-64 text-4xl font-medium`}></h1>
<p className={`mt-10 text-gray-400`}>IP代理服务</p>
<div className={`mt-24 flex gap-8`}>
<p className={`flex gap-4 items-center`}>
<Image src={`/check.svg`} alt={`checkbox`} width={24} height={24}/>
<span className={`text-xl font-light`}>200+</span>
</p>
<p className={`flex gap-4 items-center`}>
<Image src={`/check.svg`} alt={`checkbox`} width={24} height={24}/>
<span className={`text-xl font-light`}>300+</span>
</p>
<p className={`flex gap-4 items-center`}>
<Image src={`/check.svg`} alt={`checkbox`} width={24} height={24}/>
<span className={`text-xl font-light`}>&</span>
</p>
</div>
<button className={`mt-32 w-96 h-24 bg-gradient-to-r from-blue-500 to-cyan-400 rounded-lg shadow-lg text-white text-4xl font-medium`}>
</button>
</Wrap>
</section>
{/* 数据展示 */}
<section className={`my-36`}>
<Wrap className={`flex flex-col items-center`}>
<h2 className={`text-3xl font-medium`}>IP资源及超大的带宽线路</h2>
<ul className={`w-full h-48 shadow-[0_0_20px_4px] shadow-blue-50 mt-24 flex`}>
<li className={`flex-1 flex flex-col items-center justify-center`}>
<p className={`text-xl`}>线</p>
<p className={`mt-9 text-5xl bg-gradient-to-t from-blue-500 to-cyan-400 bg-clip-text text-transparent font-bold pb-2 -mb-2`}>350+</p>
</li>
<li className={`flex-1 flex flex-col items-center justify-center`}>
<p className={`text-xl`}>IP数量</p>
<p className={`mt-9 text-5xl bg-gradient-to-t from-blue-500 to-cyan-400 bg-clip-text text-transparent font-bold pb-2 -mb-2`}>1,350,129</p>
</li>
<li className={`flex-1 flex flex-col items-center justify-center`}>
<p className={`text-xl`}></p>
<p className={`mt-9 text-5xl bg-gradient-to-t from-blue-500 to-cyan-400 bg-clip-text text-transparent font-bold pb-2 -mb-2`}>26,578</p>
</li>
<li className={`flex-1 flex flex-col items-center justify-center`}>
<p className={`text-xl`}>IP可用率</p>
<p className={`mt-9 text-5xl bg-gradient-to-t from-blue-500 to-cyan-400 bg-clip-text text-transparent font-bold pb-2 -mb-2`}>99%</p>
</li>
</ul>
<img src={`/map.webp`} alt={`map`} className="w-[1200px]"/>
</Wrap>
</section>
{/* 优势 1 */}
<section>
<Wrap>
<h2 className={`text-3xl font-medium text-center`}>HTTP安全合规的代理IP资源池</h2>
<ul className={`mt-28 pt-16 pb-16 flex justify-between bg-[url('/earth.webp')] bg-cover`}>
<li className={`p-8 flex flex-col gap-5 shadow-[4px_4px_20px_4px] shadow-blue-50 bg-white rounded-lg`}>
<img src={`/s1-1.webp`} alt={`s1-1`} aria-hidden className="w-44 h-44 object-cover"/>
<h3 className={`text-xl font-medium`}>IP池</h3>
<div className={`flex flex-col gap-3`}>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span>IP时效3-30()</span>
</p>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span></span>
</p>
</div>
</li>
<li className={`p-8 flex flex-col gap-5 shadow-[4px_4px_20px_4px] shadow-blue-50 bg-white rounded-lg`}>
<img src={`/s1-2.webp`} alt={`s1-1`} aria-hidden className="w-44 h-44 object-cover"/>
<h3 className={`text-xl font-medium`}>IP池</h3>
<div className={`flex flex-col gap-3`}>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span>IP覆盖全国各地</span>
</p>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span>0.03s</span>
</p>
</div>
</li>
<li className={`p-8 flex flex-col gap-5 shadow-[4px_4px_20px_4px] shadow-blue-50 bg-white rounded-lg`}>
<img src={`/s1-3.webp`} alt={`s1-1`} aria-hidden className="w-44 h-44 object-cover"/>
<h3 className={`text-xl font-medium`}>IP池</h3>
<div className={`flex flex-col gap-3`}>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span>线</span>
</p>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span>IP线路</span>
</p>
</div>
</li>
<li className={`p-8 flex flex-col gap-5 shadow-[4px_4px_20px_4px] shadow-blue-50 bg-white rounded-lg`}>
<img src={`/s1-4.webp`} alt={`s1-1`} aria-hidden className="w-44 h-44 object-cover"/>
<h3 className={`text-xl font-medium`}></h3>
<div className={`flex flex-col gap-3`}>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span></span>
</p>
<p className={`text-sm text-gray-400 flex gap-3 items-center`}>
<img src={`/s1-check.svg`} alt={`check`} aria-hidden className={`w-5 h-5`}/>
<span></span>
</p>
</div>
</li>
</ul>
</Wrap>
</section>
{/* 优势 2 */}
<section className={`mt-28 flex flex-col gap-24`}>
<Wrap>
<h2 className={`text-3xl text-center font-medium`}>HTTP </h2>
<div className={`mt-24 flex gap-36`}>
<ul className={`flex-auto flex flex-col gap-6`}>
<li className={`flex gap-14 items-center pl-20 h-48 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg`}>
<img src={`/s2-1-1.webp`} alt={`s2-1-1`} aria-hidden className="w-24 h-24 object-contain"/>
<div className={`flex flex-col gap-3`}>
<h3 className={`text-xl font-medium`}></h3>
<p></p>
</div>
</li>
<li className={`flex gap-14 items-center pl-20 h-48 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg`}>
<img src={`/s2-1-2.webp`} alt={`s2-1-1`} aria-hidden className="w-24 h-24 object-contain"/>
<div className={`flex flex-col gap-3`}>
<h3 className={`text-xl font-medium`}></h3>
<p>IP纯净度高达99.9%</p>
</div>
</li>
<li className={`flex gap-14 items-center pl-20 h-48 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg`}>
<img src={`/s2-1-3.webp`} alt={`s2-1-1`} aria-hidden className="w-24 h-24 object-contain"/>
<div className={`flex flex-col gap-3`}>
<h3 className={`text-xl font-medium`}></h3>
<p></p>
</div>
</li>
</ul>
<img src={`/s2-2-main.webp`} alt={`s2-1-main`} className={`w-[600px] h-[600px] object-contain flex-none`}/>
</div>
<div className={`flex gap-36 mt-24`}>
<img src={`/s2-2-main.webp`} alt={`s2-1-main`} className={`w-[600px] h-[600px] object-contain`}/>
<ul className={`flex-auto flex flex-col gap-6`}>
<li className={`flex gap-14 items-center pl-20 h-48 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg`}>
<img src={`/s2-2-1.webp`} alt={`s2-1-1`} aria-hidden className="w-24 h-24 object-cover"/>
<div className={`flex flex-col gap-3`}>
<h3 className={`text-xl font-medium`}>API接口文档</h3>
<p></p>
</div>
</li>
<li className={`flex gap-14 items-center pl-20 h-48 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg`}>
<img src={`/s2-2-2.webp`} alt={`s2-1-1`} aria-hidden className="w-24 h-24 object-cover"/>
<div className={`flex flex-col gap-3`}>
<h3 className={`text-xl font-medium`}></h3>
<p>C语言GO语言Python...</p>
</div>
</li>
<li className={`flex gap-14 items-center pl-20 h-48 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg`}>
<img src={`/s2-2-3.webp`} alt={`s2-1-1`} aria-hidden className="w-24 h-24 object-cover"/>
<div className={`flex flex-col gap-3`}>
<h3 className={`text-xl font-medium`}></h3>
<p>API提取+</p>
</div>
</li>
</ul>
</div>
</Wrap>
</section>
{/* 行业资讯 */}
<section className={`mt-44 mb-32 flex flex-col`}>
<Wrap>
<h2 className={`text-center text-3xl font-medium`}></h2>
<div className={`mt-24 flex gap-20`}>
<button className={`px-4`}>
<img src={`/next.svg`} alt={`prev`} className={`rotate-180`}/>
</button>
<div className={`flex p-14 gap-14 shadow-[4px_4px_20px_4px] shadow-blue-50 rounded-lg]`}>
<img src="/s3-main.webp" alt="tumb" className={`flex-none w-[350px] h-[270px] object-cover`}/>
<div className={`flex flex-col justify-between`}>
<h3 className={`flex justify-between`}>
<span className={`text-xl font-medium`}></span>
<sub className={`text-sm text-gray-400`}>2025-03-04</sub>
</h3>
<p className={`text-gray-400 leading-12`}>
...
</p>
<div className={`flex justify-end`}>
<a href="#" className={`text-sm text-gray-400 flex items-center gap-5`}>
<img src={`/next.svg`} alt={`more`} className={`h-4 fill-gray-400`}/>
</a>
</div>
</div>
</div>
<button className={`px-4`}>
<img src={`/next.svg`} alt={`prev`} />
</button>
</div>
</Wrap>
</section>
</main>
{/* 页脚 */}
<Footer/>
</div>
)
}

Binary file not shown.

View File

@@ -1,26 +1,5 @@
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #171717;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
color: hsl(0, 0%, 20%);
}

View File

@@ -1,34 +1,25 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import {ReactNode} from 'react'
import {Metadata} from 'next'
import './globals.css'
import localFont from 'next/font/local'
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
const font = localFont({src: './SourceHanSansSC-VF.otf.woff2'})
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
children: ReactNode;
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<html lang="zh-Cn">
<body className={font.className}>
{children}
</body>
</html>
);
)
}

View File

@@ -1,101 +0,0 @@
import Image from "next/image";
export default function Home() {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
<li className="mb-2">
Get started by editing{" "}
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">
src/app/page.tsx
</code>
.
</li>
<li>Save and see your changes instantly.</li>
</ol>
<div className="flex gap-4 items-center flex-col sm:flex-row">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
</div>
</main>
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org
</a>
</footer>
</div>
);
}

14
src/components/wrap.tsx Normal file
View File

@@ -0,0 +1,14 @@
import {ReactNode} from 'react'
export type WrapProps = {
children: ReactNode
className?: string
}
export default function Wrap(props: WrapProps) {
return (
<div className={`w-[1200px] h-full mx-auto ${props.className}`}>
{props.children}
</div>
)
}