307 lines
13 KiB
HTML
307 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>MeshRay - 简单、高效异地组网</title>
|
|
|
|
<!-- Tailwind CSS -->
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
|
|
<!-- Vue 3 -->
|
|
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
|
|
|
<!-- Element Plus -->
|
|
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
|
|
<script src="https://unpkg.com/element-plus"></script>
|
|
|
|
<!-- Element Plus Icons -->
|
|
<script src="https://unpkg.com/@element-plus/icons-vue"></script>
|
|
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
}
|
|
|
|
.sidebar {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.logo {
|
|
color: white;
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
padding: 20px;
|
|
text-align: center;
|
|
border-bottom: 1px solid rgba(255,255,255,0.1);
|
|
}
|
|
|
|
.menu-item {
|
|
color: rgba(255,255,255,0.8);
|
|
padding: 15px 20px;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.menu-item:hover, .menu-item.active {
|
|
background: rgba(255,255,255,0.2);
|
|
color: white;
|
|
}
|
|
|
|
.main-content {
|
|
background: #f5f7fa;
|
|
min-height: 100vh;
|
|
padding: 20px;
|
|
}
|
|
|
|
.card {
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 12px rgba(0,0,0,0.1);
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.stat-card {
|
|
text-align: center;
|
|
padding: 30px;
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 36px;
|
|
font-weight: bold;
|
|
color: #667eea;
|
|
}
|
|
|
|
.stat-label {
|
|
color: #909399;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
/* 登录页面样式 */
|
|
.login-container {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
min-height: 100vh;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
}
|
|
|
|
.login-box {
|
|
background: white;
|
|
padding: 40px;
|
|
border-radius: 12px;
|
|
box-shadow: 0 8px 32px rgba(0,0,0,0.2);
|
|
width: 400px;
|
|
}
|
|
|
|
.login-title {
|
|
text-align: center;
|
|
color: #667eea;
|
|
font-size: 32px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.login-subtitle {
|
|
text-align: center;
|
|
color: #909399;
|
|
font-size: 14px;
|
|
margin-bottom: 30px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<!-- 登录页面 -->
|
|
<div v-if="!isLoggedIn" class="login-container">
|
|
<div class="login-box">
|
|
<h1 class="login-title">🔺 MeshRay</h1>
|
|
<p class="login-subtitle">去中心化异地组网平台</p>
|
|
|
|
<el-form :model="loginForm" label-width="80px">
|
|
<el-form-item label="用户名">
|
|
<el-input v-model="loginForm.username" placeholder="请输入用户名" prefix-icon="User"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="密码">
|
|
<el-input v-model="loginForm.password" type="password" placeholder="请输入密码" prefix-icon="Lock" @keyup.enter="handleLogin"></el-input>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" style="width: 100%" :loading="loggingIn" @click="handleLogin">登录</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 主界面 -->
|
|
<el-container v-else>
|
|
<!-- 侧边栏 -->
|
|
<el-aside width="250px" class="sidebar">
|
|
<div class="logo">🔺 MeshRay</div>
|
|
<el-menu
|
|
:default-active="currentPage"
|
|
background-color="transparent"
|
|
text-color="rgba(255,255,255,0.8)"
|
|
active-text-color="#fff"
|
|
>
|
|
<el-menu-item index="dashboard" @click="currentPage = 'dashboard'">
|
|
<el-icon><DataBoard /></el-icon>
|
|
<span>仪表盘</span>
|
|
</el-menu-item>
|
|
<el-menu-item index="networks" @click="currentPage = 'networks'">
|
|
<el-icon><Connection /></el-icon>
|
|
<span>组网管理</span>
|
|
</el-menu-item>
|
|
<el-menu-item index="devices" @click="currentPage = 'devices'">
|
|
<el-icon><Cpu /></el-icon>
|
|
<span>设备管理</span>
|
|
</el-menu-item>
|
|
<el-menu-item index="services" @click="currentPage = 'services'">
|
|
<el-icon><Setting /></el-icon>
|
|
<span>服务管理</span>
|
|
</el-menu-item>
|
|
<el-menu-item index="settings" @click="currentPage = 'settings'">
|
|
<el-icon><Tools /></el-icon>
|
|
<span>系统设置</span>
|
|
</el-menu-item>
|
|
</el-menu>
|
|
</el-aside>
|
|
|
|
<!-- 主内容区 -->
|
|
<el-container>
|
|
<!-- 顶部导航栏 -->
|
|
<el-header style="background: white; border-bottom: 1px solid #e4e7ed; display: flex; justify-content: space-between; align-items: center; padding: 0 20px;">
|
|
<div style="font-size: 18px; font-weight: bold;">欢迎使用 MeshRay</div>
|
|
<el-button type="danger" size="small" @click="handleLogout">退出登录</el-button>
|
|
</el-header>
|
|
<el-main class="main-content">
|
|
<!-- 仪表盘页面 -->
|
|
<div v-if="currentPage === 'dashboard'">
|
|
<h2 class="text-2xl font-bold mb-6">仪表盘</h2>
|
|
|
|
<el-row :gutter="20">
|
|
<el-col :span="6">
|
|
<div class="card stat-card">
|
|
<div class="stat-number">{{ stats.networkCount }}</div>
|
|
<div class="stat-label">组网数量</div>
|
|
</div>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<div class="card stat-card">
|
|
<div class="stat-number">{{ stats.deviceCount }}</div>
|
|
<div class="stat-label">设备数量</div>
|
|
</div>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<div class="card stat-card">
|
|
<div class="stat-number">{{ stats.onlineDevices }}</div>
|
|
<div class="stat-label">在线设备</div>
|
|
</div>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<div class="card stat-card">
|
|
<div class="stat-number">{{ stats.pendingApprovals }}</div>
|
|
<div class="stat-label">待审核</div>
|
|
</div>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<!-- 最近活动 -->
|
|
<div class="card mt-6 p-6">
|
|
<h3 class="text-lg font-bold mb-4">最近活动</h3>
|
|
<el-timeline>
|
|
<el-timeline-item timestamp="2026-03-20 10:00" type="primary">
|
|
系统启动成功
|
|
</el-timeline-item>
|
|
<el-timeline-item timestamp="2026-03-20 09:30" type="success">
|
|
组网 "生产网络" 创建成功
|
|
</el-timeline-item>
|
|
<el-timeline-item timestamp="2026-03-20 09:00" type="warning">
|
|
新设备申请加入 "测试网络"
|
|
</el-timeline-item>
|
|
</el-timeline>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 组网管理页面 -->
|
|
<div v-if="currentPage === 'networks'">
|
|
<h2 class="text-2xl font-bold mb-6">组网管理</h2>
|
|
|
|
<div class="card p-6">
|
|
<el-button type="primary" @click="showCreateNetworkDialog = true">
|
|
<el-icon><Plus /></el-icon>
|
|
创建组网
|
|
</el-button>
|
|
|
|
<el-table :data="networks" style="width: 100%; margin-top: 20px;">
|
|
<el-table-column prop="id" label="ID" width="80"></el-table-column>
|
|
<el-table-column prop="name" label="名称"></el-table-column>
|
|
<el-table-column prop="subnet_ipv4" label="子网"></el-table-column>
|
|
<el-table-column prop="mesh_mode" label="模式">
|
|
<template #default="{ row }">
|
|
<el-tag :type="row.mesh_mode === 'enhanced' ? 'success' : 'info'">
|
|
{{ row.mesh_mode === 'enhanced' ? '增强' : '原生' }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" width="300">
|
|
<template #default="{ row }">
|
|
<el-button size="small" @click="viewNetwork(row)">详情</el-button>
|
|
<el-button size="small" type="success" @click="generateMeshSeed(row)">
|
|
MeshSeed
|
|
</el-button>
|
|
<el-button size="small" type="danger" @click="deleteNetwork(row)">删除</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 其他页面占位 -->
|
|
<div v-if="['devices', 'services', 'settings'].includes(currentPage)">
|
|
<h2 class="text-2xl font-bold mb-6">
|
|
{{ currentPage === 'devices' ? '设备管理' :
|
|
currentPage === 'services' ? '服务管理' : '系统设置' }}
|
|
</h2>
|
|
<div class="card p-6 text-center text-gray-500">
|
|
<p>页面开发中...</p>
|
|
</div>
|
|
</div>
|
|
</el-main>
|
|
</el-container>
|
|
</el-container>
|
|
|
|
<!-- 创建组网对话框 -->
|
|
<el-dialog v-model="showCreateNetworkDialog" title="创建组网" width="500px">
|
|
<el-form :model="newNetwork" label-width="100px">
|
|
<el-form-item label="组网名称">
|
|
<el-input v-model="newNetwork.name" placeholder="请输入组网名称"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="子网">
|
|
<el-input v-model="newNetwork.subnet_ipv4" placeholder="例如:10.0.0.0/24"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="监听端口">
|
|
<el-input-number v-model="newNetwork.listen_port" :min="1024" :max="65535" value="51820"></el-input-number>
|
|
</el-form-item>
|
|
<el-form-item label="组网模式">
|
|
<el-radio-group v-model="newNetwork.mesh_mode">
|
|
<el-radio label="native">原生模式</el-radio>
|
|
<el-radio label="enhanced">增强模式</el-radio>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="showCreateNetworkDialog = false">取消</el-button>
|
|
<el-button type="primary" @click="createNetwork">创建</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
|
|
<script src="/static/js/app.js"></script>
|
|
</body>
|
|
</html>
|