-
-
NapCat
- {error
- ? (
- error.message
- )
- : loading
- ? (
-
- )
- : (
-
- )}
-
+
+ {error ? (
+
{error.message}
+ ) : loading ? (
+
+ ) : (
+
+ WebUI v0.0.6
+ Core {data?.version}
+
+ )}
);
}
export default function AboutPage () {
- const { isDark } = useTheme();
-
- const imageUrls = useMemo(
- () => [
- 'https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=777721566&limit=30&image_size=auto&color_scheme=light',
- 'https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=777721566&limit=30&image_size=auto&color_scheme=dark',
- 'https://next.ossinsight.io/widgets/official/compose-activity-trends/thumbnail.png?repo_id=41986369&image_size=auto&color_scheme=light',
- 'https://next.ossinsight.io/widgets/official/compose-activity-trends/thumbnail.png?repo_id=41986369&image_size=auto&color_scheme=dark',
- ],
- []
- );
-
- const { loadedUrls, isLoading } = usePreloadImages(imageUrls);
-
- const getImageUrl = useMemo(
- () => (baseUrl: string) => {
- const theme = isDark ? 'dark' : 'light';
- const fullUrl = baseUrl.replace(
- /color_scheme=(?:light|dark)/,
- `color_scheme=${theme}`
- );
- return isLoading ? null : loadedUrls[fullUrl] ? fullUrl : null;
+ const features = [
+ {
+ icon:
,
+ title: '高性能架构',
+ desc: 'Node.js + Native 混合架构,资源占用低,响应速度快。',
+ className: 'bg-primary-50 text-primary'
},
- [isDark, isLoading, loadedUrls]
- );
-
- const renderImage = useMemo(
- () => (baseUrl: string, alt: string) => {
- const imageUrl = getImageUrl(baseUrl);
-
- if (!imageUrl) {
- return
;
- }
-
- return (
-
- );
+ {
+ icon:
,
+ title: '全平台支持',
+ desc: '适配 Windows、Linux 及 Docker 环境。',
+ className: 'bg-success-50 text-success'
},
- [getImageUrl]
- );
+ {
+ icon:
,
+ title: 'OneBot 11',
+ desc: '深度集成标准协议,兼容现有生态。',
+ className: 'bg-warning-50 text-warning'
+ },
+ {
+ icon:
,
+ title: '极易扩展',
+ desc: '提供丰富的 API 接口与 WebHook 支持。',
+ className: 'bg-secondary-50 text-secondary'
+ }
+ ];
+
+ const links = [
+ { icon:
, name: 'GitHub', href: 'https://github.com/NapNeko/NapCatQQ' },
+ { icon:
, name: 'Telegram', href: 'https://t.me/napcatqq' },
+ { icon:
, name: 'QQ 群 1', href: 'https://qm.qq.com/q/F9cgs1N3Mc' },
+ { icon:
, name: 'QQ 群 2', href: 'https://qm.qq.com/q/hSt0u9PVn' },
+ { icon:
, name: '文档', href: 'https://napcat.napneko.icu/' },
+ ];
+
+ const cardStyle = "bg-default/40 backdrop-blur-lg border-none shadow-none";
return (
- <>
-
关于 NapCat WebUI
-
-
-
-
-
-
-
-
-
NapCat 是什么?
-
- 基于TypeScript构建的Bot框架,通过相应的启动器或者框架,主动调用QQ
- Node模块提供给客户端的接口,实现Bot的功能.
+
+
关于 - NapCat WebUI
+
+ {/* 头部标题区 */}
+
+
+
+ 关于 NapCat
+
+
+
现代化、轻量级的 QQ 机器人框架
+
+
+
+
+
+
+
+ {/* 主内容区:双栏布局 */}
+
+
+ {/* 左侧:介绍与特性 */}
+
+
+
+ 项目简介
+
+
+
+ NapCat (瞌睡猫) 是一个致力于打破 QQ 机器人开发壁垒的开源项目。我们利用 NTQQ 的底层能力,
+ 构建了一个无需 GUI 即可在服务器端稳定运行的 Headless 框架。
- 魔法版介绍
-
- 猫猫框架通过魔法的手段获得了 QQ 的发送消息、接收消息等接口。
- 为了方便使用,猫猫框架将通过一种名为 OneBot 的约定将你的 HTTP /
- WebSocket 请求按照规范读取,
- 再去调用猫猫框架所获得的QQ发送接口之类的接口。
+
+ 无论是个人开发者还是企业用户,NapCat 都能提供开箱即用的 OneBot 11 协议支持,
+ 助您快速将创意转化为现实。
-
+
+
+
+
+ {features.map((item, index) => (
+
+
+
+ {item.icon}
+
+
+
{item.title}
+
{item.desc}
+
+
+
+ ))}
-
-
-
-
-
-
- 官方社群1
+
+ {/* 右侧:信息与链接 */}
+
+
+
+ 相关资源
+
+
+
+ {links.map((link, idx) => (
+
+
+ {link.icon}
+ {link.name}
+
+ 跳转 →
+
+ ))}
+
-
-
-
-
-
- 官方社群2
-
-
-
-
-
-
-
-
- Telegram
-
-
-
-
-
-
-
-
- 使用文档
+
+
+
+ 技术栈
+
+
+
+
+ {['TypeScript', 'React', 'Vite', 'Node.js', 'Electron', 'HeroUI'].map((tech) => (
+
+ {tech}
+
+ ))}
+
-
-
- {renderImage(
- 'https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=777721566&limit=30&image_size=auto&color_scheme=light',
- 'Contributors'
- )}
- {renderImage(
- 'https://next.ossinsight.io/widgets/official/compose-activity-trends/thumbnail.png?repo_id=41986369&image_size=auto&color_scheme=light',
- 'Activity Trends'
- )}
-
+
-
-
-
- >
+ {/* 底部版权 - 移出 grid 布局 */}
+
+
+ Made with ❤️ by NapCat Team
+
+
MIT License © {new Date().getFullYear()}
+
+
);
-}
+}
\ No newline at end of file
diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/config/webui.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/config/webui.tsx
index 47f487bf..8feaabe9 100644
--- a/packages/napcat-webui-frontend/src/pages/dashboard/config/webui.tsx
+++ b/packages/napcat-webui-frontend/src/pages/dashboard/config/webui.tsx
@@ -1,4 +1,3 @@
-import { Input } from '@heroui/input';
import { Button } from '@heroui/button';
import { useLocalStorage } from '@uidotdev/usehooks';
import { useEffect, useState } from 'react';
@@ -11,8 +10,6 @@ import SaveButtons from '@/components/button/save_buttons';
import FileInput from '@/components/input/file_input';
import ImageInput from '@/components/input/image_input';
-import useMusic from '@/hooks/use-music';
-
import { siteConfig } from '@/config/site';
import FileManager from '@/controllers/file_manager';
import WebUIManager from '@/controllers/webui_manager';
@@ -43,7 +40,6 @@ const WebUIConfigCard = () => {
} = useForm
({
defaultValues: {
background: '',
- musicListID: '',
customIcons: {},
},
});
@@ -53,7 +49,6 @@ const WebUIConfigCard = () => {
key.customIcons,
{}
);
- const { setListId, listId } = useMusic();
const [registrationOptions, setRegistrationOptions] = useState(null);
const [isLoadingOptions, setIsLoadingOptions] = useState(false);
@@ -75,14 +70,12 @@ const WebUIConfigCard = () => {
};
const reset = () => {
- setWebuiValue('musicListID', listId);
setWebuiValue('customIcons', customIcons);
setWebuiValue('background', b64img);
};
const onSubmit = handleWebuiSubmit((data) => {
try {
- setListId(data.musicListID);
setCustomIcons(data.customIcons);
setB64img(data.background);
toast.success('保存成功');
@@ -94,7 +87,7 @@ const WebUIConfigCard = () => {
useEffect(() => {
reset();
- }, [listId, customIcons, b64img]);
+ }, [customIcons, b64img]);
return (
<>
@@ -130,20 +123,6 @@ const WebUIConfigCard = () => {
/>
-
-
WebUI音乐播放器
-
(
-
- )}
- />
-
背景图
QQ登录 - NapCat WebUI
-
+
-
+
>
);
diff --git a/packages/napcat-webui-frontend/src/pages/web_login.tsx b/packages/napcat-webui-frontend/src/pages/web_login.tsx
index bcefb8a5..c0c128b5 100644
--- a/packages/napcat-webui-frontend/src/pages/web_login.tsx
+++ b/packages/napcat-webui-frontend/src/pages/web_login.tsx
@@ -8,15 +8,17 @@ import { toast } from 'react-hot-toast';
import { IoKeyOutline } from 'react-icons/io5';
import { useNavigate } from 'react-router-dom';
+import logo from '@/assets/images/logo.png';
+
import key from '@/const/key';
import HoverEffectCard from '@/components/effect_card';
import { title } from '@/components/primitives';
import { ThemeSwitch } from '@/components/theme-switch';
-import logo from '@/assets/images/logo.png';
import WebUIManager from '@/controllers/webui_manager';
import PureLayout from '@/layouts/pure';
+import { motion } from 'motion/react';
export default function WebLoginPage () {
const urlSearchParams = new URLSearchParams(window.location.search);
@@ -150,7 +152,12 @@ export default function WebLoginPage () {
<>
WebUI登录 - NapCat WebUI
-
+
-
+
>
);
diff --git a/packages/napcat-webui-frontend/src/styles/globals.css b/packages/napcat-webui-frontend/src/styles/globals.css
index c31e135b..7c3af465 100644
--- a/packages/napcat-webui-frontend/src/styles/globals.css
+++ b/packages/napcat-webui-frontend/src/styles/globals.css
@@ -6,15 +6,45 @@
body {
font-family:
- 'Aa偷吃可爱长大的',
- PingFang SC,
- Helvetica Neue,
- Microsoft YaHei,
+ 'Quicksand',
+ 'Nunito',
+ 'Inter',
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ 'Helvetica Neue',
+ Arial,
+ 'PingFang SC',
+ 'Microsoft YaHei',
sans-serif !important;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
font-smooth: always;
+ letter-spacing: 0.02em;
+}
+
+:root {
+ --heroui-primary: 217.2 91.2% 59.8%; /* 自然的现代蓝 */
+ --heroui-primary-foreground: 210 40% 98%;
+ --heroui-radius: 0.75rem;
+ --text-primary: 222.2 47.4% 11.2%;
+ --text-secondary: 215.4 16.3% 46.9%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: hsl(var(--text-primary));
+ letter-spacing: -0.02em;
+}
+
+.dark h1, .dark h2, .dark h3, .dark h4, .dark h5, .dark h6 {
+ color: hsl(210 40% 98%);
+}
+
+.dark {
+ --heroui-primary: 217.2 91.2% 59.8%;
+ --heroui-primary-foreground: 210 40% 98%;
}
@layer components {
@@ -34,23 +64,29 @@ body {
}
}
+::selection {
+ background-color: #ffcdba;
+ color: #fff;
+}
+
::-webkit-scrollbar {
- width: 8px;
- height: 8px;
+ width: 6px;
+ height: 6px;
}
::-webkit-scrollbar-track {
background-color: transparent;
- -webkit-border-radius: 2em;
- -moz-border-radius: 2em;
- border-radius: 2em;
+ border-radius: 3px;
}
::-webkit-scrollbar-thumb {
- background-color: rgb(147, 147, 153, 0.5);
- -webkit-border-radius: 2em;
- -moz-border-radius: 2em;
- border-radius: 2em;
+ background-color: rgba(255, 182, 193, 0.4); /* 浅粉色滚动条 */
+ border-radius: 3px;
+ transition: all 0.3s;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background-color: rgba(255, 127, 172, 0.6);
}
.monaco-editor {
diff --git a/packages/napcat-webui-frontend/src/utils/music.ts b/packages/napcat-webui-frontend/src/utils/music.ts
deleted file mode 100644
index 6936b0d6..00000000
--- a/packages/napcat-webui-frontend/src/utils/music.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-import { PlayMode } from '@/const/enum';
-
-import WebUIManager from '@/controllers/webui_manager';
-import type {
- FinalMusic,
- Music163ListResponse,
- Music163URLResponse,
-} from '@/types/music';
-
-/**
- * 获取网易云音乐歌单
- * @param id 歌单id
- * @returns 歌单信息
- */
-export const get163MusicList = async (id: string) => {
- const res = await WebUIManager.proxy(
- 'https://wavesgame.top/playlist/track/all?id=' + id
- );
- // const res = await request.get(
- // `https://wavesgame.top/playlist/track/all?id=${id}`
- // )
- if (res?.data?.code !== 200) {
- throw new Error('获取歌曲列表失败');
- }
- return res.data;
-};
-
-/**
- * 获取歌曲地址
- * @param ids 歌曲id
- * @returns 歌曲地址
- */
-export const getSongsURL = async (ids: number[]) => {
- const _ids = ids.reduce((prev, cur, index) => {
- const groupIndex = Math.floor(index / 10);
- if (!prev[groupIndex]) {
- prev[groupIndex] = [];
- }
- prev[groupIndex].push(cur);
- return prev;
- }, [] as number[][]);
- const res = await Promise.all(
- _ids.map(async (id) => {
- const res = await WebUIManager.proxy(
- `https://wavesgame.top/song/url?id=${id.join(',')}`
- );
- if (res?.data?.code !== 200) {
- throw new Error('获取歌曲地址失败');
- }
- return res.data.data;
- })
- );
- const result = res.reduce((prev, cur) => {
- return prev.concat(...cur);
- }, []);
- return result;
-};
-
-/**
- * 获取网易云音乐歌单歌曲
- * @param id 歌单id
- * @returns 歌曲信息
- */
-export const get163MusicListSongs = async (id: string) => {
- const listRes = await get163MusicList(id);
- const songs = listRes.songs.map((song) => song.id);
- const songsRes = await getSongsURL(songs);
- const finalMusic: FinalMusic[] = [];
- for (let i = 0; i < listRes.songs.length; i++) {
- const song = listRes.songs[i];
- const music = songsRes.find((s) => s.id === song.id);
- const songURL = music?.url;
- if (songURL) {
- finalMusic.push({
- id: song.id,
- url: songURL.replace(/http:\/\//, '//').replace(/https:\/\//, '//'),
- title: song.name,
- artist: song.ar.map((p) => p.name).join('/'),
- cover: song.al.picUrl,
- });
- }
- }
- return finalMusic;
-};
-
-/**
- * 获取随机音乐
- * @param ids 歌曲id
- * @param currentId 当前音乐id
- * @returns 随机音乐id
- */
-export const getRandomMusic = (ids: number[], currentId: number): number => {
- const randomIndex = Math.floor(Math.random() * ids.length);
- const randomId = ids[randomIndex];
- if (randomId === currentId) {
- return getRandomMusic(ids, currentId);
- }
- return randomId;
-};
-
-/**
- * 获取下一首音乐id
- * @param ids 歌曲id
- * @param currentId 当前音乐ID
- * @param mode 播放模式
- */
-export const getNextMusic = (
- musics: FinalMusic[],
- currentId: number,
- mode: PlayMode
-): number => {
- const ids = musics.map((music) => music.id);
- if (mode === PlayMode.Loop) {
- const currentIndex = ids.findIndex((id) => id === currentId);
- const nextIndex = currentIndex + 1;
- return ids[nextIndex] || ids[0];
- }
- if (mode === PlayMode.Random) {
- return getRandomMusic(ids, currentId);
- }
- return currentId;
-};
diff --git a/packages/napcat-webui-frontend/tailwind.config.js b/packages/napcat-webui-frontend/tailwind.config.js
index e48e7d97..d320d8fb 100644
--- a/packages/napcat-webui-frontend/tailwind.config.js
+++ b/packages/napcat-webui-frontend/tailwind.config.js
@@ -25,18 +25,32 @@ export default {
light: {
colors: {
primary: {
- DEFAULT: '#f31260',
+ DEFAULT: '#FF7FAC', // 樱花粉
foreground: '#fff',
- 50: '#fee7ef',
- 100: '#fdd0df',
- 200: '#faa0bf',
- 300: '#f871a0',
- 400: '#f54180',
- 500: '#f31260',
- 600: '#c20e4d',
- 700: '#920b3a',
- 800: '#610726',
- 900: '#310413',
+ 50: '#FFF0F5',
+ 100: '#FFE4E9',
+ 200: '#FFCDD9',
+ 300: '#FF9EB5',
+ 400: '#FF7FAC',
+ 500: '#F33B7C',
+ 600: '#C92462',
+ 700: '#991B4B',
+ 800: '#691233',
+ 900: '#380A1B',
+ },
+ secondary: {
+ DEFAULT: '#88C0D0', // 冰霜蓝
+ foreground: '#fff',
+ 50: '#F0F9FC',
+ 100: '#D7F0F8',
+ 200: '#AEE1F2',
+ 300: '#88C0D0',
+ 400: '#5E9FBF',
+ 500: '#4C8DAE',
+ 600: '#3A708C',
+ 700: '#2A546A',
+ 800: '#1A3748',
+ 900: '#0B1B26',
},
danger: {
DEFAULT: '#DB3694',