App.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <template>
  2. <a-config-provider>
  3. <a-layout class="app-layout">
  4. <!-- 头部 -->
  5. <a-layout-header class="app-header">
  6. <div class="header-content">
  7. <a-row align="middle" justify="space-between">
  8. <a-col>
  9. <a-space align="center">
  10. <!-- <a-icon type="gateway" size="large" /> -->
  11. <div class="logo"></div>
  12. </a-space>
  13. </a-col>
  14. <a-col>
  15. <StatusIndicator />
  16. </a-col>
  17. </a-row>
  18. </div>
  19. </a-layout-header>
  20. <a-layout>
  21. <!-- 左侧菜单 -->
  22. <a-layout-sider
  23. class="app-sider"
  24. width="256"
  25. :collapsible="true"
  26. v-model:collapsed="collapsed"
  27. :trigger="null"
  28. breakpoint="lg"
  29. collapsed-width="80"
  30. >
  31. <div class="app-title">配线架配置系统</div>
  32. <a-menu
  33. mode="inline"
  34. :selected-keys="[selectedKey]"
  35. :collapsed="collapsed"
  36. @click="handleMenuClick"
  37. theme="dark"
  38. class="side-menu"
  39. >
  40. <a-menu-item key="/real-time-status" icon="<area-chart />">
  41. <router-link to="/real-time-status">实时状态</router-link>
  42. </a-menu-item>
  43. <a-menu-item key="/system-config" icon="<setting />">
  44. <router-link to="/system-config">系统配置</router-link>
  45. </a-menu-item>
  46. <a-menu-item key="/led-debug" icon="<bulb />">
  47. <router-link to="/led-debug">LED调试</router-link>
  48. </a-menu-item>
  49. <a-menu-item key="/network-config" icon="<wifi />">
  50. <router-link to="/network-config">网络配置</router-link>
  51. </a-menu-item>
  52. <a-menu-item key="/about" icon="<info-circle />">
  53. <router-link to="/about">关于</router-link>
  54. </a-menu-item>
  55. </a-menu>
  56. </a-layout-sider>
  57. <!-- 主要内容区域 -->
  58. <a-layout-content class="app-content">
  59. <div class="content-container">
  60. <router-view />
  61. </div>
  62. </a-layout-content>
  63. </a-layout>
  64. <!-- 页脚 -->
  65. <a-layout-footer class="app-footer">
  66. <p class="footer-text">&copy; {{ new Date().getFullYear() }} 配线架配置系统 v1.0.0 | 实时数据通信平台</p>
  67. </a-layout-footer>
  68. </a-layout>
  69. </a-config-provider>
  70. </template>
  71. <script setup>
  72. import { ref, computed, onMounted, watch } from 'vue'
  73. import { useRoute } from 'vue-router'
  74. import StatusIndicator from './components/StatusIndicator.vue'
  75. import { useDataStore } from './stores/dataStore'
  76. import { initWebSocket } from './utils/websocket'
  77. // 初始化数据存储
  78. const dataStore = useDataStore()
  79. const route = useRoute()
  80. const collapsed = ref(false)
  81. // 计算当前选中的菜单项
  82. const selectedKey = computed(() => {
  83. return route.path
  84. })
  85. // 处理菜单点击
  86. const handleMenuClick = (e) => {
  87. console.log('菜单点击:', e.key)
  88. }
  89. // 监听路由变化
  90. watch(() => route.path, (newPath) => {
  91. console.log('路由变化:', newPath)
  92. })
  93. // 组件挂载时初始化WebSocket连接
  94. onMounted(() => {
  95. initWebSocket(dataStore)
  96. })
  97. </script>
  98. <style scoped>
  99. /* 应用布局 */
  100. .app-layout {
  101. min-height: 100vh;
  102. }
  103. /* 头部样式 */
  104. .app-header {
  105. background-color: #001529;
  106. padding: 0;
  107. height: 64px;
  108. line-height: 64px;
  109. position: fixed;
  110. width: 100%;
  111. z-index: 10;
  112. }
  113. .header-content {
  114. max-width: 100%;
  115. margin: 0 auto;
  116. padding: 0 24px;
  117. height: 100%;
  118. }
  119. .app-title {
  120. margin: 0;
  121. font-size: 20px;
  122. font-weight: 600;
  123. color: #fff;
  124. margin: 10px;
  125. font-size: 15px;
  126. margin-bottom: 0;;
  127. }
  128. /* 侧边栏样式 */
  129. .app-sider {
  130. background-color: #001529;
  131. position: fixed;
  132. left: 0;
  133. top: 64px;
  134. height: calc(100vh - 64px);
  135. z-index: 9;
  136. transition: all 0.3s;
  137. }
  138. .logo {
  139. height: 60px;
  140. width: 94px;
  141. position: absolute;
  142. top: 0px;
  143. background: url('/vite.svg') center no-repeat;
  144. background-size: contain;
  145. }
  146. .side-menu {
  147. height: calc(100% - 64px);
  148. padding: 20px 0;
  149. padding-top: 0px;
  150. }
  151. .side-menu .ant-menu-item {
  152. margin: 0;
  153. padding: 0 20px;
  154. height: 50px;
  155. line-height: 50px;
  156. }
  157. .side-menu .ant-menu-item:hover {
  158. background-color: rgba(255, 255, 255, 0.1);
  159. }
  160. .side-menu .ant-menu-item-selected {
  161. background-color: #1890ff;
  162. }
  163. /* 主要内容区域 */
  164. .app-content {
  165. padding: 24px;
  166. background-color: #f0f2f5;
  167. min-height: calc(100vh - 64px);
  168. margin-left: 256px;
  169. margin-top: 64px;
  170. transition: all 0.3s;
  171. }
  172. .app-sider.collapsed + .app-content {
  173. margin-left: 80px;
  174. }
  175. .content-container {
  176. max-width: 100%;
  177. margin: 0 auto;
  178. }
  179. /* 页脚样式 */
  180. .app-footer {
  181. text-align: center;
  182. background-color: #001529;
  183. color: rgba(255, 255, 255, 0.65);
  184. font-size: 14px;
  185. padding: 16px 0;
  186. margin-left: 256px;
  187. transition: all 0.3s;
  188. }
  189. .app-sider.collapsed + .app-content + .app-footer {
  190. margin-left: 80px;
  191. }
  192. .footer-text {
  193. margin: 0;
  194. }
  195. /* 响应式调整 */
  196. @media (max-width: 1024px) {
  197. .app-sider {
  198. transform: translateX(-100%);
  199. }
  200. .app-sider.collapsed {
  201. transform: translateX(0);
  202. }
  203. .app-content {
  204. margin-left: 0;
  205. }
  206. .app-footer {
  207. margin-left: 0;
  208. }
  209. }
  210. @media (max-width: 768px) {
  211. .app-content {
  212. padding: 16px;
  213. }
  214. .header-content {
  215. padding: 0 16px;
  216. }
  217. .app-title {
  218. font-size: 18px;
  219. }
  220. }
  221. /* 路由链接样式 */
  222. :deep(.ant-menu-item a) {
  223. color: rgba(255, 255, 255, 0.65);
  224. width: 100%;
  225. display: flex;
  226. align-items: center;
  227. }
  228. :deep(.ant-menu-item a:hover) {
  229. color: #fff;
  230. }
  231. :deep(.ant-menu-item-selected a) {
  232. color: #fff;
  233. }
  234. /* 修复侧边栏滚动问题 */
  235. :deep(.ant-layout-sider-children) {
  236. overflow-y: auto;
  237. height: 100%;
  238. }
  239. </style>