Ryuiso преди 7 месеца
родител
ревизия
096c677569

+ 0 - 0
.ideavimrc


+ 22 - 5
web/.editorconfig

@@ -1,9 +1,26 @@
-[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
+# EditorConfig is awesome: https://EditorConfig.org
+root = true
+
+[*]
+# 基础编码设置
 charset = utf-8
-indent_size = 2
+end_of_line = lf
 indent_style = space
-insert_final_newline = true
+indent_size = 4
+# 格式规范
 trim_trailing_whitespace = true
+insert_final_newline = true
+max_line_length = 120
 
-end_of_line = lf
-max_line_length = 100
+# 缩进规则
+[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,html,css,scss,sass,less,styl,yml,yaml,,.eslintrc}]
+indent_size = 2
+
+[*.{json,package.json}]
+indent_size = 2
+
+[*.md]
+trim_trailing_whitespace = false
+
+[Makefile]
+indent_style = tab

+ 1 - 1
web/.prettierrc.json

@@ -2,5 +2,5 @@
   "$schema": "https://json.schemastore.org/prettierrc",
   "semi": false,
   "singleQuote": true,
-  "printWidth": 100
+  "printWidth": 120
 }

+ 4 - 4
web/src/App.vue

@@ -2,7 +2,7 @@
 import { RouterView, useRoute } from 'vue-router'
 import { computed } from 'vue'
 import Footer from '@/layout/Footer/index.vue'
-import NewHeader from '@/layout/NewHeader/index.vue'
+import Header from '@/layout/Header/index.vue'
 
 // 根据路由判断是否显示Footer
 const route = useRoute()
@@ -11,8 +11,8 @@ const showFooter = computed(() => route.name !== 'doc') // 在文档页面不显
 
 <template>
   <div class="app-container">
-    <NewHeader />
-
+    <Header />
+    <!--<OldHeader />-->
     <!-- 主要内容区域 -->
     <main class="main-content">
       <RouterView />
@@ -30,6 +30,6 @@ const showFooter = computed(() => route.name !== 'doc') // 在文档页面不显
 
 .main-content {
   flex: 1;
-  margin-top: var(--header-height, 64px); /* 使用margin-top而不是padding-top */
+  /* 移除margin-top以消除空白 */
 }
 </style>

+ 98 - 0
web/src/assets/styles/docs.scss

@@ -0,0 +1,98 @@
+
+:root {
+  --header-height: 60px;
+  --sidebar-width: 280px;
+
+  // 浅色主题
+  --c-bg: #ffffff;
+  --c-bg-light: #f8f8f8;
+  --c-text: #213547;
+  --c-text-light: #666;
+  --c-brand: #42b983;
+  --c-divider: #e2e2e3;
+}
+
+.dark {
+  // 深色主题
+  --c-bg: #1a1a1a;
+  --c-bg-light: #242424;
+  --c-text: #e4e4e7;
+  --c-text-light: #a1a1aa;
+  --c-brand: #42d392;
+  --c-divider: #2f2f2f;
+}
+
+.doc-container {
+  display: flex;
+  min-height: calc(100vh - var(--header-height));
+  position: relative;
+}
+
+.sidebar {
+  width: var(--sidebar-width);
+  border-right: 1px solid var(--c-divider);
+  background-color: var(--c-bg);
+  position: fixed;
+  top: var(--header-height);
+  bottom: 0;
+  left: 0;
+  z-index: 10;
+  transition: transform 0.2s ease;
+  overflow-y: auto;
+  padding: 24px 0;
+}
+
+.content {
+  flex: 1;
+  padding: 32px 48px;
+  margin-left: var(--sidebar-width);
+}
+
+// 导航菜单样式
+.menu-group-title {
+  padding: 8px 24px;
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--c-text-light);
+  text-transform: uppercase;
+  letter-spacing: 0.5px;
+}
+
+.menu-item {
+  margin: 4px 0;
+}
+
+.menu-link {
+  display: block;
+  padding: 8px 24px;
+  color: var(--c-text);
+  font-size: 14px;
+  transition: color 0.2s, background-color 0.2s;
+
+  &:hover {
+    color: var(--c-brand);
+    background-color: var(--c-bg-light);
+  }
+
+  &.active {
+    color: var(--c-brand);
+    border-right: 2px solid var(--c-brand);
+    background-color: var(--c-bg-light);
+  }
+}
+
+// 响应式处理
+@media (max-width: 768px) {
+  .sidebar {
+    transform: translateX(-100%);
+
+    &.sidebar-open {
+      transform: translateX(0);
+    }
+  }
+
+  .content {
+    margin-left: 0;
+    padding: 24px;
+  }
+}

+ 83 - 0
web/src/assets/styles/global.scss

