Initial release
This commit is contained in:
commit
b5fa9c2756
18 changed files with 4397 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.db
|
||||
config.json
|
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"html.customData": ["./frontend/node_modules/mdui/html-data.zh-cn.json"],
|
||||
"css.customData": ["./frontend/node_modules/mdui/css-data.zh-cn.json"]
|
||||
}
|
2
README.md
Normal file
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# 我的世界监控台
|
||||
用于查看我的世界服务器状态,并添加了重启功能
|
160
backend/.gitignore
vendored
Normal file
160
backend/.gitignore
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
17
backend/README.md
Normal file
17
backend/README.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
## development
|
||||
Create virtual environment and install dependencies
|
||||
```
|
||||
python -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
Debug the code
|
||||
```
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
|
||||
## deployment
|
||||
```
|
||||
uvicorn main:app --host "127.0.0.1" --port 10010 --proxy-headers --forwarded-allow-ips "*"
|
||||
```
|
19
backend/db.py
Normal file
19
backend/db.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
import sqlite3
|
||||
class MCDB:
|
||||
def __init__(self) -> None:
|
||||
self.conn = sqlite3.connect('database.db')
|
||||
self.cursor = self.conn.cursor()
|
||||
self.cursor.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS mcstatus (
|
||||
time TEXT NOT NULL,
|
||||
latency REAL NOT NULL
|
||||
)"""
|
||||
)
|
||||
self.conn.commit()
|
||||
|
||||
def insert_time_and_latency(self, time, latency):
|
||||
self.cursor.execute("""
|
||||
INSERT INTO mcstatus (time, latency)
|
||||
VALUES (?, ?)
|
||||
""", (time, latency))
|
||||
self.conn.commit()
|
109
backend/main.py
Normal file
109
backend/main.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
import json
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from utils import getJavaServerStatus, schedule_job, get_last_hour_date_info, get_current_day_time_utc8, parse_date_to_h_m_s
|
||||
from contextlib import asynccontextmanager
|
||||
from db import MCDB
|
||||
from pydantic import BaseModel
|
||||
import aiohttp
|
||||
from pathlib import Path
|
||||
|
||||
class Password(BaseModel):
|
||||
code: str
|
||||
|
||||
mcdb = MCDB()
|
||||
|
||||
with open(Path(__file__).parent.parent / "config.json", encoding="utf-8") as f:
|
||||
config = json.load(f)
|
||||
|
||||
HOST = config["mc_host"]
|
||||
PASSWORD = config["password"]
|
||||
RCON_SERVER = config["rcon_host"]
|
||||
|
||||
scheduler = AsyncIOScheduler()
|
||||
# 每30s记录一次
|
||||
scheduler.add_job(schedule_job, 'interval', [HOST, mcdb], seconds=30)
|
||||
|
||||
origins = [
|
||||
"*"
|
||||
]
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
scheduler.start()
|
||||
yield
|
||||
mcdb.cursor.close()
|
||||
mcdb.conn.close()
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=origins,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
try:
|
||||
status = await getJavaServerStatus(HOST)
|
||||
except Exception:
|
||||
return {
|
||||
"time": get_current_day_time_utc8(),
|
||||
"description": "请求错误",
|
||||
"latency": 10000,
|
||||
"max": "请求错误",
|
||||
"online": "请求错误"
|
||||
}
|
||||
|
||||
return {
|
||||
"time": get_current_day_time_utc8(),
|
||||
"description": status.description,
|
||||
"latency": round(status.latency, 2),
|
||||
"max": status.players.max,
|
||||
"online": status.players.online
|
||||
}
|
||||
|
||||
@app.get("/get_latency")
|
||||
async def get_latency_info():
|
||||
# 获取一个小时前的时间
|
||||
one_hour_ago = get_last_hour_date_info()
|
||||
mcdb.cursor.execute("SELECT time, latency FROM mcstatus WHERE time >= ?", (one_hour_ago, ))
|
||||
rows = mcdb.cursor.fetchall()
|
||||
|
||||
data = [{"time": parse_date_to_h_m_s(row[0]), "latency": row[1]} for row in rows]
|
||||
return data
|
||||
|
||||
|
||||
@app.post("/restart-server")
|
||||
async def restart_mc_server(password: Password):
|
||||
if PASSWORD != password.code:
|
||||
return {
|
||||
"status": "fail",
|
||||
"msg": "密码错误"
|
||||
}
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as asession:
|
||||
async with asession.post(RCON_SERVER,
|
||||
json={"code": password.code}) as resp1:
|
||||
result1 = await resp1.json()
|
||||
|
||||
return {
|
||||
"status": "成功",
|
||||
"msg": "重启指令已发送,请耐心等待1分钟,或者查看图表观察服务器是否正常上线"
|
||||
}
|
||||
except Exception:
|
||||
return {
|
||||
"status": "失败",
|
||||
"msg": "重启指令发送失败,请重试或者联系管理员"
|
||||
}
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(app, host="127.0.0.1", port=10000)
|
7
backend/requirements.txt
Normal file
7
backend/requirements.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
uvicorn[standard]
|
||||
fastapi
|
||||
mcstatus
|
||||
apscheduler
|
||||
pytz
|
||||
python-dateutil
|
||||
aiohttp
|
36
backend/utils.py
Normal file
36
backend/utils.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from mcstatus import JavaServer
|
||||
from mcstatus.status_response import JavaStatusResponse
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil import parser
|
||||
from pytz import timezone
|
||||
|
||||
from db import MCDB
|
||||
|
||||
async def getJavaServerStatus(host: str) -> JavaStatusResponse:
|
||||
return await (await JavaServer.async_lookup(host)).async_status()
|
||||
|
||||
async def getJavaServerLatency(host: str) -> float:
|
||||
status = await getJavaServerStatus(host)
|
||||
return status.latency
|
||||
|
||||
async def schedule_job(host: str, mcdb: MCDB):
|
||||
current_time = datetime.now(timezone("Asia/Shanghai"))
|
||||
try:
|
||||
latency = await getJavaServerLatency(host)
|
||||
except Exception as e:
|
||||
# 服务器连接失败,可能宕机了,把延迟设为10s秒
|
||||
latency = 10000
|
||||
print(e)
|
||||
mcdb.insert_time_and_latency(current_time, latency)
|
||||
|
||||
def get_last_hour_date_info():
|
||||
return (datetime.now(timezone("Asia/Shanghai")) - timedelta(hours=1))
|
||||
|
||||
def get_current_day_time_utc8():
|
||||
return datetime.now(timezone("Asia/Shanghai")).strftime('%H:%M:%S')
|
||||
|
||||
|
||||
def parse_date_to_h_m_s(timestamp_str) -> str:
|
||||
timestamp = parser.parse(timestamp_str)
|
||||
formatted_timestamp = timestamp.strftime("%H:%M:%S")
|
||||
return formatted_timestamp
|
5
config.json.example
Normal file
5
config.json.example
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"mc_host": "xxxxx.xxx.xxx:25565",
|
||||
"password": "xxxxxxxxxxxxxxx",
|
||||
"rcon_host": "http://127.0.0.1:10001"
|
||||
}
|
133
frontend/.gitignore
vendored
Normal file
133
frontend/.gitignore
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# parcel
|
||||
.parcel-cache
|
10
frontend/README.md
Normal file
10
frontend/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
## development
|
||||
```
|
||||
npm install
|
||||
npx parcel src/index.html
|
||||
```
|
||||
|
||||
## build
|
||||
```
|
||||
npx parcel build src/index.html
|
||||
```
|
3710
frontend/package-lock.json
generated
Normal file
3710
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
11
frontend/package.json
Normal file
11
frontend/package.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"@parcel/transformer-webmanifest": "^2.12.0",
|
||||
"parcel": "^2.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdui/icons": "^1.0.2",
|
||||
"chart.js": "^4.4.2",
|
||||
"mdui": "^2.0.6"
|
||||
}
|
||||
}
|
BIN
frontend/src/assets/mc.jpg
Normal file
BIN
frontend/src/assets/mc.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
26
frontend/src/index.html
Normal file
26
frontend/src/index.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<html lang="zh-CN" class="mdui-theme-auto">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<link rel="stylesheet" href="main.css">
|
||||
<script type="module" src="main.js"></script>
|
||||
<title>MC监控台</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main class="mdui-prose center">
|
||||
<h1>MC状态监测-No-Flesh-Within-Chest(脆骨症)</h1>
|
||||
<mdui-text-field autocomplete="on" readonly rows="5" id="server-status" helper="如果延迟等于10000,且下面图表是一条直线那大概率是服务器中断了"></mdui-text-field>
|
||||
<canvas id="latency-chart"></canvas>
|
||||
|
||||
<mdui-button id="restart-server-btn">重启服务器</mdui-button>
|
||||
<p>©BobMaster 2024</p>
|
||||
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
10
frontend/src/main.css
Normal file
10
frontend/src/main.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
body {
|
||||
display: flex;
|
||||
flex-flow: column wrap;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#restart-server-btn {
|
||||
margin-top: 5px;
|
||||
}
|
136
frontend/src/main.js
Normal file
136
frontend/src/main.js
Normal file
|
@ -0,0 +1,136 @@
|
|||
import 'mdui/mdui.css';
|
||||
import 'mdui/components/layout.js';
|
||||
import 'mdui/components/layout-item.js';
|
||||
import 'mdui/components/layout-main.js';
|
||||
import 'mdui/components/text-field.js';
|
||||
import 'mdui/components/button.js';
|
||||
import { prompt } from 'mdui/functions/prompt.js';
|
||||
import { dialog } from 'mdui/functions/dialog.js';
|
||||
import Chart from 'chart.js/auto';
|
||||
import '@mdui/icons/copyright.js';
|
||||
|
||||
|
||||
let ctx = document.getElementById("latency-chart").getContext('2d');
|
||||
let chart = new Chart(
|
||||
ctx,
|
||||
{
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [], // 存储时间信息
|
||||
datasets: [{
|
||||
label: '延迟信息',
|
||||
data: [], // 存储延迟信息
|
||||
backgroundColor: 'rgba(0, 123, 255, 0.5)',
|
||||
borderColor: 'rgba(0, 123, 255, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '延迟曲线图'
|
||||
},
|
||||
subtitle: {
|
||||
display: true,
|
||||
text: '单位: ms'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const restartBtn = document.getElementById("restart-server-btn")
|
||||
|
||||
window.onload = function () {
|
||||
fetch('http://127.0.0.1:10000/')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
let compose_string = "";
|
||||
compose_string += "当前时间: " + data.time;
|
||||
compose_string += "\n服务器描述: " + data.description;
|
||||
compose_string += "\n延迟: " + data.latency + "ms";
|
||||
compose_string += "\n最大玩家容量: " + data.max;
|
||||
compose_string += "\n当前在线人数: " + data.online;
|
||||
document.getElementById("server-status").value = compose_string;
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
fetch('http://127.0.0.1:10000/get_latency')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
for (let i = 0; i < data.length; i = i + 2) {
|
||||
chart.data.labels.push(data[i].time);
|
||||
chart.data.datasets[0].data.push(data[i].latency);
|
||||
}
|
||||
chart.update();
|
||||
});
|
||||
|
||||
|
||||
setInterval(function () {
|
||||
|
||||
fetch('http://127.0.0.1:10000')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
compose_string = "";
|
||||
compose_string += "当前时间: " + data.time;
|
||||
compose_string += "\n服务器描述: " + data.description;
|
||||
compose_string += "\n延迟: " + data.latency + "ms";
|
||||
compose_string += "\n最大玩家容量: " + data.max;
|
||||
compose_string += "\n当前在线人数: " + data.online;
|
||||
document.getElementById("server-status").value = compose_string;
|
||||
|
||||
// 添加新的数据到图表并更新
|
||||
chart.data.labels.push(data.time);
|
||||
chart.data.datasets[0].data.push(data.latency);
|
||||
if (chart.data.labels.length > 30) {
|
||||
chart.data.labels.shift();
|
||||
chart.data.datasets[0].data.shift();
|
||||
}
|
||||
chart.update();
|
||||
});
|
||||
}, 30 * 1000); // 每30s执行一次
|
||||
};
|
||||
|
||||
|
||||
|
||||
restartBtn.addEventListener("click", () => {
|
||||
prompt({
|
||||
headline: "请输入重置密码",
|
||||
confirmText: "OK",
|
||||
cancelText: "Cancel",
|
||||
closeOnEsc: true,
|
||||
onConfirm: (value) => {
|
||||
restartBtn.disabled = true;
|
||||
restartBtn.loading = true;
|
||||
fetch("http://127.0.0.1:10000/restart-server", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({"code": value})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
dialog({
|
||||
headline: "执行结果",
|
||||
description: data.status,
|
||||
body: data.msg,
|
||||
actions: [
|
||||
{
|
||||
"text": "了解",
|
||||
onClick: () => {
|
||||
restartBtn.disabled = false;
|
||||
restartBtn.loading = false;
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue