reaper 1 週間 前
コミット
bc0c21f887

+ 284 - 0
PROJECT_OVERVIEW.md

@@ -0,0 +1,284 @@
+# DDAC 安全防护官网项目文档
+
+## 项目概述
+
+DDAC 是一个网络安全防护服务官网,提供高防服务器、高防DNS、游戏盾SDK、高防CDN等安全产品。项目基于 Nuxt 3 框架开发,采用 PC 和 H5 双端设计,通过设备检测自动适配不同终端。
+
+## 技术栈
+
+- **框架**: Nuxt 4.2.2
+- **Vue版本**: Vue 3.5.26
+- **路由**: Vue Router 4.6.4
+- **UI组件库**: Element Plus 2.13.1
+- **样式预处理**: Sass 1.97.2
+- **TypeScript**: 5.x
+- **包管理器**: pnpm
+
+## 项目结构
+
+```
+DDAC/
+├── .github/                 # GitHub Actions 配置
+├── .nuxt/                  # Nuxt 自动生成的配置文件
+├── .output/                # 构建输出目录
+├── app/                    # 应用源代码目录
+│   ├── app.vue            # 应用入口组件
+│   ├── assets/            # 静态资源
+│   │   ├── images/        # 图片资源
+│   │   │   └── home/      # 首页图片(20+ 张图标、背景图)
+│   │   ├── scss/          # 全局样式文件
+│   │   │   └── main.scss  # CSS 重置和全局样式
+│   │   ├── svg/           # SVG 图标
+│   │   └── video/         # 视频资源
+│   │       └── home.webm  # 首页背景视频
+│   ├── components/        # Vue 组件
+│   │   ├── Header.vue     # 头部导航组件
+│   │   ├── Footer.vue     # 底部组件
+│   │   ├── ParticlesCanvas.vue      # 首页粒子动画组件
+│   │   └── SecurityParticles.vue   # 安全架构粒子动画组件
+│   └── pages/             # 页面路由(自动生成路由)
+│       ├── index.vue      # 首页(设备检测重定向)
+│       ├── pc/            # PC 端页面
+│       │   ├── index.vue  # PC 首页
+│       │   └── about.vue  # PC 关于页(占位)
+│       └── h5/            # 移动端页面
+│           ├── index.vue  # H5 首页(占位)
+│           └── about.vue  # H5 关于页(占位)
+├── node_modules/          # 依赖包
+├── plugins/               # Nuxt 插件目录(当前为空)
+├── public/                # 静态公共资源
+│   ├── favicon.ico        # 网站图标
+│   └── logo.png           # Logo 图片
+├── .gitignore             # Git 忽略配置
+├── nuxt.config.ts         # Nuxt 配置文件
+├── package.json           # 项目依赖配置
+├── pnpm-lock.yaml         # pnpm 锁文件
+├── README.md              # 项目说明
+└── tsconfig.json          # TypeScript 配置
+```
+
+## 核心功能
+
+### 1. 设备检测与重定向
+- **文件位置**: `app/pages/index.vue`
+- **功能**: 自动检测用户设备类型(PC/移动端)
+- **实现方式**: 通过 `navigator.userAgent` 检测移动端特征
+- **重定向规则**:
+  - 移动设备 → `/h5`
+  - PC设备 → `/pc`
+
+### 2. PC 首页 (`/pc/index.vue`)
+
+#### 页面模块
+1. **头部导航**
+   - 品牌Logo和标题
+   - 导航菜单:首页、产品、行业解决方案、文档中心、了解我们
+   - 登录/注册按钮
+
+2. **Hero区域**
+   - 背景视频(`home.webm`)
+   - 粒子动画覆盖层(`ParticlesCanvas.vue`)
+   - 渐变色标题:您专注业务,我们守护安全
+   - 副标题:展示产品服务范围
+
+3. **产品标签栏**
+   - 6个产品分类标签
+   - 首个标签高亮显示
+
+4. **产品卡片展示**
+   - Web安全加速
+   - DNS安全加速
+   - 扫描观测(漏洞扫描)
+   - 每个卡片包含:标题、描述、特性标签、操作按钮
+
+5. **安全洞见数据展示**
+   - 背景图 + 动画效果
+   - 实时攻防态势数据:
+     - 今日CC攻击次数: 19,009
+     - 今日DDoS攻击峰值: 22,844
+     - 今日WAF拦截次数: 56,870
+
+6. **定价方案**
+   - Lite Plan ($999) - 项目上线初期
+   - Basic Plan ($1999) - 个人开发者
+   - Standard Plan ($4999) - 企业入门
+   - 每个方案包含:防护目标数、峰值设备数、线路、带宽、防御能力
+
+7. **安全架构展示**
+   - 全景技术架构背景图
+   - 粒子动画(`SecurityParticles.vue`)
+   - 技术描述文字
+
+8. **行业解决方案**
+   - 彩虹背景效果
+   - 5大行业:金融、互联网、医疗健康、制造、教育
+   - 15个客户案例展示
+   - 雷达扫描动画
+
+#### 动画效果
+- **粒子动画**: 从四周向中心汇聚的粒子效果
+- **浮动动画**: 游戏盾图标上下浮动
+- **雷达扫描**: 旋转扫描效果 + 闪烁点
+- **渐变过渡**: 多处使用CSS渐变背景
+
+### 3. 组件说明
+
+#### Header.vue
+- 使用 Element Plus 的 `el-row` 和 `el-col` 布局
+- 响应式三列布局(6-12-6)
+- 包含品牌标识、导航菜单、用户操作区
+
+#### Footer.vue
+- 5列导航链接:安全产品、安全服务、热搜榜单、文档中心、关于我们
+- 行业解决方案入口
+- 联系方式
+- 版权信息
+
+#### ParticlesCanvas.vue
+- Canvas 粒子动画
+- 30个粒子从随机位置向中心移动
+- 到达中心后重新生成
+- 支持 window resize 事件
+
+#### SecurityParticles.vue
+- 上升流动的粒子效果
+- 60-600个粒子(根据屏幕面积自适应)
+- 带有横向摆动效果
+- 支持高DPI屏幕
+
+## 样式设计
+
+### 颜色方案
+- **背景色**: `#030014`(深紫黑色)
+- **主色调**: 紫色系(`#7C4DFF`、`#DEB9FF`、`#617FFF`)
+- **文字色**: 白色 `#ffffff`、浅灰 `#bdbdbd`
+- **强调色**: `#a39dff`、`#9b71ff`
+
+### 字体
+- **标题**: Source Han Sans CN(思源黑体)
+- **英文/数字**: Roboto、Inter
+- **字重**: 400(常规)、500(中粗)、700(粗体)
+
+### 设计特点
+- 渐变色背景和按钮
+- 磨砂玻璃效果(`backdrop-filter: blur`)
+- 悬浮阴影和边框发光效果
+- CSS动画(浮动、闪烁、扫描)
+
+## 开发指南
+
+### 环境要求
+- Node.js >= 18.x
+- pnpm >= 8.x
+
+### 安装依赖
+```bash
+pnpm install
+```
+
+### 启动开发服务器
+```bash
+pnpm dev
+```
+访问 `http://localhost:3000`
+
+### 构建生产版本
+```bash
+pnpm build
+```
+
+### 预览生产构建
+```bash
+pnpm preview
+```
+
+### 生成静态站点
+```bash
+pnpm generate
+```
+
+## 路由配置
+
+Nuxt 3 采用文件系统路由,路由结构如下:
+
+```
+/
+├── index.vue          → /
+├── pc/
+│   ├── index.vue      → /pc
+│   └── about.vue      → /pc/about
+└── h5/
+    ├── index.vue      → /h5
+    └── about.vue      → /h5/about
+```
+
+## Nuxt 配置
+
+### `nuxt.config.ts`
+```typescript
+export default defineNuxtConfig({
+  modules: ['@element-plus/nuxt'],  // Element Plus 集成
+  compatibilityDate: '2025-07-15',
+  css: ['~/assets/scss/main.scss'], // 全局样式
+})
+```
+
+### TypeScript 配置
+- 支持模块系统:ESM
+- 严格模式:已启用
+- 类型检查:完整支持
+
+## 部署说明
+
+### 构建输出
+- `.output/` 目录包含构建后的应用
+- 支持静态导出(`nuxt generate`)
+- 支持服务器端渲染部署
+
+### 部署建议
+1. 使用 Nginx 反向代理
+2. 配置 HTTPS
+3. 启用 Gzip/Brotli 压缩
+4. 配置 CDN 加速静态资源
+
+## 待完成功能
+
+- [ ] 完善移动端 H5 页面设计
+- [ ] 完成 PC 端关于页面
+- [ ] 实现产品详情页
+- [ ] 实现文档中心
+- [ ] 添加用户登录/注册功能
+- [ ] 添加后台管理系统
+- [ ] 添加数据统计功能
+- [ ] SEO 优化
+- [ ] 性能优化(代码分割、懒加载)
+- [ ] 添加单元测试和端到端测试
+
+## 注意事项
+
+1. **设备检测**: 当前通过 `window.location.href` 重定向,生产环境建议使用 Nuxt 中间件
+2. **视频加载**: Hero 背景视频使用 WebM 格式,注意浏览器兼容性
+3. **Canvas 性能**: 粒子动画在移动端可能会有性能问题,建议添加性能优化
+4. **图片优化**: 静态资源较大,建议使用图片压缩和 CDN 加速
+5. **SEO**: 当前页面 SEO 元数据较简单,建议完善
+
+## 浏览器兼容性
+
+- Chrome >= 90
+- Firefox >= 88
+- Safari >= 14
+- Edge >= 90
+
+## 许可证
+
+Copyright © 2025 SUYUN, All Rights Reserved
+
+## 联系方式
+
+- 企业邮箱:support@yundun.com
+- 官网:DDAC(待补充域名)
+
+---
+
+**文档生成时间**: 2025-01-19
+**项目版本**: 1.0.0

