mirror of https://github.com/yb/uptime-status
"更新 uptime-status 为 jj-status,增加新依赖和功能
- 重命名项目从 uptime-status 到 jj-status。 - 添加 react-simple-typewriter 依赖,引入打字机效果。 - 更新相关配置文件和代码,适应新依赖和特性。 - 增加博客链接和云助手导航,移除旧的 Homepage 和 GitHub 导航。 - 引入每日一言(hitokoto)功能。 - 调整样式变量和组件pull/55/head
parent
bb67f7f2a7
commit
3fad902619
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "uptime-status",
|
||||
"name": "jj-status",
|
||||
"version": "2.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "uptime-status",
|
||||
"name": "jj-status",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@ -14,6 +14,7 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-simple-typewriter": "^5.0.1",
|
||||
"react-tooltip": "^4.2.21",
|
||||
"sass": "^1.53.0"
|
||||
}
|
||||
|
@ -13538,6 +13539,18 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-simple-typewriter": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/react-simple-typewriter/-/react-simple-typewriter-5.0.1.tgz",
|
||||
"integrity": "sha512-vA5HkABwJKL/DJ4RshSlY/igdr+FiVY4MLsSQYJX6FZG/f1/VwN4y1i3mPXRyfaswrvI8xii1kOVe1dYtO2Row==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-tooltip": {
|
||||
"version": "4.2.21",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz",
|
||||
|
@ -25752,6 +25765,12 @@
|
|||
"workbox-webpack-plugin": "^6.4.1"
|
||||
}
|
||||
},
|
||||
"react-simple-typewriter": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/react-simple-typewriter/-/react-simple-typewriter-5.0.1.tgz",
|
||||
"integrity": "sha512-vA5HkABwJKL/DJ4RshSlY/igdr+FiVY4MLsSQYJX6FZG/f1/VwN4y1i3mPXRyfaswrvI8xii1kOVe1dYtO2Row==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-tooltip": {
|
||||
"version": "4.2.21",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "uptime-status",
|
||||
"name": "jj-status",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
@ -12,6 +12,7 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-simple-typewriter": "^5.0.1",
|
||||
"react-tooltip": "^4.2.21",
|
||||
"sass": "^1.53.0"
|
||||
},
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
window.Config = {
|
||||
|
||||
// 显示标题
|
||||
SiteName: 'Public Status',
|
||||
SiteName: '站点检测',
|
||||
|
||||
// UptimeRobot Api Keys
|
||||
// 支持 Monitor-Specific 和 Read-Only
|
||||
ApiKeys: [
|
||||
'm784488775-dd1ad84b209c05f8e185c33e',
|
||||
'm784490063-7b5da437e7f1e0d67613714d',
|
||||
'm784497419-de55aa09902ccb3ab22d548a',
|
||||
'm784496436-71a4bf7b1e3bdf7756be131b',
|
||||
'ur2648744-49ccec99d7a4ea70c9e441f3'
|
||||
],
|
||||
|
||||
// 日志天数
|
||||
|
@ -21,16 +18,17 @@ window.Config = {
|
|||
// 导航栏菜单
|
||||
Navi: [
|
||||
{
|
||||
text: 'Homepage',
|
||||
url: 'https://status.org.cn/'
|
||||
text: 'Blog',
|
||||
url: 'https://wzue.cn/'
|
||||
},
|
||||
{
|
||||
text: '云助手',
|
||||
url: 'https://mz.wzue.cn/'
|
||||
},
|
||||
{
|
||||
text: 'GitHub',
|
||||
url: 'https://github.com/yb/uptime-status'
|
||||
},
|
||||
{
|
||||
text: 'Blog',
|
||||
url: 'https://abo.xyz/'
|
||||
url: 'https://github.com/9075512'
|
||||
},
|
||||
|
||||
],
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||||
<title>Uptime Status</title>
|
||||
<script src="./config.js"></script>
|
||||
<!-- 本例不能添加链接内容,放在此处只是因为此接口比较方便,也许能够解决大部分的需求-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
|
10
src/app.scss
10
src/app.scss
|
@ -27,7 +27,7 @@ a {
|
|||
}
|
||||
|
||||
#header {
|
||||
background-color: #121a26;
|
||||
background-color: $primary-color;
|
||||
padding: 30px 0 60px 0;
|
||||
color: $primary-color;
|
||||
width: 100%;
|
||||
|
@ -39,6 +39,7 @@ a {
|
|||
.logo {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
.navi {
|
||||
font-size: 14px;
|
||||
|
@ -48,7 +49,7 @@ a {
|
|||
transition: color ease 150ms;
|
||||
}
|
||||
a:hover {
|
||||
color: $primary-color;
|
||||
// color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,4 +171,9 @@ a {
|
|||
font-weight: bold;
|
||||
color: $primary-color;
|
||||
}
|
||||
.hitokoto{
|
||||
font-weight: bold;
|
||||
color: $primary-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import axios from 'axios';
|
||||
|
||||
export async function GetHitokoto() {
|
||||
const response = await axios.get('https://v1.hitokoto.cn');
|
||||
return response;
|
||||
}
|
|
@ -1,30 +1,54 @@
|
|||
import { useMemo } from 'react';
|
||||
import Link from './link';
|
||||
import Header from './header';
|
||||
import UptimeRobot from './uptimerobot';
|
||||
import Package from '../../package.json';
|
||||
import { useMemo } from "react";
|
||||
import Link from "./link";
|
||||
import Header from "./header";
|
||||
import UptimeRobot from "./uptimerobot";
|
||||
import Package from "../../package.json";
|
||||
import { GetHitokoto } from "../common/hitokoto";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Typewriter } from 'react-simple-typewriter'
|
||||
|
||||
function App() {
|
||||
|
||||
const apikeys = useMemo(() => {
|
||||
const { ApiKeys } = window.Config;
|
||||
if (Array.isArray(ApiKeys)) return ApiKeys;
|
||||
if (typeof ApiKeys === 'string') return [ApiKeys];
|
||||
if (typeof ApiKeys === "string") return [ApiKeys];
|
||||
return [];
|
||||
}, []);
|
||||
|
||||
const [hitokoto, setHitokoto] = useState(['结局是什么,我们自己决定!']);
|
||||
|
||||
function getText() {
|
||||
GetHitokoto().then(({ data }) => {
|
||||
setHitokoto([...hitokoto,data.hitokoto]);
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getText();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<div className='container'>
|
||||
<div id='uptime'>
|
||||
<div className="container">
|
||||
<div id="uptime">
|
||||
{apikeys.map((key) => (
|
||||
<UptimeRobot key={key} apikey={key} />
|
||||
))}
|
||||
</div>
|
||||
<div id='footer'>
|
||||
<p>基于 <Link to='https://uptimerobot.com/' text='UptimeRobot' /> 接口制作,检测频率 5 分钟</p>
|
||||
<p>© 2020 <Link to='https://status.org.cn/' text='STATUS.ORG.CN' />, Version {Package.version}</p>
|
||||
<div id="footer">
|
||||
<p className="hitokoto">
|
||||
<Typewriter cursor="true" delaySpeed="6000" cursorStyle="⚡" words={hitokoto} onDelay={getText}/>
|
||||
</p>
|
||||
<p>
|
||||
基于 <Link to="https://uptimerobot.com/" text="UptimeRobot" />{" "}
|
||||
接口制作,检测频率 5 分钟
|
||||
</p>
|
||||
<p>
|
||||
© 2020{" "}
|
||||
<Link to="https://status.wzue.cn/" text="STATUS.WZUE.CN" />, Version{" "}
|
||||
{Package.version}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import ReactTooltip from 'react-tooltip';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { GetMonitors } from '../common/uptimerobot';
|
||||
import { formatDuration, formatNumber } from '../common/helper';
|
||||
import Link from './link';
|
||||
import ReactTooltip from "react-tooltip";
|
||||
import { useEffect, useState } from "react";
|
||||
import { GetMonitors } from "../common/uptimerobot";
|
||||
import { formatDuration, formatNumber } from "../common/helper";
|
||||
import Link from "./link";
|
||||
|
||||
function UptimeRobot({ apikey }) {
|
||||
|
||||
const status = {
|
||||
ok: '正常',
|
||||
down: '无法访问',
|
||||
unknow: '未知'
|
||||
ok: "正常",
|
||||
down: "无法访问",
|
||||
unknow: "未知",
|
||||
};
|
||||
|
||||
const { CountDays, ShowLink } = window.Config;
|
||||
|
@ -20,50 +19,65 @@ function UptimeRobot({ apikey }) {
|
|||
GetMonitors(apikey, CountDays).then(setMonitors);
|
||||
}, [apikey, CountDays]);
|
||||
|
||||
if (monitors) return monitors.map((site) => (
|
||||
<div key={site.id} className='site'>
|
||||
<div className='meta'>
|
||||
<span className='name' dangerouslySetInnerHTML={{ __html: site.name }} />
|
||||
{ShowLink && <Link className='link' to={site.url} text={site.name} />}
|
||||
<span className={'status ' + site.status}>{status[site.status]}</span>
|
||||
if (monitors)
|
||||
return monitors.map((site) => (
|
||||
<div key={site.id} className="site">
|
||||
<div className="meta">
|
||||
<span
|
||||
className="name"
|
||||
dangerouslySetInnerHTML={{ __html: site.name }}
|
||||
/>
|
||||
{ShowLink && <Link className="link" to={site.url} text={site.name} />}
|
||||
<span className={"status " + site.status}>{status[site.status]}</span>
|
||||
</div>
|
||||
<div className="timeline">
|
||||
{site.daily.map((data, index) => {
|
||||
let status = "";
|
||||
let text = data.date.format("YYYY-MM-DD ");
|
||||
if (data.uptime >= 100) {
|
||||
status = "ok";
|
||||
text += `可用率 ${formatNumber(data.uptime)}%`;
|
||||
} else if (data.uptime <= 0 && data.down.times === 0) {
|
||||
status = "none";
|
||||
text += "无数据";
|
||||
} else {
|
||||
status = "down";
|
||||
text += `故障 ${data.down.times} 次,累计 ${formatDuration(
|
||||
data.down.duration
|
||||
)},可用率 ${formatNumber(data.uptime)}%`;
|
||||
}
|
||||
return <i key={index} className={status} data-tip={text} />;
|
||||
})}
|
||||
</div>
|
||||
<div className="summary">
|
||||
<span>今天</span>
|
||||
<span>
|
||||
{site.total.times
|
||||
? `最近 ${CountDays} 天故障 ${
|
||||
site.total.times
|
||||
} 次,累计 ${formatDuration(site.total.duration)},平均可用率 ${
|
||||
site.average
|
||||
}%`
|
||||
: `最近 ${CountDays} 天可用率 ${site.average}%`}
|
||||
</span>
|
||||
<span>
|
||||
{site.daily[site.daily.length - 1].date.format("YYYY-MM-DD")}
|
||||
</span>
|
||||
</div>
|
||||
<ReactTooltip
|
||||
className="tooltip"
|
||||
place="top"
|
||||
type="dark"
|
||||
effect="solid"
|
||||
/>
|
||||
</div>
|
||||
<div className='timeline'>
|
||||
{site.daily.map((data, index) => {
|
||||
let status = '';
|
||||
let text = data.date.format('YYYY-MM-DD ');
|
||||
if (data.uptime >= 100) {
|
||||
status = 'ok';
|
||||
text += `可用率 ${formatNumber(data.uptime)}%`;
|
||||
}
|
||||
else if (data.uptime <= 0 && data.down.times === 0) {
|
||||
status = 'none';
|
||||
text += '无数据';
|
||||
}
|
||||
else {
|
||||
status = 'down';
|
||||
text += `故障 ${data.down.times} 次,累计 ${formatDuration(data.down.duration)},可用率 ${formatNumber(data.uptime)}%`;
|
||||
}
|
||||
return (<i key={index} className={status} data-tip={text} />)
|
||||
})}
|
||||
));
|
||||
else
|
||||
return (
|
||||
<div className="site">
|
||||
<div className="loading" />
|
||||
</div>
|
||||
<div className='summary'>
|
||||
<span>今天</span>
|
||||
<span>
|
||||
{site.total.times
|
||||
? `最近 ${CountDays} 天故障 ${site.total.times} 次,累计 ${formatDuration(site.total.duration)},平均可用率 ${site.average}%`
|
||||
: `最近 ${CountDays} 天可用率 ${site.average}%`}
|
||||
</span>
|
||||
<span>{site.daily[site.daily.length - 1].date.format('YYYY-MM-DD')}</span>
|
||||
</div>
|
||||
<ReactTooltip className='tooltip' place='top' type='dark' effect='solid' />
|
||||
</div>
|
||||
));
|
||||
|
||||
else return (
|
||||
<div className='site'>
|
||||
<div className='loading' />
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
export default UptimeRobot;
|
||||
|
|
Loading…
Reference in New Issue