diff --git a/package.json b/package.json index 8c73196..a75ac9f 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,17 @@ "dependencies": { "axios": "^1.3.4", "form-data": "^4.0.1", + "next": "^14.2.16", "node-id3": "^0.2.6", + "p-queue": "^8.0.1", "qrcode": "^1.5.3", - "p-queue": "^8.0.1" + "react": "^18.3.1", + "react-circular-progressbar": "^2.1.0", + "react-dom": "^18.3.1", + "systeminformation": "^5.23.5" + }, + "devDependencies": { + "daisyui": "^4.12.14", + "tailwindcss": "^3.4.14" } } diff --git a/server/app/layout.jsx b/server/app/layout.jsx new file mode 100644 index 0000000..e8acbcc --- /dev/null +++ b/server/app/layout.jsx @@ -0,0 +1,9 @@ +import "../styles/global.css"; + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} diff --git a/server/app/page.jsx b/server/app/page.jsx new file mode 100644 index 0000000..4e3a190 --- /dev/null +++ b/server/app/page.jsx @@ -0,0 +1,3 @@ +export default function Page() { + return

进入控制面板

+} diff --git a/server/app/r/api/napcat/[pid]/route.js b/server/app/r/api/napcat/[pid]/route.js new file mode 100644 index 0000000..0fd7fc0 --- /dev/null +++ b/server/app/r/api/napcat/[pid]/route.js @@ -0,0 +1,10 @@ +import axiosInstance from "../../../../../utils/axiosInstance.js"; + +export async function GET(request, { params }) { + const { pid } = params; + const napcatResp = await axiosInstance.get(`/${ pid }`); + return new Response(JSON.stringify(napcatResp), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); +} diff --git a/server/app/r/api/network/route.js b/server/app/r/api/network/route.js new file mode 100644 index 0000000..ba2c6af --- /dev/null +++ b/server/app/r/api/network/route.js @@ -0,0 +1,25 @@ +import axios from "axios"; + +export async function GET(request) { + const url = new URL(request.url); // 获取请求的 URL + const targetUrl = url.searchParams.get("url"); // 从查询参数中获取目标 URL + const start = Date.now(); // 记录请求开始时间 + + try { + await axios.get(targetUrl); + // 计算结束时间减去开始时间 + return new Response(JSON.stringify({ + time: Date.now() - start + }), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + } catch (error) { + return new Response(JSON.stringify({ + time: 0 + }), { + status: 500, + headers: { 'Content-Type': 'application/json' }, + }) + } +} diff --git a/server/app/r/api/system/route.js b/server/app/r/api/system/route.js new file mode 100644 index 0000000..af08533 --- /dev/null +++ b/server/app/r/api/system/route.js @@ -0,0 +1,60 @@ +import si from 'systeminformation'; +import os from 'os'; + +export async function GET(request, { params }) { + try { + // 获取CPU信息 + const cpuInfo = await si.cpu(); + const cpuUsage = await si.currentLoad(); + const totalCpuCores = cpuInfo.cores; + const cpuCoresUsed = ((cpuUsage.currentLoad / 100) * totalCpuCores).toFixed(1); // 使用的核心数 + + // 获取内存信息 + const totalMemory = (os.totalmem() / (1024 ** 3)).toFixed(2); // 转换为 GB + const freeMemory = (os.freemem() / (1024 ** 3)).toFixed(2); // 转换为 GB + const usedMemory = (totalMemory - freeMemory).toFixed(2); + const memoryUsagePercent = ((usedMemory / totalMemory) * 100).toFixed(2); + + // 获取磁盘信息 + const diskInfo = await si.fsSize(); + const totalDisk = (diskInfo[0].size / (1024 ** 3)).toFixed(2); // 转换为 GB + const usedDisk = (diskInfo[0].used / (1024 ** 3)).toFixed(2); // 转换为 GB + const diskUsagePercent = ((usedDisk / totalDisk) * 100).toFixed(2); + + // 获取网络信息 + const networkInterfaces = os.networkInterfaces(); + const ipAddress = Object.values(networkInterfaces) + .flat() + .filter(detail => detail.family === 'IPv4' && !detail.internal)[0].address; + + // 获取系统信息 + const hostname = os.hostname(); + const uptime = os.uptime(); + const osInfo = await si.osInfo(); + + return new Response(JSON.stringify({ + cpuUsage: cpuUsage.currentLoad.toFixed(2), + cpuUsageDetail: `${cpuUsage.currentLoad.toFixed(2)}%`, + totalCpuCores, + cpuCoresUsed, + memoryUsage: memoryUsagePercent, + usedMemory: `${usedMemory} GB`, + totalMemory: `${totalMemory} GB`, + diskUsage: diskUsagePercent, + usedDisk: `${usedDisk} GB`, + totalDisk: `${totalDisk} GB`, + loadAverage: cpuUsage.avgLoad.toFixed(2), + ipAddress, + hostname, + uptime: `${Math.floor(uptime / 60 / 60)} hours`, + distro: osInfo.distro, + kernelVersion: osInfo.kernel, + arch: os.arch(), + }), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + } catch (error) { + return new Response(JSON.stringify({ error: error.message }), { status: 500 }); + } +} diff --git a/server/app/r/page.js b/server/app/r/page.js new file mode 100644 index 0000000..3bc2d81 --- /dev/null +++ b/server/app/r/page.js @@ -0,0 +1,12 @@ +import Sidebar from "../../components/sidebar.jsx"; +import Header from "../../components/header.jsx"; +import { DrawerProvider } from "../../contexts/drawer-context.js"; + +export default function Page() { + return ( + +
+ + + ) +} diff --git a/server/assets/fonts/FiraCode-VF.woff2 b/server/assets/fonts/FiraCode-VF.woff2 new file mode 100644 index 0000000..e755a9d Binary files /dev/null and b/server/assets/fonts/FiraCode-VF.woff2 differ diff --git a/server/assets/fonts/SourceHanSerifCN-VF.woff2 b/server/assets/fonts/SourceHanSerifCN-VF.woff2 new file mode 100644 index 0000000..87e20c4 Binary files /dev/null and b/server/assets/fonts/SourceHanSerifCN-VF.woff2 differ diff --git a/server/components/ThemeToggle.jsx b/server/components/ThemeToggle.jsx new file mode 100644 index 0000000..67ba3a8 --- /dev/null +++ b/server/components/ThemeToggle.jsx @@ -0,0 +1,23 @@ +import React, { useState } from 'react'; + +function ThemeToggle() { + // 用于保存主题状态,默认为“light”主题 + const [isDarkTheme, setIsDarkTheme] = useState(false); + + // 切换主题时的处理函数 + const handleThemeChange = () => { + setIsDarkTheme(!isDarkTheme); + }; + + return ( + + ); +} + +export default ThemeToggle; diff --git a/server/components/content.jsx b/server/components/content.jsx new file mode 100644 index 0000000..39ae729 --- /dev/null +++ b/server/components/content.jsx @@ -0,0 +1,21 @@ +import Bili from "./contents/bili.jsx"; +import Home from "./contents/home.jsx"; +import Tiktok from "./contents/tiktok.jsx"; +import Weekly from "./contents/weekly.jsx"; + +export function Content({ activeItem }) { + + // 使用对象映射内容,以便于后期扩展和维护 + const contentMap = { + "总控制台": , + "哔哩哔哩控制台": , + "抖音控制台": , + "周刊预览": + }; + + return ( +
+ { contentMap[activeItem] || contentMap["总控制台"] } +
+ ); +} diff --git a/server/components/contents/bili.jsx b/server/components/contents/bili.jsx new file mode 100644 index 0000000..e98ba6e --- /dev/null +++ b/server/components/contents/bili.jsx @@ -0,0 +1,7 @@ +export default function Bili() { + + + return ( +
Bili
+ ) +} diff --git a/server/components/contents/home.jsx b/server/components/contents/home.jsx new file mode 100644 index 0000000..eff1a96 --- /dev/null +++ b/server/components/contents/home.jsx @@ -0,0 +1,30 @@ +import React from 'react'; +import BotInfo from "../home/bot-info.jsx"; +import System from "../home/system.jsx"; + +export default function Home({ }) { + return ( +
+ + +
+ {/* 监控卡片 */ } +
+
+

监控

+
+
+

上传: 0.87 KB/s

+

下载: 3.21 KB/s

+
+
+

总发送: 21.17 GB

+

总接收: 90.46 GB

+
+
+
+
+
+
+ ); +} diff --git a/server/components/contents/tiktok.jsx b/server/components/contents/tiktok.jsx new file mode 100644 index 0000000..95bcac4 --- /dev/null +++ b/server/components/contents/tiktok.jsx @@ -0,0 +1,5 @@ +export default function Tiktok() { + return ( +
Tiktok
+ ) +} diff --git a/server/components/contents/weekly.jsx b/server/components/contents/weekly.jsx new file mode 100644 index 0000000..c3767d5 --- /dev/null +++ b/server/components/contents/weekly.jsx @@ -0,0 +1,11 @@ +export default function Weekly() { + return ( +
+