+ 0 - 3
app/app.vue

@@ -4,7 +4,4 @@
   </div>
 </template>
 <script setup>
-definePageMeta({
-  middleware: 'device-redirect'
-})
 </script>

+ 26 - 26
app/components/Footer.vue

@@ -12,16 +12,16 @@
           <h3 class="nav-title">安全产品</h3>
           <ul class="nav-list">
             <li>
-              <NuxtLink to="/products/sdk-security" class="nav-link">SDK安全加速(游戏DDoS、CC、WAF防护)</NuxtLink>
+              <span class="nav-link">SDK安全加速(游戏DDoS、CC、WAF防护)</span>
             </li>
             <li>
-              <NuxtLink to="/products/web-security" class="nav-link">Web安全加速(网站DDoS、CC、WAF防护)</NuxtLink>
+              <span class="nav-link">Web安全加速(网站DDoS、CC、WAF防护)</span>
             </li>
             <li>
-              <NuxtLink to="/products/tcp-security" class="nav-link">TCP安全加速(DDoS防护)</NuxtLink>
+              <span class="nav-link">TCP安全加速(DDoS防护)</span>
             </li>
             <li>
-              <NuxtLink to="/products/dns-security" class="nav-link">DNS安全加速(域名解析)</NuxtLink>
+              <span class="nav-link">DNS安全加速(域名解析)</span>
             </li>
           </ul>
         </section>
