Add css style

This commit is contained in:
2024-10-15 19:59:20 +08:00
parent bf6e25b722
commit 7fa5bb460c
4 changed files with 150 additions and 198 deletions

View File

@@ -1,29 +1,114 @@
@keyframes glow-border {
0% {
box-shadow: inset 0 0 0 2px #00e6e6;
}
25% {
box-shadow: inset 0 0 0 2px #00e6e6, 2px 0 0 0 #00e6e6;
}
50% {
box-shadow: inset 0 0 0 2px #00e6e6, 2px 0 0 0 #00e6e6, 0 2px 0 0 #00e6e6;
}
75% {
box-shadow: inset 0 0 0 2px #00e6e6, 2px 0 0 0 #00e6e6, 0 2px 0 0 #00e6e6, -2px 0 0 0 #00e6e6;
}
100% {
box-shadow: inset 0 0 0 2px #00e6e6, 2px 0 0 0 #00e6e6, 0 2px 0 0 #00e6e6, -2px 0 0 0 #00e6e6, 0 -2px 0 0 #00e6e6;
}
}
body {
background-color: #1e1e1e;
color: #ffffff;
font-family: Arial, sans-serif;
}
.App-header {
background-color: #282c34;
padding: 20px;
color: white;
}
.App {
text-align: center;
margin: 20px;
padding: 20px;
}
table {
margin: 20px auto;
border-collapse: collapse;
h1 {
color: #eff4f0;
font-size: 4em;
margin-bottom: 20px;
}
table, th, td {
border: 1px solid #ccc;
h2 {
color: #2196f3;
font-size: 2em;
margin-top: 20px;
margin-bottom: 10px;
}
h3 {
color: #ff9800;
font-size: 1.75em;
margin-top: 15px;
margin-bottom: 10px;
}
h4 {
color: #f44336;
font-size: 1.5em;
margin-top: 10px;
margin-bottom: 5px;
}
input, button {
margin: 10px 0;
padding: 10px;
border: none;
border-radius: 5px;
}
th {
background-color: #f0f0f0;
input {
width: 80%;
max-width: 300px;
}
button {
background-color: #2196f3;
color: #ffffff;
cursor: pointer;
}
button:hover {
background-color: #1976d2;
}
section {
background-color: #333333;
padding: 20px;
margin: 20px 0;
border-radius: 10px;
animation: glow-border 4s infinite;
}
.log-info {
width: 80%;
margin: 20px auto;
background-color: #444444;
color: #ffffff;
padding: 10px;
border-radius: 5px;
animation: glow-border 4s infinite;
}
ul {
list-style-type: none;
padding: 0;
}
li {
background-color: #444444;
margin: 5px 0;
padding: 10px;
border-radius: 5px;
}
.container {
display: flex;
justify-content: space-between;
}
.left-panel, .right-panel {
width: 48%;
}

View File

@@ -1,9 +1,9 @@
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import WebSocketComponent from './WebSocketComponent';
import './App.css';
function App() {
const [nodes, setNodes] = useState([]);
const [node, setNode] = useState(null);
const [heartbeat, setHeartbeat] = useState(null);
const [nodesList, setNodesList] = useState([]);
@@ -13,7 +13,7 @@ function App() {
const fetchNodes = async () => {
try {
const response = await axios.get('/server/show_nodes');
setNodes(response.data);
setNodesList(response.data);
} catch (error) {
console.error('Error fetching nodes:', error);
}
@@ -65,52 +65,52 @@ function App() {
return (
<div className="App">
<header className="App-header">
<h1>中央服务器路由</h1>
<h1 className="glow">The server</h1>
<div className="container">
<div className="left-panel">
<section>
<h2 className="glow">get node</h2>
<input
type="text"
value={ip}
onChange={(e) => setIp(e.target.value)}
placeholder="Enter node ip"
/>
<button onClick={handleFetchNode}>send</button>
{node ? <p>{JSON.stringify(node)}</p> : <p>here is nothing!</p>}
</section>
<h2>所有节点</h2>
{nodes.length > 0 ? (
<ul>
{nodes.map((node, index) => (
<li key={index}>{JSON.stringify(node)}</li>
))}
</ul>
) : (
<p>没有节点数据</p>
)}
<section>
<h2 className="glow">heartbeat</h2>
<button onClick={handleFetchHeartbeat}>Get heartbeat</button>
{heartbeat ? <p>{JSON.stringify(heartbeat)}</p> : <p>here is nothing!</p>}
</section>
<h2>单个节点</h2>
<input
type="text"
value={ip}
onChange={(e) => setIp(e.target.value)}
placeholder="输入节点 IP"
/>
<button onClick={handleFetchNode}>获取节点</button>
{node ? <p>{JSON.stringify(node)}</p> : <p></p>}
<h2>心跳信息</h2>
<button onClick={handleFetchHeartbeat}>获取心跳信息</button>
{heartbeat ? <p>{JSON.stringify(heartbeat)}</p> : <p></p>}
<h2>节点列表</h2>
<input
type="number"
value={count}
onChange={(e) => setCount(e.target.value)}
placeholder="输入节点数量"
/>
<button onClick={handleFetchNodesList}>获取节点列表</button>
{nodesList.length > 0 ? (
<ul>
{nodesList.map((node, index) => (
<li key={index}>{JSON.stringify(node)}</li>
))}
</ul>
) : (
<p>没有节点列表数据</p>
)}
<section>
<h2 className="glow">nodes list</h2>
<input
type="number"
value={count}
onChange={(e) => setCount(e.target.value)}
placeholder="Enter the number of nodes"
/>
<button onClick={handleFetchNodesList}>Get node list</button>
{nodesList.length > 0 ? (
<ul>
{nodesList.map((node, index) => (
<li key={index}>{JSON.stringify(node)}</li>
))}
</ul>
) : (
<p>here is nothing!</p>
)}
</section>
</div>
<div className="right-panel">
<WebSocketComponent />
</div>
</div>
</header>
<WebSocketComponent/>
</div>
);
}

View File

@@ -2,9 +2,7 @@ import React, { useEffect, useState, useRef, useCallback } from 'react';
const WebSocketComponent = () => {
const [logs, setLogs] = useState([]);
const [nodes, setNodes] = useState([]);
const wsRef = useRef(null);
const heartbeatIntervalRef = useRef(null);
const connectWebSocket = useCallback(() => {
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
@@ -15,17 +13,11 @@ const WebSocketComponent = () => {
wsRef.current.onopen = () => {
console.log('WebSocket 连接成功');
heartbeatIntervalRef.current = setInterval(() => {
if (wsRef.current.readyState === WebSocket.OPEN) {
wsRef.current.send(JSON.stringify({ type: 'heartbeat' }));
}
}, 10000); // 心跳包间隔调整为 10 秒
};
wsRef.current.onmessage = (event) => {
setLogs((prevLogs) => [...prevLogs, event.data]); // 直接加入收到的消息
};
wsRef.current.onerror = (error) => {
console.error('WebSocket 错误: ', error);
@@ -33,7 +25,6 @@ const WebSocketComponent = () => {
wsRef.current.onclose = () => {
console.log('WebSocket 连接关闭,尝试重新连接...');
clearInterval(heartbeatIntervalRef.current);
// 确保 WebSocket 连接在关闭后再进行重连
setTimeout(() => {
connectWebSocket();
@@ -47,30 +38,9 @@ const WebSocketComponent = () => {
if (wsRef.current) {
wsRef.current.close();
}
clearInterval(heartbeatIntervalRef.current);
};
}, [connectWebSocket]);
// 获取节点信息
const fetchNodes = useCallback(async () => {
try {
const response = await fetch('/server/show_nodes');
const data = await response.json();
setNodes(data);
} catch (error) {
console.error('Error fetching nodes:', error);
}
}, []);
useEffect(() => {
connectWebSocket();
fetchNodes(); // 组件加载时获取节点信息
return () => {
if (wsRef.current) {
wsRef.current.close();
}
clearInterval(heartbeatIntervalRef.current);
};
}, [connectWebSocket, fetchNodes]);
useEffect(() => {
const logContainer = document.querySelector('.log-info');
if (logContainer) {
@@ -80,29 +50,10 @@ const WebSocketComponent = () => {
return (
<div>
<h1>节点记录信息</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>IP</th>
<th>Last Heartbeat</th>
</tr>
</thead>
<tbody>
{nodes.map((node) => (
<tr key={node[0]}>
<td>{node[0]}</td>
<td>{node[1]}</td>
<td>{new Date(node[2] * 1000).toLocaleString()}</td>
</tr>
))}
</tbody>
</table>
<h2>日志信息</h2>
<h2>The logs</h2>
<div
className="log-info"
style={{ height: '300px', overflowY: 'scroll', background: '#fff', padding: '10px' }}
style={{ height: '550px', overflowY: 'scroll', backgroundColor: 'rgb(32, 28, 28)', padding: '10px' }}
>
{logs.map((log, index) => (
<p key={index} style={{ margin: '5px 0' }}>{log}</p>
@@ -112,4 +63,4 @@ const WebSocketComponent = () => {
);
};
export default WebSocketComponent;
export default WebSocketComponent;