@@ -0,0 +1,83 @@
+
+:root {
+  // 定义颜色变量
+  --c-brand: #0070D5;
+  --c-brand-light: #4098fc;
+  --c-text: #213547;
+  --c-text-light: #476582;
+  --c-text-lighter: #8a8f98;
+  --c-text-lightest: #a8adb7;
+  --c-divider: #e2e2e3;
+  --c-bg: #ffffff;
+  --c-bg-light: #f3f4f5;
+  --c-bg-lighter: #eeeeee;
+  --c-bg-navbar: var(--c-bg);
+  --c-bg-sidebar: var(--c-bg);
+  --c-bg-float: var(--c-bg);
+}
+
+// 基础样式重置
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+body {
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
+    Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+  color: var(--c-text);
+  background-color: var(--c-bg);
+  line-height: 1.5;
+}
+
+a {
+  text-decoration: none;
+  color: var(--c-brand);
+  transition: color 0.2s;
+}
+
+a:hover {
+  color: var(--c-brand-light);
+}
+
+// 布局样式
+.container {
+  width: 100%;
+  max-width: 1200px;
+  margin: 0 auto;
+  padding: 0 16px;
+}
+
+// 工具类
+.text-center {
+  text-align: center;
+}
+
+// 布局样式
+.app-container {
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.main-content {
+  flex: 1;
+}
+
+// Section样式
+.section {
+  padding: var(--spacing-xl) 0;
+
+  &-header {
+    text-align: center;
+    margin-bottom: var(--spacing-xl);
+  }
+}
+
+// 响应式调整
+@media (max-width: 768px) {
+  .section {
+    padding: var(--spacing-lg) 0;
+  }
+}

+ 5 - 122
web/src/assets/styles/layout.scss

@@ -1,88 +1,10 @@
 @use './variables' as v;
 @use './mixins' as m;
 
-// Reset styles
-*,
-*::before,
-*::after {
-  box-sizing: border-box;
-  margin: 0;
-  padding: 0;
-}
-
-body {
-  font-family: v.$font-family-base;
-  font-size: v.$font-size-md;
-  line-height: 1.6;
-  color: v.$text-primary;
-  background-color: v.$background-primary;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}
-
-// Typography
-h1, h2, h3, h4, h5, h6 {
-  font-weight: v.$font-weight-bold;
-  line-height: 1.2;
-  margin-bottom: v.$spacing-md;
-}
-
-p {
-  margin-bottom: v.$spacing-md;
-}
-
-a {
-  color: v.$primary-color;
-  text-decoration: none;
-  transition: color v.$transition-fast;
-
-  &:hover {
-    color: v.$secondary-color;
-  }
-}
-
-// Layout styles
-.app-container {
-  min-height: 100vh;
-  @include m.flex-column;
-  font-family: v.$font-family-base;
-}
-
-.main-content {
-  margin-top: v.$header-height;
-  flex: 1;
-  min-height: calc(100vh - #{v.$header-height} - #{v.$footer-height});
-}
-
-.container {
-  @include m.container;
-}
-
-// Section styles
-.section {
-  padding: v.$spacing-xl 0;
-
-  &-header {
-    text-align: center;
-    margin-bottom: v.$spacing-xl;
-  }
+// 仅保留组件级布局样式
+// 基础样式已迁移到global.scss
 
-  &-title {
-    font-size: v.$font-size-xl;
-    font-weight: v.$font-weight-bold;
-    color: v.$text-primary;
-    margin-bottom: v.$spacing-md;
-  }
-
-  &-description {
-    font-size: v.$font-size-md;
-    color: v.$text-secondary;
-    max-width: v.$content-max-width;
-    margin: 0 auto;
-  }
-}
-
-// Grid system
+// Grid系统 (组件专用)
 .row {
   display: flex;
   flex-wrap: wrap;
@@ -94,26 +16,7 @@ a {
   flex: 1;
 }
 
-// Utility classes
-.text {
-  &-center { text-align: center; }
-  &-right { text-align: right; }
-  &-left { text-align: left; }
-}
-
-// Margin utilities
-@each $size, $value in (
-  '1': v.$spacing-xs,
-  '2': v.$spacing-sm,
-  '3': v.$spacing-md,
-  '4': v.$spacing-lg,
-  '5': v.$spacing-xl
-) {
-  .mt-#{$size} { margin-top: $value; }
-  .mb-#{$size} { margin-bottom: $value; }
-}
-
-// Animations
+// 动画效果
 .fade {
   &-enter-active,
   &-leave-active {
@@ -126,16 +29,8 @@ a {
   }
 }
 
-// Responsive adjustments
+// 响应式调整 (组件专用)
 @include v.responsive(medium) {
-  .container {
-    padding: 0 v.$spacing-sm;
-  }
-
-  .section {
-    padding: v.$spacing-lg 0;
-  }
-
   .row {
     flex-direction: column;
   }
@@ -144,15 +39,3 @@ a {
     margin-bottom: v.$spacing-md;
   }
 }
-
-@include v.responsive(large) {
-  .container {
-    max-width: 100%;
-  }
-}
-
-@include v.responsive(small) {
-  .section {
-    padding: v.$spacing-md 0;
-  }
-}

+ 87 - 0
web/src/components/BaseCard/index.vue

@@ -0,0 +1,87 @@
+
+<script setup lang="ts">
+defineProps({
+  title: {
+    type: String,
+    required: true
+  },
+  image: {
+    type: String,
+    default: ''
+  },
+  description: {
+    type: String,
+    default: ''
+  },
+  height: {
+    type: String,
+    default: '260px'
+  },
+  contentPosition: {
+    type: String,
+    default: 'flex-end'
+  }
+})
+</script>
+
+<template>
+  <div
+    class="base-card"
+    :style="{
+      backgroundImage: image ? `url('${image}')` : 'none',
+      height,
+      alignItems: contentPosition
+    }"
+  >
+    <div class="card-content">
+      <h3>{{ title }}</h3>
+      <p v-if="description">{{ description }}</p>
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.base-card {
+  background: #141414;
+  display: flex;
+  padding: 24px;
+  cursor: pointer;
+  transition: opacity 0.3s;
+  background-size: cover;
+  background-position: center;
+  position: relative;
+  overflow: hidden;
+
+  &::before {
+    content: '';
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 50%;
+    background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
+  }
+
+  &:hover {
+    opacity: 0.9;
+  }
+
+  .card-content {
+    position: relative;
+    z-index: 1;
+
+    h3 {
+      color: white;
+      font-size: 20px;
+      margin-bottom: 8px;
+    }
+
+    p {
+      color: rgba(255, 255, 255, 0.8);
+      font-size: 14px;
+      line-height: 1.4;
+    }
+  }
+}
+</style>

+ 174 - 0
web/src/components/DocLayout/index.vue

@@ -0,0 +1,174 @@
+
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+
+defineProps<{
+  menus: Array<{
+    title: string
+    path?: string
+    children?: Array<{
+      title: string
+      path: string
+    }>
+  }>
+}>()
+
+const currentPath = ref('')
+const sidebarOpen = ref(true)
+
+// 响应式处理
+const isMobile = ref(false)
+const checkIsMobile = () => {
+  isMobile.value = window.innerWidth < 768
+  if (isMobile.value) sidebarOpen.value = false
+}
+
+// 初始化检查
+if (typeof window !== 'undefined') {
+  checkIsMobile()
+  window.addEventListener('resize', checkIsMobile)
+}
+</script>
+
+<template>
+  <div class="doc-container">
+    <!-- 移动端菜单按钮 -->
+    <button
+      class="mobile-menu-button"
+      @click="sidebarOpen = !sidebarOpen"
+      v-if="isMobile"
+    >
+      <svg viewBox="0 0 24 24" width="24" height="24">
+        <path fill="currentColor" d="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z" />
+      </svg>
+    </button>
+
+    <!-- 侧边栏导航 -->
+    <aside
+      class="sidebar"
+      :class="{ 'sidebar-open': sidebarOpen }"
+    >
+      <nav>
+        <div v-for="group in menus" :key="group.title">
+          <h3 class="menu-group-title">{{ group.title }}</h3>
+          <ul v-if="group.children">
+            <li
+              v-for="item in group.children"
+              :key="item.path"
+              class="menu-item"
+            >
+              <RouterLink
+                :to="item.path"
+                class="menu-link"
+                :class="{ active: currentPath === item.path }"
+                @click="currentPath = item.path"
+              >
+                {{ item.title }}
+              </RouterLink>
+            </li>
+          </ul>
+        </div>
+      </nav>
+    </aside>
+
+    <!-- 主内容区 -->
+    <main class="content">
+      <div class="content-container">
+        <slot />
+      </div>
+    </main>
+  </div>
+</template>
+
+<style scoped>
+.doc-container {
+  display: flex;
+  min-height: calc(100vh - var(--header-height));
+  position: relative;
+}
+
+.sidebar {
+  width: 280px;
+  border-right: 1px solid var(--c-divider);
+  background-color: var(--c-bg);
+  position: fixed;
+  top: var(--header-height);
+  bottom: 0;
+  left: 0;
+  z-index: 10;
+  transition: transform 0.2s ease;
+  overflow-y: auto;
+  padding: 24px 0;
+}
+
+.content {
+  flex: 1;
+  padding: 32px 48px;
+  margin-left: 280px;
+}
+
+.menu-group-title {
+  padding: 8px 24px;
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--c-text-2);
+  text-transform: uppercase;
+  letter-spacing: 0.5px;
+}
+
+.menu-item {
+  margin: 4px 0;
+}
+
+.menu-link {
+  display: block;
+  padding: 8px 24px;
+  color: var(--c-text-1);
+  font-size: 14px;
+  transition: color 0.2s, background-color 0.2s;
+}
+
+.menu-link:hover {
+  color: var(--c-brand);
+  background-color: var(--c-bg-light);
+}
+
+.menu-link.active {
+  color: var(--c-brand);
+  border-right: 2px solid var(--c-brand);
+  background-color: var(--c-bg-light);
+}
+
+/* 移动端样式 */
+@media (max-width: 768px) {
+  .sidebar {
+    transform: translateX(-100%);
+  }
+
+  .sidebar.sidebar-open {
+    transform: translateX(0);
+  }
+
+  .content {
+    margin-left: 0;
+    padding: 24px;
+  }
+
+  .mobile-menu-button {
+    position: fixed;
+    bottom: 20px;
+    right: 20px;
+    z-index: 20;
+    background: var(--c-brand);
+    color: white;
+    border: none;
+    border-radius: 50%;
+    width: 50px;
+    height: 50px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+  }
+}
+</style>

+ 109 - 0
web/src/components/DocNavigation/index.vue

@@ -0,0 +1,109 @@
+
+<script setup lang="ts">
+defineProps<{
+  menus: Array<{
+    title: string
+    path?: string
+    children?: Array<{
+      title: string
+      path: string
+      children?: Array<{
+        title: string
+        path: string
+      }>
+    }>
+  }>
+}>()
+
+const activePath = ref('')
+</script>
+
+<template>
+  <nav class="doc-navigation">
+    <ul class="first-level">
+      <li v-for="item in menus" :key="item.title">
+        <RouterLink
+          v-if="item.path"
+          :to="item.path"
+          class="nav-link"
+          :class="{ active: activePath === item.path }"
+        >
+          {{ item.title }}
+        </RouterLink>
+        <div v-else class="nav-title">{{ item.title }}</div>
+
+        <ul v-if="item.children" class="second-level">
+          <li v-for="child in item.children" :key="child.title">
+            <RouterLink
+              v-if="child.path"
+              :to="child.path"
+              class="nav-link"
+              :class="{ active: activePath === child.path }"
+            >
+              {{ child.title }}
+            </RouterLink>
+            <div v-else class="nav-title">{{ child.title }}</div>
+
+            <ul v-if="child.children" class="third-level">
+              <li v-for="sub in child.children" :key="sub.title">
+                <RouterLink
+                  :to="sub.path"
+                  class="nav-link"
+                  :class="{ active: activePath === sub.path }"
+                >
+                  {{ sub.title }}
+                </RouterLink>
+              </li>
+            </ul>
+          </li>
+        </ul>
+      </li>
+    </ul>
+  </nav>
+</template>
+
+<style scoped>
+.doc-navigation {
+  padding: 16px 0;
+}
+
+.first-level > li,
+.second-level > li,
+.third-level > li {
+  margin: 4px 0;
+}
+
+.nav-title {
+  font-weight: 600;
+  color: var(--c-text-1);
+  padding: 8px 16px;
+  margin-top: 12px;
+}
+
+.nav-link {
+  display: block;
+  padding: 8px 16px;
+  color: var(--c-text-2);
+  border-radius: 4px;
+  transition: all 0.2s;
+}
+
+.nav-link:hover {
+  color: var(--c-brand);
+  background: var(--c-bg-light);
+}
+
+.nav-link.active {
+  color: var(--c-brand);
+  background: var(--c-bg-light);
+  font-weight: 500;
+}
+
+.second-level {
+  padding-left: 8px;
+}
+
+.third-level {
+  padding-left: 16px;
+}
+</style>

+ 9 - 39
web/src/components/SceneCard/index.vue

@@ -1,4 +1,6 @@
 <script setup lang="ts">
+import BaseCard from '@/components/BaseCard/index.vue'
+
 defineProps({
   title: {
     type: String,
@@ -16,54 +18,22 @@ defineProps({
 </script>
 
 <template>
-  <div class="scene-card" :style="image ? { backgroundImage: `url('${image}')` } : {}">
-    <div class="scene-content">
-      <h3>{{ title }}</h3>
-      <p v-if="description">{{ description }}</p>
-    </div>
-  </div>
+  <BaseCard
+    :title="title"
+    :image="image"
+    :description="description"
+    class="scene-card"
+  />
 </template>
 
 <style lang="scss" scoped>
 .scene-card {
-  background: #141414;
-  height: 260px;
-  display: flex;
-  align-items: flex-end;
-  padding: 24px;
-  cursor: pointer;
-  transition: opacity 0.3s;
-  background-size: cover;
-  background-position: center;
-  position: relative;
-  overflow: hidden;
-
-  &::before {
-    content: '';
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    height: 50%;
-    background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
-  }
-
-  &:hover {
-    opacity: 0.9;
-  }
-
-  .scene-content {
-    position: relative;
-    z-index: 1;
-
+  :deep(.card-content) {
     h3 {
-      color: white;
       font-size: 20px;
       margin-bottom: 8px;
     }
-
     p {
-      color: rgba(255, 255, 255, 0.8);
       font-size: 14px;
       line-height: 1.4;
     }

+ 0 - 106
web/src/layout/BackUp/index.vue

@@ -1,106 +0,0 @@
-<script setup lang="ts">
-import { RouterLink, useRoute } from 'vue-router'
-import { navigation } from '@/router'
-import { computed } from 'vue'
-
-// 计算当前是否在文档页面
-const route = useRoute()
-const isDocView = computed(() => route.name === 'doc')
-</script>
-
-<template>
-  <header class="navbar" :class="{ 'navbar-doc': isDocView }">
-    <div class="nav-content">
-      <div class="nav-left">
-        <img alt="Pendulum logo" class="logo" src="@/assets/icons/logo.svg" width="40" height="40" />
-      </div>
-
-      <nav class="nav-links">
-        <RouterLink
-          v-for="item in navigation"
-          :key="item.name"
-          :to="item.path"
-          class="nav-link"
-        >
-          {{ item.title }}
-        </RouterLink>
-      </nav>
-    </div>
-  </header>
-</template>
-
-<style scoped lang="scss">
-@use '@/assets/styles/variables' as v;
-@use '@/assets/styles/mixins' as m;
-
-.navbar {
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  height: v.$header-height;
-  background-color: v.$background-primary;
-  box-shadow: v.$shadow-sm;
-  z-index: v.$z-index-fixed;
-}
-
-.nav-content {
-  @include m.container;
-  height: 100%;
-  @include m.flex-between;
-}
-
-.nav-left {
-  @include m.flex-center;
-}
-
-.logo {
-  margin-right: v.$spacing-md;
-}
-
-.nav-links {
-  display: flex;
-  gap: v.$spacing-lg;
-}
-
-.nav-link {
-  color: v.$text-primary;
-  text-decoration: none;
-  font-size: v.$font-size-md;
-  padding: v.$spacing-xs v.$spacing-md;
-  border-radius: v.$border-radius-md;
-  transition: background-color v.$transition-fast;
-
-  &:hover {
-    background-color: rgba(0, 0, 0, 0.05);
-  }
-
-  &.router-link-active {
-    color: v.$primary-color;
-    font-weight: v.$font-weight-medium;
-  }
-}
-
-.navbar-doc {
-  .nav-content {
-    max-width: none;
-    padding: 0 v.$spacing-xl;
-  }
-}
-
-@include v.responsive(medium) {
-  .nav-content {
-    padding: 0 v.$spacing-sm;
-  }
-
-  .nav-link {
-    padding: v.$spacing-xs v.$spacing-sm;
-  }
-
-  .navbar-doc {
-    .nav-content {
-      padding: 0 v.$spacing-lg;
-    }
-  }
-}
-</style>

+ 42 - 42
web/src/layout/Footer/index.vue

@@ -6,50 +6,50 @@
   <footer class="footer">
     <div class="footer-wrapper">
       <div class="footer-content">
-      <div class="footer-section">
-        <h3>开发</h3>
-        <ul>
-          <li><a href="#">Mobile SDK</a></li>
-          <li><a href="#">UX SDK</a></li>
-          <li><a href="#">Onboard SDK</a></li>
-          <li><a href="#">Payload SDK</a></li>
-          <li><a href="#">Windows SDK</a></li>
-          <li><a href="#">上云API</a></li>
-        </ul>
-      </div>
-      <div class="footer-section">
-        <h3>开发者社区</h3>
-        <ul>
-          <li><a href="#">Github</a></li>
-          <!--<li><a href="#">技术论坛</a></li>-->
-        </ul>
-      </div>
-      <div class="footer-section">
-        <h3>联系我们</h3>
-        <ul>
-          <li><a href="#">问题反馈</a></li>
-        </ul>
-      </div>
-      <div class="footer-section">
-        <h3>商务合作</h3>
-        <ul>
-          <li><a href="mailto:dev@pendulum.com">dev@pendulum.com</a></li>
-        </ul>
-      </div>
-      <div class="footer-section">
-        <h3>账单</h3>
-        <ul>
-          <li><a href="mailto:billing-dev@pendulum.com">billing-dev@pendulum.com</a></li>
-        </ul>
-      </div>
+        <div class="footer-section">
+          <h3>开发</h3>
+          <ul>
+            <li><a href="#">Mobile SDK</a></li>
+            <li><a href="#">UX SDK</a></li>
+            <li><a href="#">Onboard SDK</a></li>
+            <li><a href="#">Payload SDK</a></li>
+            <li><a href="#">Windows SDK</a></li>
+            <li><a href="#">上云API</a></li>
+          </ul>
+        </div>
+        <div class="footer-section">
+          <h3>开发者社区</h3>
+          <ul>
+            <li><a href="#">Github</a></li>
+            <!--<li><a href="#">技术论坛</a></li>-->
+          </ul>
+        </div>
+        <div class="footer-section">
+          <h3>联系我们</h3>
+          <ul>
+            <li><a href="#">问题反馈</a></li>
+          </ul>
+        </div>
+        <div class="footer-section">
+          <h3>商务合作</h3>
+          <ul>
+            <li><a href="mailto:dev@pendulum.com">dev@pendulum.com</a></li>
+          </ul>
+        </div>
+        <div class="footer-section">
+          <h3>账单</h3>
+          <ul>
+            <li><a href="mailto:billing-dev@pendulum.com">billing-dev@pendulum.com</a></li>
+          </ul>
+        </div>
       </div>
       <div class="footer-bottom">
-      <p>Copyright © 2025 pendulum 版权所有</p>
-      <nav>
-        <a href="#">隐私政策</a>
-        <a href="#">使用条款</a>
-        <a href="#">SDK 信息收集清单</a>
-      </nav>
+        <p>Copyright © 2025 pendulum 版权所有</p>
+        <nav>
+          <a href="#">隐私政策</a>
+          <a href="#">使用条款</a>
+          <a href="#">SDK 信息收集清单</a>
+        </nav>
       </div>
     </div>
   </footer>

+ 249 - 0
web/src/layout/Header/index.vue

@@ -0,0 +1,249 @@
+
+<script setup lang="ts">
+import { RouterLink, useRoute } from 'vue-router'
+import { navigation } from '@/router'
+import { computed } from 'vue'
+
+// 计算当前是否在文档页面
+const route = useRoute()
+const isDocView = computed(() => route.name === 'doc')
+
+defineOptions({ name: 'Header' })
+
+defineProps({
+  title: {
+    type: String,
+    default: '',
+  },
+  subtitle: {
+    type: String,
+    default: '',
+  },
+  dark: {
+    type: Boolean,
+    default: false,
+  },
+  bgImage: {
+    type: String,
+    default: '',
+  },
+  bgColor: {
+    type: String,
+    default: '',
+  },
+  heroSection: {
+    type: Boolean,
+    default: false,
+  },
+  centered: {
+    type: Boolean,
+    default: false,
+  },
+})
+</script>
+
+<template>
+  <header class="new-header" :class="{ 'new-header-doc': isDocView }">
+    <div class="header-container">
+      <!-- Logo 区域 -->
+      <div class="logo-section">
+        <RouterLink to="/">
+          <img src="@/assets/icons/logo.svg" alt="Pendulum Logo" class="logo" />
+          <span class="logo-text">Pendulum 开放平台</span>
+        </RouterLink>
+      </div>
+
+      <!-- 简化后的导航菜单 -->
+      <nav class="nav-menu">
+        <ul class="menu-list">
+          <li
+            v-for="item in navigation"
+            :key="item.name"
+            class="menu-item"
+          >
+            <RouterLink :to="item.path" class="menu-link">{{ item.title }}</RouterLink>
+          </li>
+        </ul>
+      </nav>
+
+      <!-- 右侧操作区 -->
+      <div class="action-section">
+        <a href="#" class="action-link">联系我们</a>
+        <a href="#" class="action-button">预览平台</a>
+      </div>
+    </div>
+  </header>
+</template>
+
+<style scoped lang="scss">
+@use '@/assets/styles/variables' as v;
+@use '@/assets/styles/mixins' as m;
+@use "sass:color";
+
+.new-header {
+  position: relative;
+  width: 100%;
+  background-color: v.$background-light;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  z-index: 100;
+}
+
+.header-container {
+  @include m.container;
+  @include m.flex-between;
+  padding: 0 v.$spacing-lg;
+  height: 64px;
+}
+
+// Logo 区域样式
+.logo-section {
+  display: flex;
+  align-items: center;
+  gap: v.$spacing-sm;
+
+  a {
+    display: flex;
+    align-items: center;
+    text-decoration: none;
+    gap: v.$spacing-sm;
+  }
+
+  .logo {
+    height: 42px;
+    width: auto;
+  }
+
+  .logo-text {
+    font-size: v.$font-size-md;
+    font-weight: v.$font-weight-medium;
+    color: v.$text-primary;
+  }
+}
+
+// 导航菜单样式
+.nav-menu {
+  flex: 1;
+  margin: 0 v.$spacing-xl;
+  height: 100%;
+
+  .menu-list {
+    display: flex;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    height: 100%;
+  }
+
+  .menu-item {
+    display: flex;
+    align-items: center;
+    padding: 0 v.$spacing-lg;
+  }
+
+  .menu-link {
+    color: v.$text-primary;
+    text-decoration: none;
+    font-size: v.$font-size-sm;
+    transition: color v.$transition-fast;
+
+    &:hover {
+      color: v.$primary-color;
+    }
+  }
+}
+
+// 右侧操作区样式
+.action-section {
+  display: flex;
+  align-items: center;
+  gap: v.$spacing-md;
+
+  .action-link {
+    color: v.$text-primary;
+    text-decoration: none;
+    font-size: v.$font-size-sm;
+    transition: color v.$transition-fast;
+
+    &:hover {
+      color: v.$primary-color;
+    }
+  }
+
+  .action-button {
+    padding: v.$spacing-sm v.$spacing-lg;
+    background-color: v.$primary-color;
+    color: v.$text-color-light;
+    border-radius: v.$border-radius-md;
+    text-decoration: none;
+    font-size: v.$font-size-sm;
+    transition: background-color v.$transition-fast;
+
+    &:hover {
+      background-color: color.adjust(v.$primary-color, $lightness: -10%);
+    }
+  }
+}
+
+.new-header-doc {
+  .header-container {
+    max-width: none;
+    padding: 0 v.$spacing-xl;
+  }
+}
+
+// 移动端适配
+@include v.responsive(medium) {
+  .header-container {
+    padding: 0 v.$spacing-sm;
+  }
+
+  .nav-menu {
+    margin: 0 v.$spacing-md;
+
+    .menu-item {
+      padding: 0 v.$spacing-sm;
+    }
+  }
+
+  .new-header-doc {
+    .header-container {
+      padding: 0 v.$spacing-lg;
+    }
+  }
+}
+
+@include v.responsive(small) {
+  .header-container {
+    padding: 0 v.$spacing-sm;
+  }
+
+  .logo-text {
+    display: none;
+  }
+
+  .nav-menu {
+    margin: 0 v.$spacing-sm;
+
+    .menu-item {
+      padding: 0 v.$spacing-xs;
+    }
+
+    .menu-link {
+      font-size: v.$font-size-xs;
+    }
+  }
+
+  .action-section {
+    gap: v.$spacing-sm;
+
+    .action-link {
+      display: none;
+    }
+
+    .action-button {
+      padding: v.$spacing-xs v.$spacing-sm;
+      font-size: v.$font-size-xs;
+    }
+  }
+}
+</style>

+ 0 - 398
web/src/layout/NewHeader/index.vue

@@ -1,398 +0,0 @@
-<script setup lang="ts">
-import { RouterLink, useRoute } from 'vue-router'
-import { navigation } from '@/router'
-import { computed, ref } from 'vue'
-
-// 计算当前是否在文档页面
-const route = useRoute()
-const isDocView = computed(() => route.name === 'doc')
-
-// 计算当前激活的菜单索引
-defineOptions({ name: 'NewHeader' })
-
-// 组件属性
-defineProps({
-  title: {
-    type: String,
-    default: '',
-  },
-  subtitle: {
-    type: String,
-    default: '',
-  },
-  dark: {
-    type: Boolean,
-    default: false,
-  },
-  bgImage: {
-    type: String,
-    default: '',
-  },
-  bgColor: {
-    type: String,
-    default: '',
-  },
-  heroSection: {
-    type: Boolean,
-    default: false,
-  },
-  centered: {
-    type: Boolean,
-    default: false,
-  },
-})
-
-// 当前激活的菜单索引
-const activeIndex = ref(-1)
-
-// 处理菜单悬停
-const handleMenuHover = (index: number) => {
-  activeIndex.value = index
-}
-
-// 处理整个菜单区域离开
-const handleMenuLeave = () => {
-  // 添加一个小延迟,防止意外关闭
-  setTimeout(() => {
-    activeIndex.value = -1
-  }, 100)
-}
-
-// 处理子菜单悬停,防止子菜单消失
-const handleSubmenuHover = (index: number) => {
-  activeIndex.value = index
-}
-
-// 处理菜单项点击
-const handleMenuClick = (index: number) => {
-  if (activeIndex.value === index) {
-    activeIndex.value = -1
-  } else {
-    activeIndex.value = index
-  }
-}
-</script>
-
-<template>
-  <header
-    class="new-header"
-    :class="{ 'new-header-doc': isDocView }"
-    @mouseleave="handleMenuLeave"
-  >
-    <div class="header-container">
-      <!-- Logo 区域 -->
-      <div class="logo-section">
-        <RouterLink to="/">
-          <img src="@/assets/icons/logo.svg" alt="Pendulum Logo" class="logo" />
-          <span class="logo-text">Pendulum 开放平台</span>
-        </RouterLink>
-      </div>
-
-      <!-- 导航菜单 -->
-      <nav class="nav-menu">
-        <ul class="menu-list">
-          <li
-            v-for="(item, index) in navigation"
-            :key="item.name"
-            class="menu-item"
-            @mouseenter="handleMenuHover(index)"
-            @click="handleMenuClick(index)"
-            :class="{ active: activeIndex === index }"
-          >
-            <RouterLink :to="item.path" class="menu-link" @click.prevent>{{ item.title }}</RouterLink>
-            <!-- 添加二级和三级菜单 -->
-            <div
-              v-if="item.children && item.children.length > 0"
-              class="submenu"
-              @mouseenter="handleSubmenuHover(index)"
-            >
-              <div class="submenu-content">
-                <div v-for="subItem in item.children" :key="subItem.name" class="submenu-item">
-                  <RouterLink :to="`${item.path}/${subItem.path}`" class="submenu-link">{{ subItem.title }}</RouterLink>
-                  <!-- 添加三级菜单 -->
-                  <div v-if="subItem.children && subItem.children.length > 0" class="sub-submenu">
-                    <div v-for="subSubItem in subItem.children" :key="subSubItem.name" class="sub-submenu-item">
-                      <RouterLink :to="`${item.path}/${subItem.path}/${subSubItem.path}`" class="sub-submenu-link">{{ subSubItem.title }}</RouterLink>
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </li>
-        </ul>
-      </nav>
-
-      <!-- 右侧操作区 -->
-      <div class="action-section">
-        <a href="#" class="action-link">联系我们</a>
-        <a href="#" class="action-button">预览平台</a>
-      </div>
-    </div>
-  </header>
-</template>
-
-<style scoped lang="scss">
-@use '@/assets/styles/variables' as v;
-@use '@/assets/styles/mixins' as m;
-@use "sass:color";
-
-.new-header {
-  position: relative;
-  width: 100%;
-  background-color: v.$background-light;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-  z-index: 1001; // 确保header在submenu之上
-}
-
-.header-container {
-  @include m.container;
-  @include m.flex-between;
-  padding: 0 v.$spacing-lg;
-}
-
-// Logo 区域样式
-.logo-section {
-  display: flex;
-  align-items: center;
-  gap: v.$spacing-sm;
-  //height: 100%; // 确保logo区域填满header高度
-
-  a {
-    display: flex;
-    align-items: center;
-    text-decoration: none;
-    gap: v.$spacing-sm;
-    height: 100%; // 确保链接区域填满header高度
-  }
-
-  .logo {
-    height: 42px; // 保持logo高度不变
-    width: auto;
-    transition: transform 0.3s ease;
-    transform-origin: center;
-
-    &:hover {
-      transform: scale(1.1);
-      animation-play-state: paused;
-    }
-  }
-
-  .logo-text {
-    font-size: v.$font-size-md;
-    font-weight: v.$font-weight-medium;
-    color: v.$text-primary;
-  }
-}
-
-// 导航菜单样式
-.nav-menu {
-  flex: 1;
-  margin: 0 v.$spacing-xl;
-  height: 100%; // 确保导航菜单填满header高度
-
-  .menu-list {
-    display: flex;
-    list-style: none;
-    margin: 0;
-    padding: 0;
-    height: 100%;
-  }
-
-  .menu-item {
-    position: relative;
-    height: 64px; // 确保菜单项高度与header一致
-    padding: 0 v.$spacing-lg;
-
-    &:hover, &.active {
-      .menu-link {
-        color: v.$primary-color;
-      }
-    }
-  }
-
-  .menu-link {
-    display: flex;
-    align-items: center;
-    height: 100%;
-    color: v.$text-primary;
-    text-decoration: none;
-    font-size: v.$font-size-sm;
-    transition: color v.$transition-fast;
-  }
-
-  // 添加二级菜单样式
-  .submenu {
-    display: none;
-    position: fixed;
-    top: 64px; // 直接使用固定的header高度
-    left: 0;
-    width: 100%;
-    background-color: v.$background-light;
-    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
-    padding: v.$spacing-lg 0;
-    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
-    animation: slideDown 0.3s ease;
-    z-index: 1000;
-    pointer-events: auto; // 确保可以接收鼠标事件
-  }
-  @keyframes slideDown {
-    from {
-      opacity: 0;
-      transform: translateY(-10px);
-    }
-    to {
-      opacity: 1;
-      transform: translateY(0);
-    }
-  }
-
-  .menu-item.active .submenu {
-    display: block;
-  }
-
-  .submenu-item {
-    position: relative;
-  }
-
-  .submenu-content {
-    max-width: v.$container-width;
-    margin: 0 auto;
-    padding: 0 v.$spacing-lg;
-    display: grid;
-    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
-    gap: v.$spacing-xl;
-  }
-
-  .submenu-item {
-    display: flex;
-    flex-direction: column;
-  }
-
-  .submenu-link {
-    display: block;
-    padding: v.$spacing-sm 0;
-    color: v.$text-primary;
-    text-decoration: none;
-    font-size: v.$font-size-md;
-    font-weight: v.$font-weight-medium;
-    border-bottom: 2px solid v.$primary-color;
-    margin-bottom: v.$spacing-md;
-    transition: all v.$transition-fast;
-
-    &:hover {
-      color: v.$primary-color;
-    }
-  }
-
-  // 添加三级菜单样式
-  .sub-submenu {
-    display: flex;
-    flex-direction: column;
-    margin-top: v.$spacing-xs;
-  }
-
-  .sub-submenu-item {
-    margin-bottom: v.$spacing-xs;
-  }
-
-  .sub-submenu-link {
-    display: block;
-    padding: v.$spacing-xs v.$spacing-sm v.$spacing-xs v.$spacing-md;
-    color: v.$text-secondary;
-    text-decoration: none;
-    font-size: v.$font-size-sm;
-    transition: all v.$transition-fast;
-    position: relative;
-
-    &:before {
-      content: "•";
-      position: absolute;
-      left: 0;
-      color: v.$primary-color;
-      opacity: 0.7;
-    }
-
-    &:hover {
-      color: v.$primary-color;
-      transform: translateX(5px);
-    }
-  }
-
-  .sub-submenu-link {
-    display: block;
-    padding: v.$spacing-sm v.$spacing-lg v.$spacing-sm v.$spacing-lg;
-    color: v.$text-primary;
-    text-decoration: none;
-    font-size: v.$font-size-sm;
-    transition: background-color v.$transition-fast;
-
-    &:hover {
-      background-color: rgba(v.$primary-color, 0.1);
-      color: v.$primary-color;
-    }
-  }
-}
-
-// 右侧操作区样式
-.action-section {
-  display: flex;
-  align-items: center;
-  gap: v.$spacing-md;
-  height: 100%; // 确保操作区域填满header高度
-}
-
-.action-link {
-  color: v.$text-primary;
-  text-decoration: none;
-  font-size: v.$font-size-sm;
-  transition: color v.$transition-fast;
-
-  &:hover {
-    color: v.$primary-color;
-  }
-}
-
-.action-button {
-  display: inline-flex;
-  align-items: center;
-  justify-content: center;
-  padding: v.$spacing-sm v.$spacing-lg;
-  background-color: v.$primary-color;
-  color: v.$text-color-light;
-  border-radius: v.$border-radius-md;
-  text-decoration: none;
-  font-size: v.$font-size-sm;
-  transition: background-color v.$transition-fast;
-
-  &:hover {
-    background-color: color.adjust(v.$primary-color, $lightness: -10%);
-  }
-}
-
-.new-header-doc {
-  .header-container {
-    max-width: none;
-    padding: 0 v.$spacing-xl;
-  }
-}
-
-@include v.responsive(medium) {
-  .header-container {
-    padding: 0 v.$spacing-sm;
-  }
-
-  .nav-menu {
-    margin: 0 v.$spacing-md;
-  }
-
-  .menu-item {
-    padding: 0 v.$spacing-sm;
-  }
-
-  .new-header-doc {
-    .header-container {
-      padding: 0 v.$spacing-lg;
-    }
-  }
-}
-</style>

+ 2 - 1
web/src/main.ts

@@ -1,4 +1,5 @@
-import './assets/styles/layout.scss'
+import './assets/styles/global.scss'
+// layout.scss现在只包含组件级样式,按需导入
 
 import { createApp } from 'vue'
 import { createPinia } from 'pinia'

+ 128 - 32
web/src/router/index.ts

@@ -20,14 +20,44 @@ const enterpriseRoutes: NavItem[] = [
     children: [
       {
         path: '',
-        redirect: { name: 'mapping' }
-      },
-      { path: 'mapping', name: 'mapping', component: () => import('@/views/Enterprise/PublicSafety/Mapping.vue'), title: '测绘', showInNav: true },
-      { path: 'power', name: 'power', component: () => import('@/views/Enterprise/PublicSafety/Power.vue'), title: '电力', showInNav: true },
-      { path: 'oil-gas', name: 'oilGas', component: () => import('@/views/Enterprise/PublicSafety/OilGas.vue'), title: '石油与天然气', showInNav: true },
-      { path: 'water', name: 'water', component: () => import('@/views/Enterprise/PublicSafety/Water.vue'), title: '水利', showInNav: true },
-      { path: 'forestry', name: 'forestry', component: () => import('@/views/Enterprise/PublicSafety/Forestry.vue'), title: '林业', showInNav: true },
-    ]
+        redirect: { name: 'mapping' },
+      },
+      {
+        path: 'mapping',
+        name: 'mapping',
+        component: () => import('@/views/Enterprise/PublicSafety/Mapping.vue'),
+        title: '测绘',
+        showInNav: true,
+      },
+      {
+        path: 'power',
+        name: 'power',
+        component: () => import('@/views/Enterprise/PublicSafety/Power.vue'),
+        title: '电力',
+        showInNav: true,
+      },
+      {
+        path: 'oil-gas',
+        name: 'oilGas',
+        component: () => import('@/views/Enterprise/PublicSafety/OilGas.vue'),
+        title: '石油与天然气',
+        showInNav: true,
+      },
+      {
+        path: 'water',
+        name: 'water',
+        component: () => import('@/views/Enterprise/PublicSafety/Water.vue'),
+        title: '水利',
+        showInNav: true,
+      },
+      {
+        path: 'forestry',
+        name: 'forestry',
+        component: () => import('@/views/Enterprise/PublicSafety/Forestry.vue'),
+        title: '林业',
+        showInNav: true,
+      },
+    ],
   },
   {
     path: 'emergency',
@@ -38,13 +68,37 @@ const enterpriseRoutes: NavItem[] = [
     children: [
       {
         path: '',
-        redirect: { name: 'flood' }
+        redirect: { name: 'flood' },
+      },
+      {
+        path: 'flood',
+        name: 'flood',
+        component: () => import('@/views/Enterprise/Emergency/Flood.vue'),
+        title: '洪涝灾害救援',
+        showInNav: true,
+      },
+      {
+        path: 'forest-fire',
+        name: 'forestFire',
+        component: () => import('@/views/Enterprise/Emergency/ForestFire.vue'),
+        title: '森林火灾救援',
+        showInNav: true,
+      },
+      {
+        path: 'earthquake',
+        name: 'earthquake',
+        component: () => import('@/views/Enterprise/Emergency/Earthquake.vue'),
+        title: '地震与地质灾害救援',
+        showInNav: true,
+      },
+      {
+        path: 'mountain-rescue',
+        name: 'mountainRescue',
+        component: () => import('@/views/Enterprise/Emergency/MountainRescue.vue'),
+        title: '山岳搜救',
+        showInNav: true,
       },
-      { path: 'flood', name: 'flood', component: () => import('@/views/Enterprise/Emergency/Flood.vue'), title: '洪涝灾害救援', showInNav: true },
-      { path: 'forest-fire', name: 'forestFire', component: () => import('@/views/Enterprise/Emergency/ForestFire.vue'), title: '森林火灾救援', showInNav: true },
-      { path: 'earthquake', name: 'earthquake', component: () => import('@/views/Enterprise/Emergency/Earthquake.vue'), title: '地震与地质灾害救援', showInNav: true },
-      { path: 'mountain-rescue', name: 'mountainRescue', component: () => import('@/views/Enterprise/Emergency/MountainRescue.vue'), title: '山岳搜救', showInNav: true },
-    ]
+    ],
   },
   {
     path: 'law-enforcement',
@@ -55,13 +109,37 @@ const enterpriseRoutes: NavItem[] = [
     children: [
       {
         path: '',
-        redirect: { name: 'investigation' }
+        redirect: { name: 'investigation' },
+      },
+      {
+        path: 'investigation',
+        name: 'investigation',
+        component: () => import('@/views/Enterprise/LawEnforcement/Investigation.vue'),
+        title: '侦查取证',
+        showInNav: true,
+      },
+      {
+        path: 'patrol',
+        name: 'patrol',
+        component: () => import('@/views/Enterprise/LawEnforcement/Patrol.vue'),
+        title: '治安巡逻',
+        showInNav: true,
+      },
+      {
+        path: 'traffic',
+        name: 'traffic',
+        component: () => import('@/views/Enterprise/LawEnforcement/Traffic.vue'),
+        title: '交通治理',
+        showInNav: true,
+      },
+      {
+        path: 'city-management',
+        name: 'cityManagement',
+        component: () => import('@/views/Enterprise/LawEnforcement/CityManagement.vue'),
+        title: '城管巡查',
+        showInNav: true,
       },
-      { path: 'investigation', name: 'investigation', component: () => import('@/views/Enterprise/LawEnforcement/Investigation.vue'), title: '侦查取证', showInNav: true },
-      { path: 'patrol', name: 'patrol', component: () => import('@/views/Enterprise/LawEnforcement/Patrol.vue'), title: '治安巡逻', showInNav: true },
-      { path: 'traffic', name: 'traffic', component: () => import('@/views/Enterprise/LawEnforcement/Traffic.vue'), title: '交通治理', showInNav: true },
-      { path: 'city-management', name: 'cityManagement', component: () => import('@/views/Enterprise/LawEnforcement/CityManagement.vue'), title: '城管巡查', showInNav: true },
-    ]
+    ],
   },
   {
     path: 'safety-production',
@@ -72,13 +150,31 @@ const enterpriseRoutes: NavItem[] = [
     children: [
       {
         path: '',
-        redirect: { name: 'supervision' }
+        redirect: { name: 'supervision' },
       },
-      { path: 'supervision', name: 'supervision', component: () => import('@/views/Enterprise/SafetyProduction/Supervision.vue'), title: '安全生产部门监管', showInNav: true },
-      { path: 'self-inspection', name: 'selfInspection', component: () => import('@/views/Enterprise/SafetyProduction/SelfInspection.vue'), title: '企业安全生产自查', showInNav: true },
-      { path: 'accident-handling', name: 'accidentHandling', component: () => import('@/views/Enterprise/SafetyProduction/AccidentHandling.vue'), title: '安全生产事故处置', showInNav: true },
-    ]
-  }
+      {
+        path: 'supervision',
+        name: 'supervision',
+        component: () => import('@/views/Enterprise/SafetyProduction/Supervision.vue'),
+        title: '安全生产部门监管',
+        showInNav: true,
+      },
+      {
+        path: 'self-inspection',
+        name: 'selfInspection',
+        component: () => import('@/views/Enterprise/SafetyProduction/SelfInspection.vue'),
+        title: '企业安全生产自查',
+        showInNav: true,
+      },
+      {
+        path: 'accident-handling',
+        name: 'accidentHandling',
+        component: () => import('@/views/Enterprise/SafetyProduction/AccidentHandling.vue'),
+        title: '安全生产事故处置',
+        showInNav: true,
+      },
+    ],
+  },
 ]
 
 const routes: NavItem[] = [
@@ -87,7 +183,7 @@ const routes: NavItem[] = [
     name: 'home',
     component: HomeView,
     title: '概览',
-    showInNav: true
+    showInNav: true,
   },
   {
     path: '/enterprise',
@@ -96,23 +192,23 @@ const routes: NavItem[] = [
     title: '行业',
     showInNav: true,
     children: enterpriseRoutes,
-    redirect: { path: '/enterprise/public-safety' }
+    redirect: { path: '/enterprise/public-safety' },
   },
   {
     path: '/doc',
     name: 'doc',
-    component: DocView,
+    component: () => import('@/views/Doc/index.vue'),
     title: '文档中心',
     showInNav: true,
     meta: {
-      hideFooter: true
+      hideFooter: true,
     }
-  }
+  },
 ]
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
-  routes: routes as RouteRecordRaw[]
+  routes: routes as RouteRecordRaw[],
 })
 
 export default router

+ 31 - 805
web/src/views/Doc/index.vue

@@ -1,823 +1,49 @@
 <script setup lang="ts">
-import { ref } from 'vue'
-
-// 接口定义
-interface MenuItem {
-  key: string;
-  title: string;
-  type: 'link' | 'group';
-  children?: MenuItem[];
-}
-
-interface DocSection {
-  title: string;
-  text?: string;
-  image?: {
-    src: string;
-    alt: string;
-    width?: string;
-    height?: string;
-  };
-  table?: {
-    headers: string[];
-    rows: string[][];
-  };
-}
-
-interface DocContent {
-  title: string;
-  updateDate: string;
-  rating: number;
-  ratingCount: number;
-  gitUrl: string;
-  content: {
-    title: string;
-    date: string;
-    sections?: DocSection[];
-  }
-}
-
-// 左侧导航菜单配置
-const menuItems = ref<MenuItem[]>([
-  {
-    key: 'version-release',
-    title: '版本发布记录',
-    type: 'link'
-  },
-  {
-    key: 'doc-guide',
-    title: '文档阅读指引',
-    type: 'link'
-  },
-  {
-    key: 'basic-intro',
-    title: '基本介绍',
-    type: 'group',
-    children: [
-      {
-        key: 'product-intro',
-        title: '产品介绍',
-        type: 'link'
-      },
-      {
-        key: 'product-architecture',
-        title: '产品架构',
-        type: 'link'
-      },
-      {
-        key: 'product-support',
-        title: '产品支持',
-        type: 'link'
-      },
-      {
-        key: 'basic-concept',
-        title: '基本概念',
-        type: 'link'
-      }
-    ]
-  }
-]);
-
-// 折叠菜单状态
-const expandedMenus = ref<{ [key: string]: boolean }>({
-  'basic-intro': false,
-});
-
-// 当前选中的导航项
-const currentNav = ref<string>('version-release');
-
-// 文档内容数据
-const docContents = ref<{ [key: string]: DocContent }>({
-  'version-release': {
-    title: '版本发布记录',
-    updateDate: '2025-02-27',
-    rating: 4,
-    ratingCount: 183,
-    gitUrl: 'https://github.com/dji-sdk/Cloud-API-Doc/blob/master/docs/cn/00.index.md',
-    content: {
-      title: '上云 API v1.13.0 发布记录',
-      date: '2025.02.27',
-      sections: [
-        {
-          title: '主要更新',
-          text: '此版本包含多项功能增强和bug修复,提升了整体稳定性和用户体验。'
-        },
-        {
-          title: '功能图示',
-          image: {
-            src: '/src/assets/img/api-diagram.svg',
-            alt: 'API功能架构图',
-            width: '100%'
-          }
-        },
-        {
-          title: '版本对比',
-          table: {
-            headers: ['功能', 'v1.12.0', 'v1.13.0'],
-            rows: [
-              ['实时数据传输', '支持', '支持'],
-              ['离线数据同步', '不支持', '支持'],
-              ['多设备管理', '有限支持', '完全支持'],
-              ['安全认证', '基础版', '增强版']
-            ]
-          }
-        }
-      ]
-    }
-  },
-  'doc-guide': {
-    title: '文档阅读指引',
-    updateDate: '2025-02-26',
-    rating: 5,
-    ratingCount: 156,
-    gitUrl: 'https://github.com/dji-sdk/Cloud-API-Doc/blob/master/docs/cn/01.guide.md',
-    content: {
-      title: '文档阅读指引',
-      date: '2025.02.26',
-      sections: [
-        {
-          title: '如何使用本文档',
-          text: '本文档提供了详细的API使用说明和示例代码,帮助开发者快速集成和使用云平台功能。'
-        },
-        {
-          title: '文档结构',
-          image: {
-            src: '/src/assets/img/doc-structure.svg',
-            alt: '文档结构示意图',
-            width: '80%'
-          }
-        }
-      ]
-    }
-  },
-  'product-intro': {
-    title: '产品介绍',
-    updateDate: '2025-02-25',
-    rating: 4.5,
-    ratingCount: 210,
-    gitUrl: 'https://github.com/dji-sdk/Cloud-API-Doc/blob/master/docs/cn/02.product-intro.md',
-    content: {
-      title: '云平台产品介绍',
-      date: '2025.02.25',
-      sections: [
-        {
-          title: '产品概述',
-          text: '云平台是一个全面的解决方案,提供设备管理、数据分析和远程控制等功能,帮助企业实现数字化转型。'
-        },
-        {
-          title: '核心优势',
-          table: {
-            headers: ['优势', '描述'],
-            rows: [
-              ['高可靠性', '99.99%的服务可用性,确保业务连续性'],
-              ['可扩展性', '支持百万级设备接入,满足企业规模化需求'],
-              ['数据安全', '多层次安全防护,保障数据传输和存储安全'],
-              ['开放生态', '丰富的API接口,支持与第三方系统集成']
-            ]
-          }
-        },
-        {
-          title: '产品架构',
-          image: {
-            src: '/src/assets/img/product-architecture.svg',
-            alt: '产品架构图',
-            width: '100%'
-          }
-        },
-      ]
-    }
-  },
-  'product-architecture': {
-    title: '产品架构',
-    updateDate: '2025-02-24',
-    rating: 4.8,
-    ratingCount: 175,
-    gitUrl: 'https://github.com/dji-sdk/Cloud-API-Doc/blob/master/docs/cn/03.product-architecture.md',
-    content: {
-      title: '云平台架构设计',
-      date: '2025.02.24',
-      sections: [
-        {
-          title: '系统架构',
-          text: '云平台采用微服务架构设计,包含设备接入、数据处理、业务逻辑和应用服务等多个层次。'
-        },
-        {
-          title: '架构图',
-          image: {
-            src: '/src/assets/img/system-architecture.svg',
-            alt: '系统架构图',
-            width: '100%'
-          }
-        },
-        {
-          title: '技术栈',
-          table: {
-            headers: ['层级', '技术组件'],
-            rows: [
-              ['接入层', 'MQTT, WebSocket, HTTP'],
-              ['处理层', 'Kafka, Flink, Spark'],
-              ['存储层', 'TimescaleDB, Redis, MinIO'],
-              ['应用层', 'Spring Cloud, Node.js, React']
-            ]
-          }
-        }
-      ]
-    }
-  },
-  'product-support': {
-    title: '产品支持',
-    updateDate: '2025-02-23',
-    rating: 4.7,
-    ratingCount: 198,
-    gitUrl: 'https://github.com/dji-sdk/Cloud-API-Doc/blob/master/docs/cn/04.product-support.md',
-    content: {
-      title: '云平台技术支持与服务',
-      date: '2025.02.23',
-      sections: [
-        {
-          title: '技术支持',
-          text: '我们提供7x24小时的技术支持服务,确保客户在使用过程中遇到的问题能够及时解决。'
-        },
-        {
-          title: '服务协议',
-          table: {
-            headers: ['服务内容', '响应时间'],
-            rows: [
-              ['技术咨询', '1小时内'],
-              ['故障处理', '4小时内'],
-              ['功能请求', '48小时内']
-            ]
-          }
-        },
-        {
-          title: '客户案例',
-          image: {
-            src: '/src/assets/img/customer-case.svg',
-            alt: '客户案例图',
-            width: '100%'
-          }
-        }
-      ]
-    }
-  },
-  'basic-concept': {
-    title: '基础概念',
-    updateDate: '2025-02-22',
-    rating: 4.6,
-    ratingCount: 185,
-    gitUrl: 'https://github.com/dji-sdk/Cloud-API-Doc/blob/master/docs/cn/05.basic-concept.md',
-    content: {
-      title: '云平台基本概念介绍',
-      date: '2025.02.22',
-      sections: [
-        {
-          title: '云平台概念',
-          text: '云平台是一个集成了设备管理、数据分析和应用服务的综合性平台,旨在帮助企业实现数字化转型。'
-        },
-        {
-          title: '核心概念',
-          table: {
-            headers: ['概念', '描述'],
-            rows: [
-              ['设备', '接入云平台的硬件设备'],
-              ['数据', '设备产生的数据,包括传感器数据、日志等'],
-              ['API', '云平台提供的接口,用于与外部系统交互']
-            ]
-          }
-        }
-      ]
-    }
-  }
-});
-
-// 切换菜单展开/收起状态
-const toggleMenu = (menuKey: string) => {
-  expandedMenus.value[menuKey] = !expandedMenus.value[menuKey];
-};
-
-// 切换导航
-const switchNav = (navKey: string) => {
-  currentNav.value = navKey;
-};
-
-// 获取当前显示的内容
-const getCurrentContent = () => {
-  return docContents.value[currentNav.value];
-};
+const docUrl = 'https://onemyriad.apifox.cn'
 </script>
 
 <template>
-  <div class="doc-container">
-    <!-- 左侧边栏 -->
-    <aside class="sidebar">
-      <!-- 文档导航菜单 -->
-      <ul class="sidebar-items">
-        <li v-for="item in menuItems" :key="item.key">
-          <!-- 链接类型菜单项 -->
-          <a
-            v-if="item.type === 'link'"
-            @click.prevent="switchNav(item.key)"
-            href="#"
-            class="sidebar-item sidebar-heading"
-            :class="{ active: currentNav === item.key }"
-          >{{ item.title }}</a>
-
-          <!-- 分组类型菜单项 -->
-          <template v-else-if="item.type === 'group'">
-            <p @click="toggleMenu(item.key)" class="sidebar-item sidebar-heading collapsible">
-              {{ item.title }}
-              <span :class="['arrow', expandedMenus[item.key] ? 'down' : 'right']"></span>
-            </p>
-            <ul class="sidebar-item-children" :style="{
-              maxHeight: expandedMenus[item.key] ? '200px' : '0',
-              opacity: expandedMenus[item.key] ? '1' : '0'
-            }">
-              <li v-for="child in item.children" :key="child.key">
-                <a
-                  @click.prevent="switchNav(child.key)"
-                  href="#"
-                  class="sidebar-item"
-                  :class="{ active: currentNav === child.key }"
-                >{{ child.title }}</a>
-              </li>
-            </ul>
-          </template>
-        </li>
-      </ul>
-    </aside>
-
-    <!-- 右侧内容区 -->
-    <main class="page">
-      <div id="page-content" class="page-content">
-        <div class="page-top">
-          <h1>{{ getCurrentContent().title }}</h1>
-          <div class="page-header-meta">
-            <!-- 更新日期 -->
-            <span class="update-date">
-              <i class="el-icon">
-                <img src="@/assets/icons/calendar.svg" alt="Calendar" />
-              </i>
-              {{ getCurrentContent().updateDate }}
-            </span>
-            <!-- 评分 -->
-            <span class="rate-area">
-              <div class="el-rate is-disabled" role="slider" :aria-label="'rating'" :aria-valuenow="getCurrentContent().rating" :aria-valuetext="getCurrentContent().rating + ' 分'" aria-valuemin="0" aria-valuemax="5" tabindex="0">
-                <span class="el-rate__item" v-for="i in 5" :key="i">
-                  <i class="el-icon el-rate__icon" :class="{ 'is-active': i <= getCurrentContent().rating }">
-                    <img src="@/assets/icons/star.svg" alt="Star" />
-                  </i>
-                </span>
-                <span class="el-rate__text">{{ getCurrentContent().rating }} 分</span>
-              </div>
-              <span class="rate-count">{{ getCurrentContent().ratingCount }} 用户已评分</span>
-            </span>
-            <!-- github edit -->
-            <div class="meta-item edit-link">
-              <a class="external-link meta-item-label" :href="getCurrentContent().gitUrl" rel="noopener noreferrer" target="_blank" aria-label="Github Edit">
-                Github Edit
-                <span>
-                  <img class="external-link-icon" src="@/assets/icons/external-link.svg" alt="External Link" />
-                  <span class="external-link-icon-sr-only">open in new window</span>
-                </span>
-              </a>
-            </div>
-          </div>
-        </div>
-        <!-- 目录 -->
-        <div class="theme-default-content">
-          <!-- 这里是文档内容 -->
-          <div>
-            <h2 :id="getCurrentContent().content.title" tabindex="-1">
-              <a class="header-anchor" :href="'#' + getCurrentContent().content.title" aria-hidden="true">#</a>
-              {{ getCurrentContent().content.title }}
-            </h2>
-            <h3 id="发布日期" tabindex="-1">
-              <a class="header-anchor" href="#发布日期" aria-hidden="true">#</a>
-              发布日期
-            </h3>
-            <p>{{ getCurrentContent().content.date }}</p>
-
-            <!-- 动态内容部分 -->
-            <div v-if="getCurrentContent().content.sections">
-              <div v-for="(section, index) in getCurrentContent().content.sections" :key="index" class="content-section">
-                <!-- 小节标题 -->
-                <h3 :id="section.title" tabindex="-1">
-                  <a class="header-anchor" :href="'#' + section.title" aria-hidden="true">#</a>
-                  {{ section.title }}
-                </h3>
-
-                <!-- 文本内容 -->
-                <p v-if="section.text">{{ section.text }}</p>
-
-                <!-- 图片内容 -->
-                <div v-if="section.image" class="image-container">
-                  <img
-                    :src="section.image.src"
-                    :alt="section.image.alt"
-                    :width="section.image.width || 'auto'"
-                    :height="section.image.height || 'auto'"
-                  />
-                  <div class="image-caption">{{ section.image.alt }}</div>
-                </div>
-
-                <!-- 表格内容 -->
-                <div v-if="section.table" class="table-container">
-                  <table>
-                    <thead>
-                    <tr>
-                      <th v-for="(header, hIndex) in section.table.headers" :key="hIndex">{{ header }}</th>
-                    </tr>
-                    </thead>
-                    <tbody>
-                    <tr v-for="(row, rIndex) in section.table.rows" :key="rIndex">
-                      <td v-for="(cell, cIndex) in row" :key="cIndex">{{ cell }}</td>
-                    </tr>
-                    </tbody>
-                  </table>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
+  <div class="doc-page">
+    <!-- iframe嵌入外部文档 -->
+    <main class="doc-main">
+      <iframe
+        :src="docUrl"
+        class="doc-iframe"
+        frameborder="0"
+        allowfullscreen
+      ></iframe>
     </main>
+
+    <!-- 保留Footer -->
+    <footer class="doc-footer">
+      <p>© 2025 OneMyriad, Ltd.</p>
+    </footer>
   </div>
 </template>
 
-<style lang="scss" scoped>
-// 变量定义
-$primary-color: #3eaf7c;
-$text-color: #2c3e50;
-$border-color: #eaecef;
-$bg-color: #fff;
-$meta-color: #6a8bad;
-$rate-color: #F7BA2A;
-$disabled-color: #C6D1DE;
-$hover-bg: #f3f5f7;
-$even-row-bg: #f9f9f9;
-
-// Mixins
-@mixin flex-center {
-  display: flex;
-  align-items: center;
-}
-
-@mixin transition($property: all) {
-  transition: $property 0.3s ease;
-}
-
-@mixin icon-size($size: 1rem) {
-  width: $size;
-  height: $size;
-}
-
-// 容器样式
-.doc-container {
+<style scoped>
+.doc-page {
   display: flex;
-  min-height: calc(100vh - 64px); // 减去顶部导航栏的高度
-  position: relative;
-  margin-top: 60px; // 为顶部导航栏留出空间
-  max-width: 100%; // 确保容器可以占满整个屏幕宽度
-}
-
-// 侧边栏样式
-.sidebar {
-  width: 280px; // 稍微调整侧边栏宽度
-  flex: 0 0 280px; // 固定宽度,不伸缩
-  border-right: 1px solid $border-color;
-  background-color: $bg-color;
-  overflow-y: auto;
-  padding: 1.5rem 0;
-  position: fixed;
-  top: 60px; // 预留顶部导航栏的高度
-  bottom: 0;
-  left: 0; // 恢复到左边界
-  z-index: 10;
-
-  &-items {
-    list-style: none;
-    padding: 1.5rem 0;
-    margin: 0;
-  }
-
-  &-item {
-    display: block;
-    padding: 0.35rem 1.5rem;
-    color: $text-color;
-    text-decoration: none;
-    font-size: 0.9rem;
-    position: relative;
-    @include transition;
-    cursor: pointer;
-
-    &:hover {
-      color: $primary-color;
-      background-color: rgba($primary-color, 0.05);
-    }
-
-    &.active {
-      color: $primary-color;
-      background-color: rgba($primary-color, 0.1);
-      font-weight: 600;
-    }
-
-    // 点击涟漪效果
-    &::after {
-      content: '';
-      position: absolute;
-      top: 50%;
-      left: 50%;
-      @include icon-size(5px);
-      background: rgba($primary-color, 0.3);
-      opacity: 0;
-      border-radius: 100%;
-      transform: scale(1, 1) translate(-50%);
-      transform-origin: 50% 50%;
-    }
-
-    &:active::after {
-      animation: ripple 0.6s ease-out;
-    }
-  }
-
-  &-heading {
-    font-weight: 600;
-    border-left: 0.25rem solid transparent;
-    margin-left: -0.25rem;
-    @include transition(border-left-color);
-    margin-bottom: 0;
-
-    &.active {
-      color: $primary-color;
-      border-left-color: $primary-color;
-    }
-  }
-
-  &-item-children {
-    list-style: none;
-    padding-left: 0;
-    margin: 0;
-    overflow: hidden;
-    @include transition(max-height);
-
-    .sidebar-item {
-      padding: 0.35rem 2.5rem;
-      font-size: 0.9rem;
-      position: relative;
-
-      &::before {
-        content: '';
-        position: absolute;
-        left: 1rem;
-        top: 50%;
-        transform: translateY(-50%);
-        @include icon-size(4px);
-        background-color: $text-color;
-        border-radius: 50%;
-        opacity: 0.4;
-        @include transition;
-      }
-
-      &:hover::before,
-      &.active::before {
-        background-color: $primary-color;
-        opacity: 1;
-      }
-    }
-  }
+  flex-direction: column;
+  min-height: 100vh;
 }
 
-// 涟漪动画
-@keyframes ripple {
-  0% {
-    transform: scale(0, 0);
-    opacity: 0.5;
-  }
-  20% {
-    transform: scale(25, 25);
-    opacity: 0.3;
-  }
-  100% {
-    opacity: 0;
-    transform: scale(40, 40);
-  }
-}
-
-// 折叠箭头
-.collapsible {
-  cursor: pointer;
-  @include flex-center;
-  justify-content: space-between;
-}
-
-.arrow {
-  display: inline-block;
-  width: 0;
-  height: 0;
-  border: 5px solid transparent;
-
-  &.down {
-    border-top-color: $text-color;
-    margin-top: 3px;
-  }
-
-  &.right {
-    border-left-color: $text-color;
-    margin-left: 3px;
-  }
-}
-
-// 右侧内容区样式
-.page {
+.doc-main {
   flex: 1;
-  padding: 2rem 40px; // 左右padding与header保持一致
-  overflow-y: auto;
-  margin-left: 280px; // 与侧边栏宽度一致,确保内容不被遮挡
-  box-sizing: border-box;
-
-  &-content {
-    max-width: 100%; // 使用完整宽度
-    margin: 0; // 移除额外的margin
-  }
-
-  &-top {
-    padding-bottom: 1rem;
-    border-bottom: 1px solid $border-color;
-    margin-bottom: 2rem;
-  }
-
-  &-header-meta {
-    @include flex-center;
-    font-size: 0.9rem;
-    color: $meta-color;
-  }
-}
-
-// 元信息样式
-.update-date {
-  @include flex-center;
-  margin-right: 1rem;
-}
-
-.el-icon {
-  margin-right: 0.5rem;
-  @include flex-center;
-
-  img {
-    @include icon-size;
-  }
-}
-
-.rate-area {
-  @include flex-center;
-  margin-right: 1rem;
-}
-
-.el-rate {
-  display: inline-flex;
-  margin-right: 0.5rem;
-  vertical-align: text-bottom;
-
-  &__icon {
-    font-size: 1rem;
-    color: $disabled-color;
-
-    &.is-active {
-      color: $rate-color;
-    }
-
-    img {
-      @include icon-size;
-    }
-  }
-
-  &__item {
-    margin-right: 6px;
-  }
-
-  &__text {
-    font-size: 14px;
-    vertical-align: middle;
-  }
-}
-
-.rate-count {
-  font-size: 0.8rem;
-}
-
-// 外部链接
-.meta-item.edit-link {
-  font-size: 0.9rem;
-}
-
-.external-link {
-  color: $primary-color;
-  text-decoration: none;
-
-  &:hover {
-    text-decoration: underline;
-  }
-
-  &-icon {
-    margin-left: 0.25rem;
-    width: 15px;
-    height: 15px;
-  }
-}
-
-// 内容样式
-.theme-default-content {
-  padding: 2rem 0;
-  text-align: left; // 确保文本左对齐
-}
-
-// 标题样式
-h1, h2, h3 {
-  font-weight: 600;
-  line-height: 1.25;
-
-  &:hover .header-anchor {
-    opacity: 1;
-  }
-}
-
-h1 {
-  font-size: 2.2rem;
-}
-
-h2 {
-  font-size: 1.65rem;
-  padding-bottom: 0.3rem;
-  border-bottom: 1px solid $border-color;
-  margin-top: 2rem;
-}
-
-h3 {
-  font-size: 1.35rem;
-  margin-top: 1.5rem;
-}
-
-.header-anchor {
-  font-size: 0.85em;
-  float: left;
-  margin-left: -0.87em;
-  padding-right: 0.23em;
-  margin-top: 0.125em;
-  opacity: 0;
-  text-decoration: none;
-}
-
-p {
-  line-height: 1.7;
-}
-
-// 内容区域样式
-.content-section {
-  margin-bottom: 2rem;
-}
-
-.image-container {
-  margin: 1.5rem 0;
-  text-align: left; // 图片左对齐,与文本保持一致
-}
-
-.image-caption {
-  color: $meta-color;
-  font-size: 0.9rem;
-  margin-top: 0.5rem;
-  text-align: left; // 图片说明左对齐
-}
-
-// 表格样式
-.table-container {
-  margin: 1.5rem 0;
-  overflow-x: auto;
+  padding: 0 1rem;
+  position: relative;
+  overflow: hidden;
 }
 
-table {
-  border-collapse: collapse;
+.doc-iframe {
   width: 100%;
-  margin: 1rem 0;
-
-  th, td {
-    border: 1px solid $border-color;
-    padding: 0.6rem 1rem;
-    text-align: left;
-  }
-
-  th {
-    background-color: $hover-bg;
-    font-weight: 600;
-  }
-
-  tr {
-    &:nth-child(even) {
-      background-color: $even-row-bg;
-    }
+  height: 100%;
+  min-height: calc(100vh - 120px); /* 减去header和footer高度 */
+}
 
-    &:hover {
-      background-color: $hover-bg;
-    }
-  }
+.doc-footer {
+  padding: 1rem;
+  text-align: center;
+  background: #f5f5f5;
 }
 </style>

+ 0 - 101
web/src/views/Enterprise/Emergency/index_bk.vue

@@ -1,101 +0,0 @@
-<script setup lang="ts">
-import { useRoute } from 'vue-router'
-import { computed } from 'vue'
-
-const route = useRoute()
-
-const subMenuItems = [
-  { path: '/enterprise/emergency/flood', title: '洪涝灾害救援' },
-  { path: '/enterprise/emergency/forest-fire', title: '森林火灾救援' },
-  { path: '/enterprise/emergency/earthquake', title: '地震与地质灾害救援' },
-  { path: '/enterprise/emergency/mountain-rescue', title: '山岳搜救' }
-]
-
-const currentPath = computed(() => route.path)
-</script>
-
-<template>
-  <div class="emergency-view">
-    <div class="header">
-      <h1>应急救援解决方案</h1>
-      <p class="description">为应急救援提供高效、精准的数字化支持</p>
-    </div>
-
-    <!-- 子菜单导航 -->
-    <nav class="sub-nav">
-      <router-link
-        v-for="item in subMenuItems"
-        :key="item.path"
-        :to="item.path"
-        class="nav-item"
-        :class="{ active: currentPath === item.path }"
-      >
-        {{ item.title }}
-      </router-link>
-    </nav>
-
-    <!-- 子路由视图 -->
-    <div class="content">
-      <router-view></router-view>
-    </div>
-  </div>
-</template>
-
-<style scoped lang="scss">
-@use '@/assets/styles/variables' as v;
-@use '@/assets/styles/mixins' as m;
-
-.emergency-view {
-  padding: v.$spacing-xl v.$spacing-xl * 2;
-
-  .header {
-    text-align: center;
-    margin-bottom: v.$spacing-xl * 2;
-
-    h1 {
-      font-size: v.$font-size-xxl;
-      color: v.$text-primary;
-      margin-bottom: v.$spacing-md;
-    }
-
-    .description {
-      font-size: v.$font-size-lg;
-      color: v.$text-secondary;
-    }
-  }
-
-  .sub-nav {
-    display: flex;
-    justify-content: center;
-    gap: v.$spacing-md;
-    margin-bottom: v.$spacing-xl;
-    padding: v.$spacing-md;
-    background-color: v.$background-light;
-    border-radius: v.$border-radius-lg;
-    box-shadow: v.$shadow-sm;
-
-    .nav-item {
-      padding: v.$spacing-sm v.$spacing-md;
-      color: v.$text-primary;
-      text-decoration: none;
-      border-radius: v.$border-radius-md;
-      transition: all v.$transition-fast;
-
-      &:hover {
-        background-color: rgba(v.$primary-color, 0.1);
-        color: v.$primary-color;
-      }
-
-      &.active {
-        background-color: v.$primary-color;
-        color: white;
-      }
-    }
-  }
-
-  .content {
-    max-width: 1200px;
-    margin: 0 auto;
-  }
-}
-</style>

+ 38 - 36
web/src/views/Home/index.vue

@@ -18,45 +18,47 @@ const supportedProducts = ref([
 </script>
 
 <template>
-  <main>
-    <div class="api-overview-page">
-      <!-- 头部区域 -->
-      <Section
-        heroSection
-        dark
-        centered
-        bgImage="//devcn.djicdn.com/img/6997ab1.png"
-        title="低门槛接入三方云平台"
-        subtitle="无需重复开发APP,即可让无人机通过DJI Pilot2或大疆机场快速接入三方云平台"
-      />
+  <div class="api-overview-page">
+    <!-- 头部区域 -->
+    <Section
+      heroSection
+      dark
+      centered
+      bgImage="//devcn.djicdn.com/img/6997ab1.png"
+      title="低门槛接入三方云平台"
+      subtitle="无需重复开发APP,即可让您的设备快速接入流媒体平台"
+    />
 
-      <!-- 核心理念 -->
-      <Section
-        title="核心理念"
-        subtitle="上云API基于业界标准的MQTT、HTTPS、Websocket协议,对无人机业务功能集充分抽象,隔离了复杂的无人机底层业务逻辑,让开发者聚焦在场景业务实现上。同时,上云API可以连接到任意网络,只要DJI Pilot2或大疆机场可以访问三方云平台即可工作"
-      >
-        <img src="//devcn.djicdn.com/img/046ccbe.png" class="section-img" alt="Core Concept">
-      </Section>
+    <!-- 核心理念 -->
+    <Section
+      title="核心理念"
+      subtitle="基于业界标准的MQTT、HTTPS、Websocket协议,对直播业务功能集充分抽象,隔离了复杂的硬件底层业务逻辑,让开发者聚焦在场景业务实现上。同时,可以连接到任意网络,只要您的设备可以访问三方云平台即可工作"
+    >
+      <img src="//devcn.djicdn.com/img/046ccbe.png" class="section-img" alt="Core Concept" />
+    </Section>
 
-      <!-- 方案架构 -->
-      <Section title="方案架构">
-        <img src="//devcn.djicdn.com/img/baca5bf.jpg" class="section-img" alt="Solution Architecture">
-      </Section>
+    <!-- 方案架构 -->
+    <Section title="方案架构">
+      <img
+        src="//devcn.djicdn.com/img/baca5bf.jpg"
+        class="section-img"
+        alt="Solution Architecture"
+      />
+    </Section>
 
-      <!-- 支持的产品 -->
-      <Section title="支持的DJI产品">
-        <div class="supported-products">
-          <ProductCard
-            v-for="product in supportedProducts"
-            :key="product.name"
-            :title="product.name"
-            :image="product.image"
-            class="product-item"
-          />
-        </div>
-      </Section>
-    </div>
-  </main>
+    <!-- 支持的产品 -->
+    <Section title="支持的产品">
+      <div class="supported-products">
+        <ProductCard
+          v-for="product in supportedProducts"
+          :key="product.name"
+          :title="product.name"
+          :image="product.image"
+          class="product-item"
+        />
+      </div>
+    </Section>
+  </div>
 </template>
 
 <style lang="scss" scoped>