@@ -30,19 +30,19 @@
           <h3 class="nav-title">安全服务</h3>
           <ul class="nav-list">
             <li>
-              <NuxtLink to="/services/exposure-detection" class="nav-link">互联网暴露面检测服务</NuxtLink>
+              <span class="nav-link">互联网暴露面检测服务</span>
             </li>
             <li>
-              <NuxtLink to="/services/penetration-test" class="nav-link">渗透测试服务</NuxtLink>
+              <span class="nav-link">渗透测试服务</span>
             </li>
             <li>
-              <NuxtLink to="/services/security-inspection" class="nav-link">安全巡检和加固服务</NuxtLink>
+              <span class="nav-link">安全巡检和加固服务</span>
             </li>
             <li>
-              <NuxtLink to="/services/security-support" class="nav-link">重保服务</NuxtLink>
+              <span class="nav-link">重保服务</span>
             </li>
             <li>
-              <NuxtLink to="/services/expert-services" class="nav-link">其他安全专家服务</NuxtLink>
+              <span class="nav-link">其他安全专家服务</span>
             </li>
           </ul>
         </section>
@@ -51,16 +51,16 @@
           <h3 class="nav-title">热搜榜单</h3>
           <ul class="nav-list">
             <li>
-              <NuxtLink to="/trending/zero-trust" class="nav-link">零信任安全访问</NuxtLink>
+              <span class="nav-link">零信任安全访问</span>
             </li>
             <li>
-              <NuxtLink to="/trending/overseas-cloud" class="nav-link">出海云主机</NuxtLink>
+              <span class="nav-link">出海云主机</span>
             </li>
             <li>
-              <NuxtLink to="/trending/web-security" class="nav-link">Web网站安全加速</NuxtLink>
+              <span class="nav-link">Web网站安全加速</span>
             </li>
             <li>
-              <NuxtLink to="/trending/app-security" class="nav-link">APP安全加速</NuxtLink>
+              <span class="nav-link">APP安全加速</span>
             </li>
           </ul>
         </section>
@@ -69,19 +69,19 @@
           <h3 class="nav-title">文档中心</h3>
           <ul class="nav-list">
             <li>
-              <NuxtLink to="/docs/getting-started" class="nav-link">入门指导</NuxtLink>
+              <span class="nav-link">入门指导</span>
             </li>
             <li>
-              <NuxtLink to="/docs/faq" class="nav-link">问答专区</NuxtLink>
+              <span class="nav-link">问答专区</span>
             </li>
             <li>
-              <NuxtLink to="/docs/topics" class="nav-link">主题</NuxtLink>
+              <span class="nav-link">主题</span>
             </li>
             <li>
-              <NuxtLink to="/docs/news" class="nav-link">资讯列表</NuxtLink>
+              <span class="nav-link">资讯列表</span>
             </li>
             <li>
-              <NuxtLink to="/docs/keywords" class="nav-link">关键词</NuxtLink>
+              <span class="nav-link">关键词</span>
             </li>
           </ul>
         </section>
@@ -90,16 +90,16 @@
           <h3 class="nav-title">关于我们</h3>
           <ul class="nav-list">
             <li>
-              <NuxtLink to="/about/company" class="nav-link">企业简介</NuxtLink>
+              <span class="nav-link">企业简介</span>
             </li>
             <li>
-              <NuxtLink to="/about/certifications" class="nav-link">资质认证</NuxtLink>
+              <span class="nav-link">资质认证</span>
             </li>
             <li>
-              <NuxtLink to="/about/legal" class="nav-link">法律条款</NuxtLink>
+              <span class="nav-link">法律条款</span>
             </li>
             <li>
-              <NuxtLink to="/about/history" class="nav-link">大事记</NuxtLink>
+              <span class="nav-link">大事记</span>
             </li>
           </ul>
         </section>
@@ -107,7 +107,7 @@
 
       <!-- 行业解决方案 -->
       <div class="footer-section">
-        <NuxtLink to="/solutions" class="section-link">行业解决方案</NuxtLink>
+        <span class="section-link">行业解决方案</span>
       </div>
 
       <!-- 联系信息 -->
@@ -118,7 +118,7 @@
 
       <!-- 底部信息 -->
       <div class="footer-bottom">
-        <NuxtLink to="/report" class="report-link">举报中心</NuxtLink>
+        <span class="report-link">举报中心</span>
         <p class="copyright">Copyright@2025&nbsp;SUYUN,All&nbsp;Rights&nbsp;Reserved</p>
       </div>
     </div>
@@ -305,7 +305,7 @@
       }
     }
 
-  
+
   }
 }
-</style>
+</style>

+ 48 - 29
app/components/Header.vue

@@ -1,42 +1,60 @@
 <template>
-  <header class="header" role="banner">
-    <el-row :gutter="10">
-      <el-col :span="6">
-        <div class="header-left">
-          <a href="/" class="brand" aria-label="Home">
-            <img src="/logo.png" alt="DDAC logo" class="brand-logo" width="34" height="34" />
-            <h1 class="brand-title">DDAC</h1>
-          </a>
-        </div>
-      </el-col>
-      <el-col :span="12">
-        <nav class="header-nav" role="navigation" aria-label="Main navigation">
-          <div class="nav-item">首页</div>
-          <div class="nav-item">产品</div>
-          <div class="nav-item">行业解决方案</div>
-          <div class="nav-item">文档中心</div>
-          <div class="nav-item">了解我们</div>
-        </nav>
-      </el-col>   
-      <el-col :span="6">
-        <div class="header-right">
-          <div>登录</div>
-          <div class="register">注册</div>
-        </div>
-      </el-col>
-    </el-row>
+  <header class="header" :class="{ 'header-hidden': isHidden }" role="banner">
+    <div class="header-left">
+      <a href="/" class="brand" aria-label="Home">
+        <img src="/logo.png" alt="DDAC logo" class="brand-logo" width="34" height="34" />
+        <h1 class="brand-title">DDAC</h1>
+      </a>
+    </div>
+    <nav class="header-nav" role="navigation" aria-label="Main navigation">
+      <div class="nav-item">首页</div>
+      <div class="nav-item">产品</div>
+      <div class="nav-item">行业解决方案</div>
+      <div class="nav-item">文档中心</div>
+      <div class="nav-item">了解我们</div>
+    </nav>
+    <div class="header-right">
+      <div>登录</div>
+      <div class="register">注册</div>
+    </div>
   </header>
 </template>
 <script setup>
-  
+const { y: scrollY } = useWindowScroll()
+const lastScrollY = ref(0)
+const isHidden = ref(false)
+
+watchEffect(() => {
+  if (scrollY.value > lastScrollY.value && scrollY.value > 60) {
+    isHidden.value = true
+  } else {
+    isHidden.value = false
+  }
+  lastScrollY.value = scrollY.value
+})
 </script>
 <style lang="scss">
 .header {
   box-sizing: border-box;
   padding: 22px 0;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  z-index: 1000;
+  background: #030014;
+  transition: transform 0.3s ease;
+
+  &.header-hidden {
+    transform: translateY(-100%);
+  }
 }
 
 .header-left {
+  flex: 1;
   display: flex;
   align-items: center;
   justify-content: right;
@@ -62,10 +80,10 @@
 }
 
 .header-nav {
+  flex: 2;
   display: flex;
   justify-content: center;
   align-items: center;
-  height: 100%;
 
   .nav-item {
     margin: 0 15px;
@@ -84,9 +102,10 @@
 }
 
 .header-right {
+  flex: 1;
   display: flex;
   align-items: center;
-  height: 100%;
+  justify-content: left;
   color: #FFF;
 
   div {

+ 119 - 0
app/components/home/StatsSection.vue

@@ -0,0 +1,119 @@
+<template>
+  <section class="stats-section" :style="{ backgroundImage: `url(${homeBg})` }">
+    <img class="stats-figure" :src="homeD" alt="游戏盾" />
+    <div class="stat-item">
+      <div class="stat-label">今日&nbsp;CC&nbsp;攻击次数</div>
+      <div class="stat-value">{{ formatNumber(stats.ccAttacks) }}</div>
+    </div>
+    <div class="stat-item state-other">
+      <div class="stat-label">今日&nbsp;DDoS&nbsp;攻击峰值</div>
+      <div class="stat-value">{{ formatNumber(stats.ddosPeak) }}</div>
+    </div>
+    <div class="stat-item">
+      <div class="stat-label">今日&nbsp;WAF&nbsp;拦截次数</div>
+      <div class="stat-value">{{ formatNumber(stats.wafBlocks) }}</div>
+    </div>
+  </section>
+</template>
+
+<script setup>
+import { onMounted, onUnmounted } from 'vue'
+import { storeToRefs } from 'pinia'
+import homeBg from '~/assets/images/home/home-bg.png'
+import homeD from '~/assets/images/home/home-d.png'
+
+const statsStore = useStatsStore()
+const { stats } = storeToRefs(statsStore)
+
+let intervalId = null
+
+onMounted(() => {
+  intervalId = statsStore.startAutoIncrement()
+})
+
+onUnmounted(() => {
+  if (intervalId) {
+    statsStore.stopAutoIncrement(intervalId)
+  }
+})
+
+const formatNumber = (num) => {
+  return num.toLocaleString()
+}
+</script>
+
+<style scoped lang="scss">
+.stats-section {
+  width: 100%;
+  max-width: 1920px;
+  height: 749px;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background-size: cover;
+  background-position: center top;
+  overflow: hidden;
+
+  .stats-figure {
+    position: absolute;
+    top: 280px;
+    left: 50%;
+    transform: translateX(-50%) translateY(0);
+    width: 226.059px;
+    height: 305.118px;
+    object-fit: contain;
+    pointer-events: none;
+    z-index: 0;
+    will-change: transform;
+    animation: float 3s ease-in-out infinite;
+  }
+
+  @keyframes float {
+    0% {
+      transform: translateX(-50%) translateY(0);
+    }
+
+    50% {
+      transform: translateX(-50%) translateY(-20px);
+    }
+
+    100% {
+      transform: translateX(-50%) translateY(0);
+    }
+  }
+
+  .state-other {
+    position: absolute;
+    top: 100px;
+  }
+
+  .stat-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: space-between;
+    margin: 0 300px;
+    z-index: 1;
+
+    .stat-label {
+      font-family: 'Source Han Sans CN', sans-serif;
+      font-size: 24px;
+      font-weight: 400;
+      line-height: 24px;
+      color: #ffffff;
+      text-align: center;
+      margin-bottom: 20px;
+    }
+
+    .stat-value {
+      font-family: 'Roboto', sans-serif;
+      font-size: 56px;
+      font-weight: 700;
+      line-height: 56px;
+      color: #a182ff;
+      text-align: center;
+    }
+  }
+}
+</style>

+ 2 - 92
app/pages/pc/index.vue

@@ -87,21 +87,7 @@
       </section>
 
       <!-- 数据展示区域 -->
-      <section class="stats-section" :style="{ backgroundImage: `url(${homeBg})` }">
-        <img class="stats-figure" :src="homeD" alt="游戏盾" />
-        <div class="stat-item">
-          <div class="stat-label">今日&nbsp;CC&nbsp;攻击次数</div>
-          <div class="stat-value">19,009</div>
-        </div>
-        <div class="stat-item state-other">
-          <div class="stat-label">今日&nbsp;DDoS&nbsp;攻击峰值</div>
-          <div class="stat-value">22,844</div>
-        </div>
-        <div class="stat-item">
-          <div class="stat-label">今日&nbsp;WAF&nbsp;拦截次数</div>
-          <div class="stat-value">56,870</div>
-        </div>
-      </section>
+      <StatsSection />
 
       <!-- 安全运营与方案模块 -->
       <section class="plans-section">
@@ -310,11 +296,10 @@
 
 <script setup>
 import { ref } from 'vue'
+import StatsSection from '~/components/home/StatsSection.vue'
 import videoSrc from '~/assets/video/home.webm'
 import ParticlesCanvas from '~/components/ParticlesCanvas.vue'
 import SecurityParticles from '~/components/SecurityParticles.vue'
-import homeBg from '~/assets/images/home/home-bg.png'
-import homeD from '~/assets/images/home/home-d.png'
 import homeBg2 from '~/assets/images/home/home-bg2.png'
 import homeBg3 from '~/assets/images/home/home-bg3.png'
 import homeBg4 from '~/assets/images/home/home-bg4.png'
@@ -660,82 +645,7 @@ useHead(() => ({
   }
 }
 
-// 数据展示区域
-.stats-section {
-  width: 100%;
-  max-width: 1920px;
-  height: 749px;
-  // margin: 80px auto 0;
-  position: relative;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  background-size: cover;
-  background-position: center top;
-  overflow: hidden;
-
-  .stats-figure {
-    position: absolute;
-    top: 280px;
-    left: 50%;
-    transform: translateX(-50%) translateY(0);
-    width: 226.059px;
-    height: 305.118px;
-    object-fit: contain;
-    pointer-events: none;
-    z-index: 0;
-    /* 上下浮动动画 */
-    will-change: transform;
-    animation: float 3s ease-in-out infinite;
-  }
 
-  @keyframes float {
-    0% {
-      transform: translateX(-50%) translateY(0);
-    }
-
-    50% {
-      transform: translateX(-50%) translateY(-20px);
-    }
-
-    100% {
-      transform: translateX(-50%) translateY(0);
-    }
-  }
-
-  .state-other {
-    position: absolute;
-    top: 100px;
-  }
-
-  .stat-item {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: space-between;
-    margin: 0 300px;
-    z-index: 1;
-
-    .stat-label {
-      font-family: 'Source Han Sans CN', sans-serif;
-      font-size: 24px;
-      font-weight: 400;
-      line-height: 24px;
-      color: #ffffff;
-      text-align: center;
-      margin-bottom: 20px;
-    }
-
-    .stat-value {
-      font-family: 'Roboto', sans-serif;
-      font-size: 56px;
-      font-weight: 700;
-      line-height: 56px;
-      color: #a182ff;
-      text-align: center;
-    }
-  }
-}
 
 // 方案卡片区域
 .plans-section {

+ 30 - 0
app/stores/stats.js

@@ -0,0 +1,30 @@
+import { defineStore } from 'pinia'
+import { useLocalStorage } from '@vueuse/core'
+
+export const useStatsStore = defineStore('stats', () => {
+  const stats = useLocalStorage('ddac-stats', {
+    ccAttacks: 19009,
+    ddosPeak: 22844,
+    wafBlocks: 56870
+  })
+
+  const incrementStats = () => {
+    stats.value.ccAttacks += Math.floor(Math.random() * 151) + 50
+    stats.value.ddosPeak += Math.floor(Math.random() * 151) + 50
+    stats.value.wafBlocks += Math.floor(Math.random() * 151) + 50
+  }
+
+  const startAutoIncrement = () => {
+    return setInterval(incrementStats, 2000)
+  }
+
+  const stopAutoIncrement = (intervalId) => {
+    clearInterval(intervalId)
+  }
+
+  return {
+    stats,
+    startAutoIncrement,
+    stopAutoIncrement
+  }
+})

+ 16 - 0
ecosystem.config.js

@@ -0,0 +1,16 @@
+module.exports = {
+  apps: [
+    {
+      name: 'DDAC-Nuxt4', // 请替换为您的应用名称
+      script: '.output/server/index.mjs', // Nuxt 4 构建后的正确入口文件
+      instances: 'max', // 自动根据 CPU 核心数启动实例
+      exec_mode: 'cluster', // 集群模式,实现负载均衡
+      watch: false, // 生产环境关闭文件监听
+      env: {
+        NITRO_PORT: 3333, // 设置 Nitro 服务器端口
+        NITRO_HOST: '0.0.0.0', // 允许外部访问
+        NODE_ENV: 'production'
+      }
+    }
+  ]
+}

+ 1 - 1
nuxt.config.ts

@@ -1,6 +1,6 @@
 // https://nuxt.com/docs/api/configuration/nuxt-config
 export default defineNuxtConfig({
-  modules: ['@element-plus/nuxt'],
+  modules: ['@element-plus/nuxt', '@vueuse/nuxt','@pinia/nuxt'],
   compatibilityDate: '2025-07-15',
   // devtools: { enabled: true },
   css: ['~/assets/scss/main.scss'], // 全局样式文件

+ 2 - 0
package.json

@@ -10,6 +10,8 @@
     "postinstall": "nuxt prepare"
   },
   "dependencies": {
+    "@pinia/nuxt": "^0.5.5",
+    "@vueuse/nuxt": "^14.1.0",
     "nuxt": "^4.2.2",
     "vue": "^3.5.26",
     "vue-router": "^4.6.4"

+ 84 - 0
pnpm-lock.yaml

@@ -8,6 +8,12 @@ importers:
 
   .:
     dependencies:
+      '@pinia/nuxt':
+        specifier: ^0.5.5
+        version: 0.5.5(magicast@0.5.1)(vue@3.5.26)
+      '@vueuse/nuxt':
+        specifier: ^14.1.0
+        version: 14.1.0(magicast@0.5.1)(nuxt@4.2.2(@parcel/watcher@2.5.4)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.26)(cac@6.7.14)(db0@0.3.4)(ioredis@5.9.1)(magicast@0.5.1)(rollup@4.55.1)(sass@1.97.2)(terser@5.44.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.97.2)(terser@5.44.1)(yaml@2.8.2))(yaml@2.8.2))(vue@3.5.26)
       nuxt:
         specifier: ^4.2.2
         version: 4.2.2(@parcel/watcher@2.5.4)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.26)(cac@6.7.14)(db0@0.3.4)(ioredis@5.9.1)(magicast@0.5.1)(rollup@4.55.1)(sass@1.97.2)(terser@5.44.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.97.2)(terser@5.44.1)(yaml@2.8.2))(yaml@2.8.2)
@@ -880,6 +886,9 @@ packages:
     resolution: {integrity: sha512-WYa2tUVV5HiArWPB3ydlOc4R2ivq0IDrlqhMi3l7mVsFEXNcTfxYFPIHXHXIh/ca/y/V5N4E1zecyxdIBjYnkQ==}
     engines: {node: '>= 10.0.0'}
 
+  '@pinia/nuxt@0.5.5':
+    resolution: {integrity: sha512-wjxS7YqIesh4OLK+qE3ZjhdOJ5pYZQ+VlEmZNtTwzQn1Kavei/khovx7mzXVXNA/mvSPXVhb9xBzhyS3XMURtw==}
+
   '@pkgjs/parseargs@0.11.0':
     resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
     engines: {node: '>=14'}
@@ -1151,6 +1160,9 @@ packages:
   '@types/web-bluetooth@0.0.20':
     resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
 
+  '@types/web-bluetooth@0.0.21':
+    resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
+
   '@unhead/vue@2.1.2':
     resolution: {integrity: sha512-w5yxH/fkkLWAFAOnMSIbvAikNHYn6pgC7zGF/BasXf+K3CO1cYIPFehYAk5jpcsbiNPMc3goyyw1prGLoyD14g==}
     peerDependencies:
@@ -1255,12 +1267,31 @@ packages:
   '@vueuse/core@10.11.1':
     resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==}
 
+  '@vueuse/core@14.1.0':
+    resolution: {integrity: sha512-rgBinKs07hAYyPF834mDTigH7BtPqvZ3Pryuzt1SD/lg5wEcWqvwzXXYGEDb2/cP0Sj5zSvHl3WkmMELr5kfWw==}
+    peerDependencies:
+      vue: ^3.5.0
+
   '@vueuse/metadata@10.11.1':
     resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==}
 
