修改&汉化

pull/62/head
wuyuhanzijin 2024-08-17 14:51:53 +08:00
parent d576251057
commit 615fa075a3
11 changed files with 47 additions and 129 deletions

View File

@ -1,47 +0,0 @@
# ✔[UptimeFlare](https://github.com/lyc8503/UptimeFlare)
A more advanced, serverless, and free uptime monitoring & status page solution, powered by Cloudflare Workers, complete with a user-friendly interface.
## ⭐Features
- Open-source, easy to deploy (in under 10 minutes, no local tools required), and free
- Monitoring capabilities
- Up to 50 checks at 1-minute intervals
- Geo-specific checks from over [310 cities](https://www.cloudflare.com/network/) worldwide
- Support for HTTP/HTTPS/TCP port monitoring
- Up to 90-day uptime history and uptime percentage tracking
- Customizable request methods, headers, and body for HTTP(s)
- Custom status code & keyword checks for HTTP(s)
- Downtime notification supporting [100+ notification channels](https://github.com/caronc/apprise/wiki)
- Customizable Webhook
- Status page
- Interactive ping (response time) chart for all types of monitors
- Responsive UI that adapts to your system theme
- Customizable status page
- Use your own domain with CNAME
## 👀Demo
My status page (Online demo): https://uptimeflare.pages.dev/
Some screenshots:
![Desktop, Light theme](docs/desktop.png)
## ⚡Quickstart / 📄Documentation
Please refer to [Wiki](https://github.com/lyc8503/UptimeFlare/wiki)
## New features (TODOs)
- [x] Specify region for monitors
- [x] TCP `opened` promise
- [x] Use apprise to support various notification channels
- [x] ~~Telegram example~~
- [x] ~~[Bark](https://bark.day.app) example~~
- [x] ~~Email notification via Cloudflare Email Workers~~
- [x] Improve docs by providing simple examples
- [x] Notification grace period
- [ ] SSL certificate checks
- [ ] Self-host Dockerfile
- [ ] Incident timeline
- [x] Remove old incidents

View File

@ -49,7 +49,7 @@ export default function DetailBar({
key={i} key={i}
label={ label={
Number.isNaN(Number(dayPercent)) ? ( Number.isNaN(Number(dayPercent)) ? (
'No Data' '无数据'
) : ( ) : (
<> <>
<div>{dayPercent + '%'}</div> <div>{dayPercent + '%'}</div>

View File

@ -76,7 +76,7 @@ export default function DetailChart({
}, },
title: { title: {
display: true, display: true,
text: 'Response times(ms)', text: '响应时间(ms)',
align: 'start' as const, align: 'start' as const,
}, },
}, },

View File

@ -21,10 +21,7 @@ export default function Header() {
<header className={classes.header}> <header className={classes.header}>
<Container size="md" className={classes.inner}> <Container size="md" className={classes.inner}>
<div> <div>
<a href="https://github.com/lyc8503/UptimeFlare" target="_blank"> <a target="_blank">
<Text size="xl" span>
🕒
</Text>
<Text <Text
size="xl" size="xl"
span span
@ -32,7 +29,7 @@ export default function Header() {
variant="gradient" variant="gradient"
gradient={{ from: 'blue', to: 'cyan', deg: 90 }} gradient={{ from: 'blue', to: 'cyan', deg: 90 }}
> >
UptimeFlare ·LinYun
</Text> </Text>
</a> </a>
</div> </div>

View File

@ -19,11 +19,10 @@ export default function MonitorDetail({
{monitor.name} {monitor.name}
</Text> </Text>
<Text mt="sm" fw={700}> <Text mt="sm" fw={700}>
No data available, please make sure you have deployed your workers with latest config and 使WorkersWorkers
check your worker status!
</Text> </Text>
</> </>
) )Workers
const statusIcon = const statusIcon =
state.incident[monitor.id].slice(-1)[0].end === undefined ? ( state.incident[monitor.id].slice(-1)[0].end === undefined ? (
@ -65,7 +64,7 @@ export default function MonitorDetail({
)} )}
<Text mt="sm" fw={700} style={{ display: 'inline', color: getColor(uptimePercent, true) }}> <Text mt="sm" fw={700} style={{ display: 'inline', color: getColor(uptimePercent, true) }}>
Overall: {uptimePercent}% 线: {uptimePercent}%
</Text> </Text>
</div> </div>

View File

@ -29,14 +29,14 @@ export default function OverallStatus({
let statusString = '' let statusString = ''
let icon = <IconAlertCircle style={{ width: 64, height: 64, color: '#b91c1c' }} /> let icon = <IconAlertCircle style={{ width: 64, height: 64, color: '#b91c1c' }} />
if (state.overallUp === 0 && state.overallDown === 0) { if (state.overallUp === 0 && state.overallDown === 0) {
statusString = 'No data yet' statusString = '暂无数据'
} else if (state.overallUp === 0) { } else if (state.overallUp === 0) {
statusString = 'All systems not operational' statusString = '所有系统均未正常运转'
} else if (state.overallDown === 0) { } else if (state.overallDown === 0) {
statusString = 'All systems operational' statusString = '所有系统均正常运转'
icon = <IconCircleCheck style={{ width: 64, height: 64, color: '#059669' }} /> icon = <IconCircleCheck style={{ width: 64, height: 64, color: '#059669' }} />
} else { } else {
statusString = `Some systems not operational (${state.overallDown} out of ${state.overallUp + state.overallDown})` statusString = `部分系统未正常运转(${state.overallDown}个异常,共计${state.overallUp + state.overallDown}个)`
} }
const [openTime] = useState(Math.round(Date.now() / 1000)) const [openTime] = useState(Math.round(Date.now() / 1000))
@ -65,8 +65,8 @@ export default function OverallStatus({
{statusString} {statusString}
</Title> </Title>
<Title mt="sm" style={{ textAlign: 'center', color: '#70778c' }} order={5}> <Title mt="sm" style={{ textAlign: 'center', color: '#70778c' }} order={5}>
Last updated on:{' '} {' '}
{`${new Date(state.lastUpdate * 1000).toLocaleString()} (${currentTime - state.lastUpdate} sec ago)`} {`${new Date(state.lastUpdate * 1000).toLocaleString()} ${currentTime - state.lastUpdate} 秒之前)`}
</Title> </Title>
</> </>
) )

Binary file not shown.

Before

Width:  |  Height:  |  Size: 678 KiB

View File

@ -3,7 +3,7 @@ import { ColorSchemeScript } from '@mantine/core'
export default function Document() { export default function Document() {
return ( return (
<Html lang="en"> <Html lang="zh-CN">
<Head> <Head>
<ColorSchemeScript defaultColorScheme="auto" /> <ColorSchemeScript defaultColorScheme="auto" />
</Head> </Head>

View File

@ -73,19 +73,23 @@ export default function Home({
<Text size="xs" mt="xs" mb="xs" style={{ <Text size="xs" mt="xs" mb="xs" style={{
textAlign: 'center' textAlign: 'center'
}}> }}>
Open-source monitoring and status page powered by{' '} {' '}
<a href="https://github.com/lyc8503/UptimeFlare" target="_blank"> <a href="https://github.com/lyc8503/UptimeFlare" target="_blank">
Uptimeflare Uptimeflare
</a>{' '} </a>{' '}
and{' '} {' '}
<a href="https://www.cloudflare.com/" target="_blank"> <a href="https://www.cloudflare.com/" target="_blank">
Cloudflare Cloudflare
</a> </a>
, made with by{' '} {' '}
<a href="https://github.com/lyc8503" target="_blank"> <a href="https://github.com/lyc8503" target="_blank">
lyc8503 lyc8503
</a> </a>
. {' '}
<a href="https://github.com/wuyuhanzijin" target="_blank">
wuyuhanzijin
</a>
</Text> </Text>
</main> </main>
</> </>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,77 +1,42 @@
const pageConfig = { const pageConfig = {
// Title for your status page title: "凌云·LinYun 服务状态",
title: "lyc8503's Status Page",
// Links shown at the header of your status page, could set `highlight` to `true`
links: [ links: [
{ link: 'https://github.com/lyc8503', label: 'GitHub' }, { link: 'https://www.linyunlink.top/links/', label: '友情链接'},
{ link: 'https://blog.lyc8503.net/', label: 'Blog' }, { link: 'https://www.linyunlink.top/', label: '博客', highlight: true },
{ link: 'mailto:me@lyc8503.net', label: 'Email Me', highlight: true },
], ],
} }
const workerConfig = { const workerConfig = {
// Write KV at most every 3 minutes unless the status changed. // Write KV at most every 3 minutes unless the status changed.
kvWriteCooldownMinutes: 3, kvWriteCooldownMinutes: 10,
// Define all your monitors here // Define all your monitors here
monitors: [ monitors: [
// Example HTTP Monitor // ==========[凌云服务监控]==========
{ {
// `id` should be unique, history will be kept if the `id` remains constant id: 'linyun_blog_monitor',
id: 'foo_monitor', name: '凌云·LinYun 博客',
// `name` is used at status page and callback message method: 'GET',
name: 'My API Monitor', target: 'https://www.linyunlink.top/',
// `method` should be a valid HTTP Method tooltip: '凌云·LinYun 博客',
statusPageLink: 'https://www.linyunlink.top/',
},
{
id: 'linyun_twikoo_monitor',
name: '凌云·LinYun Twikoo评论系统',
method: 'POST', method: 'POST',
// `target` is a valid URL target: 'https://twikoo.linyunlink.top/',
target: 'https://example.com', tooltip: '凌云·LinYun Twikoo 评论服务后端',
// [OPTIONAL] `tooltip` is ONLY used at status page to show a tooltip statusPageLink: 'https://twikoo.linyunlink.top/',
tooltip: 'This is a tooltip for this monitor',
// [OPTIONAL] `statusPageLink` is ONLY used for clickable link at status page
statusPageLink: 'https://example.com',
// [OPTIONAL] `expectedCodes` is an array of acceptable HTTP response codes, if not specified, default to 2xx
expectedCodes: [200],
// [OPTIONAL] `timeout` in millisecond, if not specified, default to 10000
timeout: 10000,
// [OPTIONAL] headers to be sent
headers: {
'User-Agent': 'Uptimeflare',
Authorization: 'Bearer YOUR_TOKEN_HERE',
},
// [OPTIONAL] body to be sent
body: 'Hello, world!',
// [OPTIONAL] if specified, the response must contains the keyword to be considered as operational.
responseKeyword: 'success',
// [OPTIONAL] if specified, the check will run in your specified region,
// refer to docs https://github.com/lyc8503/UptimeFlare/wiki/Geo-specific-checks-setup before setting this value
checkLocationWorkerRoute: 'https://xxx.example.com',
}, },
// Example TCP Monitor
{ {
id: 'test_tcp_monitor', id: 'linyun_image_monitor',
name: 'Example TCP Monitor', name: '凌云·LinYun 图片托管站',
// `method` should be `TCP_PING` for tcp monitors method: 'GET',
method: 'TCP_PING', target: 'https://image.linyunlink.top/',
// `target` should be `host:port` for tcp monitors tooltip: '凌云·LinYun 图片托管站',
target: '1.2.3.4:22', statusPageLink: 'https://image.linyunlink.top/',
tooltip: 'My production server SSH', }
statusPageLink: 'https://example.com',
timeout: 5000,
},
], ],
notification: {
// [Optional] apprise API server URL
// if not specified, no notification will be sent
appriseApiServer: "https://apprise.example.com/notify",
// [Optional] recipient URL for apprise, refer to https://github.com/caronc/apprise
// if not specified, no notification will be sent
recipientUrl: "tgram://bottoken/ChatID",
// [Optional] timezone used in notification messages, default to "Etc/GMT"
timeZone: "Asia/Shanghai",
// [Optional] grace period in minutes before sending a notification
// notification will be sent only if the monitor is down for N continuous checks after the initial failure
// if not specified, notification will be sent immediately
gracePeriod: 5,
},
callbacks: { callbacks: {
onStatusChange: async ( onStatusChange: async (
env: any, env: any,