✨ 新版状态页面
19
liteyuki/resources/vanilla_resource/templates/css/card.css
Normal file
@ -0,0 +1,19 @@
|
||||
.data-storage {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background-repeat: repeat-y;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-shadow: 1px 1px 2px black;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 30px;
|
||||
padding: 30px;
|
||||
backdrop-filter: blur(10px);
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
margin-bottom: 20px;
|
||||
}
|
76
liteyuki/resources/vanilla_resource/templates/css/fonts.css
Normal file
@ -0,0 +1,76 @@
|
||||
/*MiSans*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'MiSans';
|
||||
src: url('../fonts/MiSans/MiSans-Light.woff2') format('woff2');
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MiSans';
|
||||
src: url('../fonts/MiSans/MiSans-Normal.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MiSans';
|
||||
src: url('../fonts/MiSans/MiSans-Semibold.woff2') format('woff2');
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MiSans';
|
||||
src: url('../fonts/MiSans/MiSans-Bold.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MiSans';
|
||||
src: url('../fonts/MiSans/MiSans-Heavy.woff2') format('woff2');
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
/*MapleMono*/
|
||||
@font-face {
|
||||
font-family: 'MapleMono';
|
||||
src: url('../fonts/MapleMono/MapleMono-Light.woff2') format('woff2');
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MapleMono';
|
||||
src: url('../fonts/MapleMono/MapleMono-LightItalic.woff2') format('woff2');
|
||||
font-weight: 200;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'MapleMono';
|
||||
src: url('../fonts/MapleMono/MapleMono-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MapleMono';
|
||||
src: url('../fonts/MapleMono/MapleMono-Italic.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MapleMono';
|
||||
src: url('../fonts/MapleMono/MapleMono-Bold.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MapleMono';
|
||||
src: url('../fonts/MapleMono/MapleMono-BoldItalic.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: 'MapleMono', 'MiSans', sans-serif;
|
||||
}
|
130
liteyuki/resources/vanilla_resource/templates/css/status.css
Normal file
@ -0,0 +1,130 @@
|
||||
:root {
|
||||
--main-text-color: #fff;
|
||||
--sub-text-color: #bbb;
|
||||
--tip-text-color: #888;
|
||||
|
||||
--device-info-width: 240px;
|
||||
}
|
||||
|
||||
.bot-info {
|
||||
display: flex;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.bot-icon {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
aspect-ratio: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.bot-icon-img {
|
||||
border-radius: 50%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.bot-name {
|
||||
color: var(--main-text-color);
|
||||
display: flex;
|
||||
font-size: 40px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.bot-tag {
|
||||
white-space: nowrap;
|
||||
color: var(--sub-text-color);
|
||||
font-size: 27px;
|
||||
font-weight: 700;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.bot-tag[suffix="1"]::after {
|
||||
content: " | ";
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
height: 30%;
|
||||
line-height: 50%;
|
||||
color: var(--tip-text-color);
|
||||
}
|
||||
|
||||
/*修改bot-info 下hr样式*/
|
||||
.bot-info hr {
|
||||
border: 0;
|
||||
height: 4px;
|
||||
background: var(--tip-text-color);
|
||||
margin: 10px 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#hardware-info {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.device-info {
|
||||
max-width: 30%;
|
||||
}
|
||||
|
||||
.device-chart {
|
||||
display: flex;
|
||||
height: var(--device-info-width);
|
||||
width: var(--device-info-width);
|
||||
margin-bottom: 20px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.device-tags {
|
||||
text-align: center;
|
||||
color: var(--sub-text-color);
|
||||
font-size: 24px;
|
||||
max-width: var(--device-info-width);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.disk-info {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background-color: #ffffff44;
|
||||
border-radius: 30px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.disk-usage {
|
||||
background-color: #a2d8f4;
|
||||
height: 100%;
|
||||
border-radius: 30px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.disk-title {
|
||||
position: absolute;
|
||||
color: var(--main-text-color);
|
||||
font-size: 24px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 20px;
|
||||
text-align: left;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#motto-text {
|
||||
font-size: 36px;
|
||||
word-wrap: break-word;
|
||||
color: var(--main-text-color);
|
||||
text-align: center;
|
||||
margin: 30px 0 10px 0;
|
||||
}
|
||||
|
||||
#motto-from {
|
||||
font-size: 24px;
|
||||
font-style: italic;
|
||||
color: var(--sub-text-color);
|
||||
text-align: right;
|
||||
}
|
101
liteyuki/resources/vanilla_resource/templates/css/style.css
Normal file
@ -0,0 +1,101 @@
|
||||
body {
|
||||
background-repeat: repeat-y;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
color: white;
|
||||
/ / 上10px,左右10px,下0px / / margin: 24 px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 30px;
|
||||
padding: 30px;
|
||||
backdrop-filter: blur(10px);
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
height: 240px;
|
||||
width: 240px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.pie-info {
|
||||
margin: 0 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bot-info {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#hardware-info {
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#disks-info {
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
#motto-info {
|
||||
margin-bottom: 0;
|
||||
text-align: center;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.bot-icon {
|
||||
border-radius: 50%;
|
||||
height: 200px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.bot-name, .bot-tag {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.bot-name {
|
||||
font-size: 42px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.bot-tag {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.chart-label {
|
||||
font-size: 24px;
|
||||
max-width: 240px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.tag[suffix="1"]::after {
|
||||
content: " | ";
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
height: 50%;
|
||||
line-height: 50%;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.motto-text {
|
||||
font-size: 36px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.motto-author {
|
||||
font-size: 30px;
|
||||
font-style: italic;
|
||||
color: #ccc;
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
#weather-info {
|
||||
color: white;
|
||||
/*justify-content: center;*/
|
||||
/*align-items: center;*/
|
||||
/*align-content: center;*/
|
||||
}
|
||||
|
||||
#main-info {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#time {
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
color: #aaa;
|
||||
|
||||
}
|
||||
|
||||
#adm {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
#city {
|
||||
margin-top: 20px;
|
||||
font-size: 70px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#temperature {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
}
|
||||
|
||||
#temperature-now {
|
||||
font-size: 70px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#temperature-range {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
#description {
|
||||
font-size: 50px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
#aqi {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
border-radius: 60px;
|
||||
padding: 5px;
|
||||
font-size: 40px;
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#aqi-dot {
|
||||
height: 80%;
|
||||
aspect-ratio: 1 / 1;
|
||||
border-radius: 50%;
|
||||
background-color: #aaa;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.main-icon {
|
||||
width: 240px;
|
||||
height: 240px;
|
||||
}
|
BIN
liteyuki/resources/vanilla_resource/templates/favicon.ico
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/bg1.png
Normal file
After Width: | Height: | Size: 9.1 MiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/bg3.png
Normal file
After Width: | Height: | Size: 5.1 MiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/bg4.png
Normal file
After Width: | Height: | Size: 5.4 MiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/bg5.png
Normal file
After Width: | Height: | Size: 5.4 MiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/bg6.png
Normal file
After Width: | Height: | Size: 3.8 MiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/bg7.png
Normal file
After Width: | Height: | Size: 2.9 MiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/bg9.png
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
liteyuki/resources/vanilla_resource/templates/img/liteyuki.png
Normal file
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 6.3 KiB |
11
liteyuki/resources/vanilla_resource/templates/js/card.js
Normal file
@ -0,0 +1,11 @@
|
||||
const bgs = [
|
||||
"bg1.png",
|
||||
"bg3.png",
|
||||
"bg4.png",
|
||||
"bg5.png",
|
||||
"bg6.png",
|
||||
"bg7.png",
|
||||
"bg9.png",
|
||||
]
|
||||
// 随机选择背景图片
|
||||
document.body.style.backgroundImage = `url(./img/${bgs[Math.floor(Math.random() * bgs.length)]})`;
|
113
liteyuki/resources/vanilla_resource/templates/js/motto.js
Normal file
@ -0,0 +1,113 @@
|
||||
// 存放格言
|
||||
const mottos = [
|
||||
{
|
||||
"text": "同是天涯沦落人,相逢何必曾相识。",
|
||||
"author": "白居易",
|
||||
"source": "《琵琶行》"
|
||||
},
|
||||
{
|
||||
"text": "海内存知己,天涯若比邻。",
|
||||
"author": "王勃",
|
||||
"source": "《送杜少府之任蜀州》"
|
||||
},
|
||||
{
|
||||
"text": "银烛秋光冷画屏,轻罗小扇扑流萤。",
|
||||
"author": "陆游",
|
||||
"source": "《秋夕》"
|
||||
},
|
||||
{
|
||||
"text": "明月几时有,把酒问青天。",
|
||||
"author": "苏轼",
|
||||
"source": "《水调歌头》"
|
||||
},
|
||||
{
|
||||
"text": "人生自古谁无死,留取丹心照汗青。",
|
||||
"author": "文天祥",
|
||||
"source": "《过零丁洋》"
|
||||
},
|
||||
{
|
||||
"text": "山重水复疑无路,柳暗花明又一村。",
|
||||
"author": "陆游",
|
||||
"source": "《游山西村》"
|
||||
},
|
||||
{
|
||||
"text": "逸一时,误一世,逸久逸久罢已龄",
|
||||
"author": "田所浩二",
|
||||
"source": "《仲夏夜之淫梦》"
|
||||
},
|
||||
{
|
||||
"text": "你知道吗,轻雪只能在Python3.10以上的版本中使用。",
|
||||
"author": "SnowyKami",
|
||||
"source": "轻雪文档"
|
||||
},
|
||||
{
|
||||
"text": "你知道吗,轻雪可以通过自定义资源包来扩展主题和语言",
|
||||
"author": "SnowyKami",
|
||||
"source": "轻雪文档"
|
||||
},
|
||||
{
|
||||
"text": "你知道吗,轻雪交流群的群号是 775840726",
|
||||
"author": "SnowyKami",
|
||||
"source": "轻雪文档"
|
||||
},
|
||||
{
|
||||
"text": "你知道吗,轻雪运行过程中会启动一个node.js运行环境",
|
||||
"author": "SnowyKami",
|
||||
"source": "轻雪文档"
|
||||
},
|
||||
{
|
||||
"text": "你知道吗,轻雪的主题是基于HTML5开发的",
|
||||
"author": "SnowyKami",
|
||||
"source": "轻雪文档"
|
||||
},
|
||||
{
|
||||
"text": "路漫漫其修远兮,吾将上下而求索。",
|
||||
"author": "屈原",
|
||||
"source": "《离骚》"
|
||||
},
|
||||
{
|
||||
"text": "千里之行,始于足下。",
|
||||
"author": "老子",
|
||||
"source": "《道德经》"
|
||||
},
|
||||
{
|
||||
"text": "读书破万卷,下笔如有神。",
|
||||
"author": "杜甫",
|
||||
"source": "《奉赠韦左丞丈二十韵》"
|
||||
},
|
||||
{
|
||||
"text": "不登高山,不知天之高也;不临深溪,不知地之厚也。",
|
||||
"author": "荀子",
|
||||
"source": "《劝学》"
|
||||
},
|
||||
{
|
||||
"text": "知之者不如好之者,好之者不如乐之者。",
|
||||
"author": "孔子",
|
||||
"source": "《论语》"
|
||||
},
|
||||
{
|
||||
"text": "天行健,君子以自强不息;地势坤,君子以厚德载物。",
|
||||
"source": "《易经》",
|
||||
"author": ""
|
||||
},
|
||||
{
|
||||
"text": "书山有路勤为径,学海无涯苦作舟。",
|
||||
"author": "韩愈",
|
||||
"source": "《读书有感》"
|
||||
},
|
||||
{
|
||||
"text": "前事不忘,后事之师。",
|
||||
"author": "孔子",
|
||||
"source": "《论语》"
|
||||
},
|
||||
{
|
||||
"text": "志当存高远,若樽俎断绝。",
|
||||
"author": "陶渊明",
|
||||
"source": "《饮酒》"
|
||||
},
|
||||
{
|
||||
"text": "不以物喜,不以己悲。",
|
||||
"author": "傅子",
|
||||
"source": "《傅子》"
|
||||
}
|
||||
]
|
295
liteyuki/resources/vanilla_resource/templates/js/status.js
Normal file
@ -0,0 +1,295 @@
|
||||
const data = JSON.parse(document.getElementById('data').innerText);
|
||||
const bot_data = data['bot']; // 机器人数据
|
||||
const hardwareData = data['hardware']; // 硬件数据
|
||||
const liteyukiData = data['liteyuki']; // LiteYuki数据
|
||||
const localData = data['localization']; // 本地化语言数据
|
||||
|
||||
/**
|
||||
* 创建CPU/内存/交换饼图
|
||||
* @param title
|
||||
* @param {Array<{name: string, value: number}>} data 数据
|
||||
*/
|
||||
function createPieChartOption(title, data) {
|
||||
// data为各项占比列表
|
||||
return {
|
||||
animation: false,
|
||||
title: {
|
||||
text: title,
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 30,
|
||||
lineHeight: 36
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'item',
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
color: data.length === 3 ? ['#00a6ff', '#a2d8f4', "#ffffff44"] : ['#a2d8f4', '#ffffff44'],
|
||||
series: [
|
||||
{
|
||||
name: 'info',
|
||||
type: 'pie',
|
||||
radius: ['80%', '100%'],
|
||||
center: ['50%', '50%'],
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: false
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
fontSize: '50',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: data
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function convertSize(size, precision = 2, addUnit = true, suffix = " XiB") {
|
||||
let isNegative = size < 0;
|
||||
size = Math.abs(size);
|
||||
let units = ["", "K", "M", "G", "T", "P", "E", "Z"];
|
||||
let unit = "";
|
||||
|
||||
for (let i = 0; i < units.length; i++) {
|
||||
if (size < 1024) {
|
||||
unit = units[i];
|
||||
break;
|
||||
}
|
||||
size /= 1024;
|
||||
}
|
||||
|
||||
if (isNegative) {
|
||||
size = -size;
|
||||
}
|
||||
|
||||
if (addUnit) {
|
||||
return size.toFixed(precision) + suffix.replace('X', unit);
|
||||
} else {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建磁盘用量柱状图
|
||||
* @param title
|
||||
* @param percent 数据
|
||||
*/
|
||||
function createBarChart(title, percent) {
|
||||
// percent为百分比,最大值为100
|
||||
let diskDiv = document.createElement('div')
|
||||
diskDiv.setAttribute('class', 'disk-info')
|
||||
diskDiv.style.marginBottom = '20px'
|
||||
diskDiv.innerHTML = `
|
||||
<div class="disk-title">${title}</div>
|
||||
<div class="disk-usage" style="width: ${percent}%"></div>
|
||||
`
|
||||
|
||||
return diskDiv
|
||||
}
|
||||
|
||||
function secondsToTextTime(seconds) {
|
||||
let days = Math.floor(seconds / 86400)
|
||||
let hours = Math.floor((seconds % 86400) / 3600)
|
||||
let minutes = Math.floor((seconds % 3600) / 60)
|
||||
let seconds_ = Math.floor(seconds % 60)
|
||||
return `${days}${localData['days']} ${hours}${localData['hours']} ${minutes}${localData['minutes']} ${seconds_}${localData['seconds']}`
|
||||
}
|
||||
|
||||
// 主函数
|
||||
function main() {
|
||||
// 添加机器人信息
|
||||
bot_data['bots'].forEach(
|
||||
(bot) => {
|
||||
let botInfoDiv = document.importNode(document.getElementById('bot-template').content, true) // 复制模板
|
||||
|
||||
|
||||
// 设置机器人信息
|
||||
botInfoDiv.className = 'info-box bot-info'
|
||||
|
||||
botInfoDiv.querySelector('.bot-icon-img').setAttribute('src', bot['icon'])
|
||||
botInfoDiv.querySelector('.bot-name').innerText = bot['name']
|
||||
let tagArray = [
|
||||
bot['protocol_name'],
|
||||
bot['app_name'],
|
||||
`${localData['groups']} ${bot['groups']}`,
|
||||
`${localData['friends']} ${bot['friends']}`,
|
||||
`${localData['message_sent']} ${bot['message_sent']}`,
|
||||
`${localData['message_received']} ${bot['message_received']}`,
|
||||
]
|
||||
// 添加一些标签
|
||||
tagArray.forEach(
|
||||
(tag, index) => {
|
||||
let tagSpan = document.createElement('span')
|
||||
tagSpan.className = 'bot-tag'
|
||||
tagSpan.innerText = tag
|
||||
// 给最后一个标签不添加后缀
|
||||
tagSpan.setAttribute('suffix', index === tagArray.length - 1 ? '0' : '1')
|
||||
botInfoDiv.querySelector('.bot-tags').appendChild(tagSpan)
|
||||
}
|
||||
)
|
||||
document.body.insertBefore(botInfoDiv, document.getElementById('hardware-info')) // 插入对象
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
// 添加轻雪信息
|
||||
let liteyukiInfoDiv = document.importNode(document.getElementById('bot-template').content, true) // 复制模板
|
||||
liteyukiInfoDiv.className = 'info-box bot-info'
|
||||
liteyukiInfoDiv.querySelector('.bot-icon-img').setAttribute('src', './img/liteyuki.png')
|
||||
liteyukiInfoDiv.querySelector('.bot-name').innerText = liteyukiData['name']
|
||||
|
||||
let tagArray = [
|
||||
`Liteyuki ${liteyukiData['version']}`,
|
||||
`Nonebot ${liteyukiData['nonebot']}`,
|
||||
liteyukiData['python'],
|
||||
liteyukiData['system'],
|
||||
`${localData['plugins']} ${liteyukiData['plugins']}`,
|
||||
`${localData['bots']} ${liteyukiData['bots']}`,
|
||||
`${localData['runtime']} ${secondsToTextTime(liteyukiData['runtime'])}`,
|
||||
]
|
||||
tagArray.forEach(
|
||||
(tag, index) => {
|
||||
let tagSpan = document.createElement('span')
|
||||
tagSpan.className = 'bot-tag'
|
||||
tagSpan.innerText = tag
|
||||
// 给最后一个标签不添加后缀
|
||||
tagSpan.setAttribute('suffix', index === tagArray.length - 1 ? '0' : '1')
|
||||
liteyukiInfoDiv.querySelector('.bot-tags').appendChild(tagSpan)
|
||||
}
|
||||
)
|
||||
document.body.insertBefore(liteyukiInfoDiv, document.getElementById('hardware-info')) // 插入对象
|
||||
|
||||
// 添加硬件信息
|
||||
const cpuData = hardwareData['cpu']
|
||||
const memData = hardwareData['memory']
|
||||
const swapData = hardwareData['swap']
|
||||
|
||||
const cpuTagArray = [
|
||||
cpuData['name'],
|
||||
`${cpuData['cores']}${localData['cores']} ${cpuData['threads']}${localData['threads']}`,
|
||||
`${(cpuData['freq'] / 1000).toFixed(2)}GHz`
|
||||
]
|
||||
|
||||
const memTagArray = [
|
||||
`${localData['process']} ${convertSize(memData['usedProcess'])}`,
|
||||
`${localData['used']} ${convertSize(memData['used'])}`,
|
||||
`${localData['free']} ${convertSize(memData['free'])}`,
|
||||
`${localData['total']} ${convertSize(memData['total'])}`
|
||||
]
|
||||
|
||||
const swapTagArray = [
|
||||
`${localData['used']} ${convertSize(swapData['used'])}`,
|
||||
`${localData['free']} ${convertSize(swapData['free'])}`,
|
||||
`${localData['total']} ${convertSize(swapData['total'])}`
|
||||
]
|
||||
let cpuDeviceInfoDiv = document.importNode(document.getElementById('device-info').content, true)
|
||||
let memDeviceInfoDiv = document.importNode(document.getElementById('device-info').content, true)
|
||||
let swapDeviceInfoDiv = document.importNode(document.getElementById('device-info').content, true)
|
||||
|
||||
cpuDeviceInfoDiv.querySelector('.device-info').setAttribute('id', 'cpu-info')
|
||||
memDeviceInfoDiv.querySelector('.device-info').setAttribute('id', 'mem-info')
|
||||
swapDeviceInfoDiv.querySelector('.device-info').setAttribute('id', 'swap-info')
|
||||
cpuDeviceInfoDiv.querySelector('.device-chart').setAttribute('id', 'cpu-chart')
|
||||
memDeviceInfoDiv.querySelector('.device-chart').setAttribute('id', 'mem-chart')
|
||||
swapDeviceInfoDiv.querySelector('.device-chart').setAttribute('id', 'swap-chart')
|
||||
|
||||
let devices = {
|
||||
'cpu': cpuDeviceInfoDiv,
|
||||
'mem': memDeviceInfoDiv,
|
||||
'swap': swapDeviceInfoDiv
|
||||
}
|
||||
// 遍历添加标签
|
||||
for (let device in devices) {
|
||||
let tagArray = []
|
||||
switch (device) {
|
||||
case 'cpu':
|
||||
tagArray = cpuTagArray
|
||||
break
|
||||
case 'mem':
|
||||
tagArray = memTagArray
|
||||
break
|
||||
case 'swap':
|
||||
tagArray = swapTagArray
|
||||
break
|
||||
}
|
||||
tagArray.forEach(
|
||||
(tag, index) => {
|
||||
let tagDiv = document.createElement('div')
|
||||
tagDiv.className = 'device-tag'
|
||||
tagDiv.innerText = tag
|
||||
// 给最后一个标签不添加后缀
|
||||
tagDiv.setAttribute('suffix', index === tagArray.length - 1 ? '0' : '1')
|
||||
devices[device].querySelector('.device-tags').appendChild(tagDiv)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// 插入
|
||||
document.getElementById('hardware-info').appendChild(cpuDeviceInfoDiv)
|
||||
document.getElementById('hardware-info').appendChild(memDeviceInfoDiv)
|
||||
document.getElementById('hardware-info').appendChild(swapDeviceInfoDiv)
|
||||
|
||||
let cpuChart = echarts.init(document.getElementById('cpu-chart'))
|
||||
let memChart = echarts.init(document.getElementById('mem-chart'))
|
||||
let swapChart = echarts.init(document.getElementById('swap-chart'))
|
||||
|
||||
|
||||
cpuChart.setOption(createPieChartOption(`${localData['cpu']}\n${cpuData['percent'].toFixed(1)}%`, [
|
||||
{name: 'used', value: cpuData['percent']},
|
||||
{name: 'free', value: 100 - cpuData['percent']}
|
||||
]))
|
||||
|
||||
memChart.setOption(createPieChartOption(`${localData['memory']}\n${memData['percent'].toFixed(1)}%`, [
|
||||
{name: 'process', value: memData['usedProcess']},
|
||||
{name: 'used', value: memData['used'] - memData['usedProcess']},
|
||||
{name: 'free', value: memData['free']}
|
||||
]))
|
||||
|
||||
|
||||
swapChart.setOption(createPieChartOption(`${localData['swap']}\n${swapData['percent'].toFixed(1)}%`, [
|
||||
{name: 'used', value: swapData['used']},
|
||||
{name: 'free', value: swapData['free']}
|
||||
]))
|
||||
|
||||
|
||||
// 磁盘信息
|
||||
const diskData = hardwareData['disk']
|
||||
diskData.forEach(
|
||||
(disk) => {
|
||||
let diskTitle = `${disk['name']} ${localData['free']} ${convertSize(disk['free'])} ${localData['total']} ${convertSize(disk['total'])}`
|
||||
// 最后一个把margin-bottom去掉
|
||||
let diskDiv = createBarChart(diskTitle, disk['percent'])
|
||||
if (disk === diskData[diskData.length - 1]) {
|
||||
diskDiv.style.marginBottom = '0'
|
||||
}
|
||||
document.getElementById('disk-info').appendChild(createBarChart(diskTitle, disk['percent']))
|
||||
})
|
||||
// 随机一言
|
||||
let motto = mottos[Math.floor(Math.random() * mottos.length)]
|
||||
let mottoText = motto['text']
|
||||
let mottoFrom = `${motto['author']} ${motto['source']}`
|
||||
document.getElementById('motto-text').innerText = mottoText
|
||||
document.getElementById('motto-from').innerText = mottoFrom
|
||||
|
||||
|
||||
}
|
||||
|
||||
main()
|
257
liteyuki/resources/vanilla_resource/templates/js/style.js
Normal file
@ -0,0 +1,257 @@
|
||||
{
|
||||
// 环形图
|
||||
|
||||
let cpuInfo = echarts.init(document.getElementById('cpu-chart'));
|
||||
let memInfo = echarts.init(document.getElementById('mem-chart'));
|
||||
let swapInfo = echarts.init(document.getElementById('swap-chart'));
|
||||
|
||||
let data = JSON.parse(document.getElementById('data').innerText);
|
||||
|
||||
let cpuData = data.cpu;
|
||||
let memData = data.mem;
|
||||
let swapData = data.swap;
|
||||
let diskData = data.disk;
|
||||
let sub_tag_data = {
|
||||
cpu: data.cpuTags,
|
||||
mem: data.memTags,
|
||||
swap: data.swapTags
|
||||
}
|
||||
for (let key in sub_tag_data) {
|
||||
let infoDiv = document.getElementById(key + '-info');
|
||||
sub_tag_data[key].forEach(tag => {
|
||||
let tagSpan = document.createElement('div');
|
||||
tagSpan.innerText = tag;
|
||||
tagSpan.className = 'chart-label';
|
||||
infoDiv.appendChild(tagSpan);
|
||||
});
|
||||
}
|
||||
cpuInfo.setOption(getPieOption(data.localization.cpu, cpuData));
|
||||
memInfo.setOption(getPieOption(data.localization.mem, memData));
|
||||
swapInfo.setOption(getPieOption(data.localization.swap, swapData));
|
||||
|
||||
|
||||
// 在disks-info中插入每个disk的div,用横向柱状图表示用量,每一行div显示一个disk,不加info-box
|
||||
diskData.forEach(disk => {
|
||||
let diskDiv = document.createElement('div');
|
||||
document.getElementById('disks-info').appendChild(diskDiv);
|
||||
let diskChart = document.createElement('div');
|
||||
diskChart.style.width = '100%';
|
||||
diskChart.style.height = '100px';
|
||||
diskDiv.appendChild(diskChart);
|
||||
let diskInfo = echarts.init(diskChart);
|
||||
// let diskTitle = disk.name + ' {{ FREE }} ' + disk.free + ' {{ TOTAL }} ' + disk.total;
|
||||
let diskTitle = `${disk.name} ${data.localization.free} ${disk.free} ${data.localization.total} ${disk.total}`;
|
||||
diskInfo.setOption(getBarOption(diskTitle, disk.percent));
|
||||
});
|
||||
|
||||
let botData = data.bot;
|
||||
// 清空bot-info
|
||||
let botInfos = document.getElementsByClassName('bot-info');
|
||||
while (botInfos.length > 0) {
|
||||
botInfos[0].remove();
|
||||
}
|
||||
botData.forEach(bot => {
|
||||
// 在hardware-info前面插入一个div
|
||||
let botDiv = document.createElement('div');
|
||||
botDiv.className = 'info-box bot-info';
|
||||
// 在body内的hardware-info前面插入botDiv
|
||||
document.body.insertBefore(botDiv, document.getElementById('hardware-info'));
|
||||
|
||||
let botIconBlock = document.createElement('div');
|
||||
let botIcon = document.createElement('img');
|
||||
botIcon.src = bot.icon;
|
||||
botIcon.className = 'bot-icon';
|
||||
botIconBlock.appendChild(botIcon);
|
||||
botDiv.appendChild(botIconBlock);
|
||||
|
||||
let botDetail = document.createElement('div');
|
||||
let botName = document.createElement('div');
|
||||
botName.className = 'bot-name';
|
||||
botName.innerText = bot.name;
|
||||
if (bot.self) {
|
||||
// 添加颜色
|
||||
botName.style.color = '#d0e9ff';
|
||||
}
|
||||
botDetail.appendChild(botName);
|
||||
|
||||
let botTags = document.createElement('div');
|
||||
botTags.className = 'bot-tag';
|
||||
botDetail.appendChild(botTags)
|
||||
|
||||
bot.tags.forEach((tag, index) => {
|
||||
if (!tag) {
|
||||
return;
|
||||
}
|
||||
let tagSpan = document.createElement('span');
|
||||
|
||||
tagSpan.innerText = tag;
|
||||
tagSpan.className = 'tag';
|
||||
if (bot.self) {
|
||||
// 添加颜色
|
||||
tagSpan.style.color = '#a2d8f4';
|
||||
}
|
||||
botTags.appendChild(tagSpan);
|
||||
if (index === bot.tags.length - 1) {
|
||||
tagSpan.setAttribute("suffix", "0")
|
||||
} else {
|
||||
tagSpan.setAttribute("suffix", "1")
|
||||
}
|
||||
});
|
||||
|
||||
botDiv.appendChild(botDetail);
|
||||
}
|
||||
)
|
||||
|
||||
// 从/js/motto.js中读取mottos{},随机选择一句
|
||||
let motto = mottos[Math.floor(Math.random() * mottos.length)];
|
||||
// 正文在中间,作者和来源格式为--作者 来源,在右下方
|
||||
let mottoDiv = document.getElementById('motto-info');
|
||||
let mottoText = document.createElement('div');
|
||||
mottoText.className = 'motto-text';
|
||||
mottoText.innerText = motto.text;
|
||||
mottoDiv.appendChild(mottoText);
|
||||
let mottoAuthor = document.createElement('div');
|
||||
mottoAuthor.className = 'motto-author';
|
||||
// motto.author和motto.source可能不存在为空,所以要判断
|
||||
if (!motto.author) {
|
||||
motto.author = '';
|
||||
}
|
||||
if (!motto.source) {
|
||||
motto.source = '';
|
||||
}
|
||||
mottoAuthor.innerText = `\n--${motto.author} ${motto.source}`;
|
||||
mottoAuthor.style.textAlign = 'right';
|
||||
mottoDiv.appendChild(mottoAuthor);
|
||||
|
||||
function getPieUsage(data){
|
||||
let total = 0
|
||||
let used = 0
|
||||
data.forEach(item => {
|
||||
total += item.value
|
||||
if(item.name === 'FREE'){
|
||||
used += item.value
|
||||
}
|
||||
})
|
||||
return (1 - used / total) * 100
|
||||
}
|
||||
|
||||
|
||||
function getPieOption(title, data) {
|
||||
return {
|
||||
animation: false,
|
||||
title: {
|
||||
text: title + '\n' + getPieUsage(data).toFixed(1) + '%',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
//文字颜色
|
||||
|
||||
lineHeight: 36,
|
||||
color: '#fff',
|
||||
fontSize: 30
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: "item",
|
||||
backgroundColor: "#ffffff00",
|
||||
// {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)
|
||||
},
|
||||
color: ['#a2d8f4', "#ffffff44", '#00a6ff'],
|
||||
series: [
|
||||
{
|
||||
name: 'info',
|
||||
type: 'pie',
|
||||
radius: ['80%', '100%'],
|
||||
center: ['50%', '50%'],
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: false
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
fontSize: '50',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: data
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function getBarOption(title, percent) {
|
||||
let fillet = 0
|
||||
if (percent < 5){
|
||||
fillet = 50
|
||||
}
|
||||
// data为百分比,最大值为100
|
||||
return {
|
||||
background: '#d0e9ff',
|
||||
title: {
|
||||
text: title,
|
||||
left: '5%',
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 30
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: "item",
|
||||
backgroundColor: "#ffffff",
|
||||
},
|
||||
grid: {
|
||||
left: '0',
|
||||
right: '0',
|
||||
top: '10%',
|
||||
bottom: '10%'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
show: false
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: [''],
|
||||
show: false
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Used',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
data: [percent],
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#a2d8f4',
|
||||
barBorderRadius: [50, 0, 0, 50]
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Free',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
data: [100 - percent],
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#d0e9ff',
|
||||
barBorderRadius: [fillet, 50, 50, fillet]
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|