+  '@vueuse/metadata@14.1.0':
+    resolution: {integrity: sha512-7hK4g015rWn2PhKcZ99NyT+ZD9sbwm7SGvp7k+k+rKGWnLjS/oQozoIZzWfCewSUeBmnJkIb+CNr7Zc/EyRnnA==}
+
+  '@vueuse/nuxt@14.1.0':
+    resolution: {integrity: sha512-zw8WSgRrdtsA1daqlFl5ojoTJnvWad/IbMIcHw4EN8Wci09koeFfh5/oKbkKeIQ3gzihvr9x0bu8BVz8Z2auSg==}
+    peerDependencies:
+      nuxt: ^3.0.0 || ^4.0.0-0
+      vue: ^3.5.0
+
   '@vueuse/shared@10.11.1':
     resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==}
 
+  '@vueuse/shared@14.1.0':
+    resolution: {integrity: sha512-EcKxtYvn6gx1F8z9J5/rsg3+lTQnvOruQd8fUecW99DCK04BkWD7z5KQ/wTAx+DazyoEE9dJt/zV8OIEQbM6kw==}
+    peerDependencies:
+      vue: ^3.5.0
+
   abbrev@3.0.1:
     resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==}
     engines: {node: ^18.17.0 || >=20.5.0}
@@ -2412,6 +2443,15 @@ packages:
     resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
     engines: {node: '>=12'}
 
