| | |
| | | <template> |
| | | <div id="app"> |
| | | <nav class="navbar navbar-expand-sm navbar-dark bg-primary shadow-sm mb-4"> |
| | | <div class="container-fluid"> |
| | | <router-link class="navbar-brand" to="/"> |
| | | <i class="bi bi-cpu-fill me-2"></i>S7 PLC Simulator |
| | | </router-link> |
| | | <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse"> |
| | | <span class="navbar-toggler-icon"></span> |
| | | </button> |
| | | <div class="navbar-collapse collapse"> |
| | | <ul class="navbar-nav flex-grow-1"> |
| | | <li class="nav-item"> |
| | | <router-link class="nav-link" to="/"> |
| | | <i class="bi bi-house-door me-1"></i>实例列表 |
| | | </router-link> |
| | | </li> |
| | | </ul> |
| | | <template> |
| | | <el-container class="admin-layout"> |
| | | <el-aside class="admin-aside" width="220px"> |
| | | <div class="brand-area"> |
| | | <el-icon :size="24" class="brand-icon"><Cpu /></el-icon> |
| | | <div class="brand-text"> |
| | | <div class="brand-title">WCS 模拟平台</div> |
| | | <div class="brand-subtitle">S7 Simulator</div> |
| | | </div> |
| | | </div> |
| | | </nav> |
| | | |
| | | <div class="container-fluid px-4"> |
| | | <router-view /> |
| | | </div> |
| | | <el-menu |
| | | class="aside-menu" |
| | | :default-active="activeMenu" |
| | | background-color="#1f2a37" |
| | | text-color="#c7d2fe" |
| | | active-text-color="#ffffff" |
| | | router |
| | | > |
| | | <el-menu-item index="/"> |
| | | <el-icon><House /></el-icon> |
| | | <span>实例管理</span> |
| | | </el-menu-item> |
| | | <el-menu-item index="/protocol-templates"> |
| | | <el-icon><Files /></el-icon> |
| | | <span>协议模板</span> |
| | | </el-menu-item> |
| | | <el-menu-item index="/robot-clients"> |
| | | <el-icon><Connection /></el-icon> |
| | | <span>机械手客户端</span> |
| | | </el-menu-item> |
| | | </el-menu> |
| | | </el-aside> |
| | | |
| | | <footer class="border-top py-3 mt-4 bg-light"> |
| | | <div class="container-fluid text-center text-muted"> |
| | | <small>© 2026 - S7 PLC Simulator Management UI</small> |
| | | </div> |
| | | </footer> |
| | | </div> |
| | | <el-container> |
| | | <el-header class="admin-header"> |
| | | <div class="header-left"> |
| | | <div class="page-title">{{ pageTitle }}</div> |
| | | <div class="page-path">{{ route.path }}</div> |
| | | </div> |
| | | </el-header> |
| | | |
| | | <el-main class="admin-main"> |
| | | <div class="content-shell"> |
| | | <router-view /> |
| | | </div> |
| | | </el-main> |
| | | </el-container> |
| | | </el-container> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { computed } from 'vue' |
| | | import { useRoute } from 'vue-router' |
| | | import { Connection, Cpu, Files, House } from '@element-plus/icons-vue' |
| | | |
| | | const route = useRoute() |
| | | |
| | | const activeMenu = computed(() => { |
| | | if (route.path.startsWith('/protocol-templates')) return '/protocol-templates' |
| | | if (route.path.startsWith('/robot-clients')) return '/robot-clients' |
| | | return '/' |
| | | }) |
| | | |
| | | const pageTitle = computed(() => { |
| | | if (route.path.startsWith('/create')) return '创建实例' |
| | | if (route.path.startsWith('/edit')) return '编辑实例' |
| | | if (route.path.startsWith('/details')) return '实例详情' |
| | | if (route.path.startsWith('/protocol-templates')) return '协议模板' |
| | | if (route.path.startsWith('/robot-clients')) return '机械手客户端' |
| | | return '实例管理' |
| | | }) |
| | | </script> |
| | | |
| | | <style> |
| | | #app { |
| | | min-height: 100vh; |
| | | <style scoped> |
| | | .admin-layout { |
| | | height: 100vh; |
| | | } |
| | | |
| | | .admin-aside { |
| | | background: linear-gradient(180deg, #1f2a37 0%, #111827 100%); |
| | | border-right: 1px solid #263445; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .container-fluid { |
| | | .brand-area { |
| | | height: 64px; |
| | | padding: 0 14px; |
| | | display: flex; |
| | | align-items: center; |
| | | border-bottom: 1px solid #2b3a4f; |
| | | color: #e5e7eb; |
| | | } |
| | | |
| | | .brand-icon { |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .brand-title { |
| | | font-size: 15px; |
| | | font-weight: 700; |
| | | line-height: 1.2; |
| | | } |
| | | |
| | | .brand-subtitle { |
| | | font-size: 12px; |
| | | color: #94a3b8; |
| | | line-height: 1.2; |
| | | } |
| | | |
| | | .aside-menu { |
| | | border-right: none; |
| | | flex: 1; |
| | | } |
| | | |
| | | .navbar-nav .nav-link.router-link-active { |
| | | font-weight: bold; |
| | | .admin-header { |
| | | height: 64px; |
| | | background: #ffffff; |
| | | border-bottom: 1px solid #e5e7eb; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | .header-left { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 2px; |
| | | } |
| | | |
| | | .page-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #0f172a; |
| | | } |
| | | |
| | | .page-path { |
| | | font-size: 12px; |
| | | color: #64748b; |
| | | } |
| | | |
| | | .admin-main { |
| | | background: #f1f5f9; |
| | | padding: 14px; |
| | | } |
| | | |
| | | .content-shell { |
| | | min-height: calc(100vh - 64px - 28px); |
| | | width: 100%; |
| | | max-width: 1680px; |
| | | margin: 0 auto; |
| | | padding: 2px; |
| | | } |
| | | |
| | | @media (max-width: 960px) { |
| | | .admin-aside { |
| | | width: 64px !important; |
| | | } |
| | | |
| | | .brand-text { |
| | | display: none; |
| | | } |
| | | |
| | | .admin-header { |
| | | padding: 0 12px; |
| | | } |
| | | } |
| | | </style> |