+  pinia@2.3.1:
+    resolution: {integrity: sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==}
+    peerDependencies:
+      typescript: '>=4.4.4'
+      vue: ^2.7.0 || ^3.5.11
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
   pkg-types@1.3.1:
     resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
 
@@ -4210,6 +4250,16 @@ snapshots:
       '@parcel/watcher-win32-ia32': 2.5.4
       '@parcel/watcher-win32-x64': 2.5.4
 
+  '@pinia/nuxt@0.5.5(magicast@0.5.1)(vue@3.5.26)':
+    dependencies:
+      '@nuxt/kit': 3.20.2(magicast@0.5.1)
+      pinia: 2.3.1(vue@3.5.26)
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+      - magicast
+      - typescript
+      - vue
+
   '@pkgjs/parseargs@0.11.0':
     optional: true
 
@@ -4402,6 +4452,8 @@ snapshots:
 
   '@types/web-bluetooth@0.0.20': {}
 
+  '@types/web-bluetooth@0.0.21': {}
+
   '@unhead/vue@2.1.2(vue@3.5.26)':
     dependencies:
       hookable: 6.0.1
@@ -4592,8 +4644,28 @@ snapshots:
       - '@vue/composition-api'
       - vue
 
+  '@vueuse/core@14.1.0(vue@3.5.26)':
+    dependencies:
+      '@types/web-bluetooth': 0.0.21
+      '@vueuse/metadata': 14.1.0
+      '@vueuse/shared': 14.1.0(vue@3.5.26)
+      vue: 3.5.26
+
   '@vueuse/metadata@10.11.1': {}
 
+  '@vueuse/metadata@14.1.0': {}
+
+  '@vueuse/nuxt@14.1.0(magicast@0.5.1)(nuxt@4.2.2(@parcel/watcher@2.5.4)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.26)(cac@6.7.14)(db0@0.3.4)(ioredis@5.9.1)(magicast@0.5.1)(rollup@4.55.1)(sass@1.97.2)(terser@5.44.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.97.2)(terser@5.44.1)(yaml@2.8.2))(yaml@2.8.2))(vue@3.5.26)':
+    dependencies:
+      '@nuxt/kit': 4.2.2(magicast@0.5.1)
+      '@vueuse/core': 14.1.0(vue@3.5.26)
+      '@vueuse/metadata': 14.1.0
+      local-pkg: 1.1.2
+      nuxt: 4.2.2(@parcel/watcher@2.5.4)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.26)(cac@6.7.14)(db0@0.3.4)(ioredis@5.9.1)(magicast@0.5.1)(rollup@4.55.1)(sass@1.97.2)(terser@5.44.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.97.2)(terser@5.44.1)(yaml@2.8.2))(yaml@2.8.2)
+      vue: 3.5.26
+    transitivePeerDependencies:
+      - magicast
+
   '@vueuse/shared@10.11.1(vue@3.5.26)':
     dependencies:
       vue-demi: 0.14.10(vue@3.5.26)
@@ -4601,6 +4673,10 @@ snapshots:
       - '@vue/composition-api'
       - vue
 
+  '@vueuse/shared@14.1.0(vue@3.5.26)':
+    dependencies:
+      vue: 3.5.26
+
   abbrev@3.0.1: {}
 
   abort-controller@3.0.0:
@@ -5941,6 +6017,14 @@ snapshots:
 
   picomatch@4.0.3: {}
 
+  pinia@2.3.1(vue@3.5.26):
+    dependencies:
+      '@vue/devtools-api': 6.6.4
+      vue: 3.5.26
+      vue-demi: 0.14.10(vue@3.5.26)
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+
   pkg-types@1.3.1:
     dependencies:
       confbox: 0.1.8