diff --git a/packages/napcat-webui-frontend/src/components/button/add_button.tsx b/packages/napcat-webui-frontend/src/components/button/add_button.tsx index 3461cc5e..f6b230b7 100644 --- a/packages/napcat-webui-frontend/src/components/button/add_button.tsx +++ b/packages/napcat-webui-frontend/src/components/button/add_button.tsx @@ -18,7 +18,7 @@ import { } from '../icons'; export interface AddButtonProps { - onOpen: (key: keyof OneBotConfig['network']) => void + onOpen: (key: keyof OneBotConfig['network']) => void; } const AddButton: React.FC = (props) => { @@ -33,7 +33,7 @@ const AddButton: React.FC = (props) => { > )} diff --git a/packages/napcat-webui-frontend/src/components/chat_input/modal.tsx b/packages/napcat-webui-frontend/src/components/chat_input/modal.tsx index 841c9258..a693de2e 100644 --- a/packages/napcat-webui-frontend/src/components/chat_input/modal.tsx +++ b/packages/napcat-webui-frontend/src/components/chat_input/modal.tsx @@ -15,8 +15,15 @@ export default function ChatInputModal () { return ( <> - { - test?: string + test?: string; } export type CodeEditorRef = monaco.editor.IStandaloneCodeEditor; diff --git a/packages/napcat-webui-frontend/src/components/display_card/common_card.tsx b/packages/napcat-webui-frontend/src/components/display_card/common_card.tsx index b920198d..439f7f7c 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/common_card.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/common_card.tsx @@ -1,5 +1,6 @@ -import { Button, ButtonGroup } from '@heroui/button'; +import { Button } from '@heroui/button'; import { Switch } from '@heroui/switch'; +import clsx from 'clsx'; import { useState } from 'react'; import { CgDebug } from 'react-icons/cg'; import { FiEdit3 } from 'react-icons/fi'; @@ -10,27 +11,25 @@ import DisplayCardContainer from './container'; type NetworkType = OneBotConfig['network']; export type NetworkDisplayCardFields = Array<{ - label: string - value: NetworkType[T][0][keyof NetworkType[T][0]] + label: string; + value: NetworkType[T][0][keyof NetworkType[T][0]]; render?: ( value: NetworkType[T][0][keyof NetworkType[T][0]] - ) => React.ReactNode + ) => React.ReactNode; }>; export interface NetworkDisplayCardProps { - data: NetworkType[T][0] - showType?: boolean - typeLabel: string - fields: NetworkDisplayCardFields - onEdit: () => void - onEnable: () => Promise - onDelete: () => Promise - onEnableDebug: () => Promise + data: NetworkType[T][0]; + typeLabel: string; + fields: NetworkDisplayCardFields; + onEdit: () => void; + onEnable: () => Promise; + onDelete: () => Promise; + onEnableDebug: () => Promise; } -const NetworkDisplayCard = ({ +const NetworkDisplayCard = ({ data, - showType, typeLabel, fields, onEdit, @@ -56,79 +55,146 @@ const NetworkDisplayCard = ({ onEnableDebug().finally(() => setEditing(false)); }; + const isFullWidthField = (label: string) => ['URL', 'Token', 'AccessToken'].includes(label); + return ( +
- +
} enableSwitch={ } - tag={showType && typeLabel} - title={name} + title={typeLabel} > -
- {fields.map((field, index) => ( -
- {field.label} - {field.render - ? ( - field.render(field.value) - ) - : ( - {field.value} - )} -
- ))} +
+ {(() => { + const targetFullField = fields.find(f => isFullWidthField(f.label)); + + if (targetFullField) { + // 模式1:存在全宽字段(如URL),布局为: + // Row 1: 名称 (全宽) + // Row 2: 全宽字段 (全宽) + return ( + <> +
+ 名称 +
+ {name} +
+
+
+ {targetFullField.label} +
+ {targetFullField.render + ? targetFullField.render(targetFullField.value) + : ( + + {String(targetFullField.value)} + + )} +
+
+ + ); + } else { + // 模式2:无全宽字段,布局为 4 个小块 (2行 x 2列) + // Row 1: 名称 | Field 0 + // Row 2: Field 1 | Field 2 + const displayFields = fields.slice(0, 3); + return ( + <> +
+ 名称 +
+ {name} +
+
+ {displayFields.map((field, index) => ( +
+ {field.label} +
+ {field.render + ? ( + field.render(field.value) + ) + : ( + + {String(field.value)} + + )} +
+
+ ))} + {/* 如果字段不足3个,可以补充空白块占位吗?或者是让它空着?用户说要高度一致。只要是grid,通常高度会被撑开。目前这样应该能保证最多2行。 */} + + ); + } + })()}
); diff --git a/packages/napcat-webui-frontend/src/components/display_card/container.tsx b/packages/napcat-webui-frontend/src/components/display_card/container.tsx index c96c9f8a..e3a1fd0d 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/container.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/container.tsx @@ -1,7 +1,8 @@ import { Card, CardBody, CardFooter, CardHeader } from '@heroui/card'; +import { useLocalStorage } from '@uidotdev/usehooks'; import clsx from 'clsx'; +import key from '@/const/key'; -import { title } from '../primitives'; export interface ContainerProps { title: string; @@ -9,6 +10,7 @@ export interface ContainerProps { action: React.ReactNode; enableSwitch: React.ReactNode; children: React.ReactNode; + className?: string; // Add className prop } export interface DisplayCardProps { @@ -25,31 +27,35 @@ const DisplayCardContainer: React.FC = ({ tag, enableSwitch, children, + className, }) => { + const [backgroundImage] = useLocalStorage(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; + return ( - - + + {tag && ( -
+
{tag}
)} -

- {_title} -

-
{enableSwitch}
+
+
+ + {_title} + +
+
+
{enableSwitch}
- {children} - {action} + {children} + {action} ); }; diff --git a/packages/napcat-webui-frontend/src/components/display_card/http_client.tsx b/packages/napcat-webui-frontend/src/components/display_card/http_client.tsx index 9519f269..b9f3ce20 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/http_client.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/http_client.tsx @@ -4,12 +4,12 @@ import NetworkDisplayCard from './common_card'; import type { NetworkDisplayCardFields } from './common_card'; interface HTTPClientDisplayCardProps { - data: OneBotConfig['network']['httpClients'][0] - showType?: boolean - onEdit: () => void - onEnable: () => Promise - onDelete: () => Promise - onEnableDebug: () => Promise + data: OneBotConfig['network']['httpClients'][0]; + showType?: boolean; + onEdit: () => void; + onEnable: () => Promise; + onDelete: () => Promise; + onEnableDebug: () => Promise; } const HTTPClientDisplayCard: React.FC = (props) => { diff --git a/packages/napcat-webui-frontend/src/components/display_card/http_server.tsx b/packages/napcat-webui-frontend/src/components/display_card/http_server.tsx index a72c4692..1ba55318 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/http_server.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/http_server.tsx @@ -4,12 +4,12 @@ import NetworkDisplayCard from './common_card'; import type { NetworkDisplayCardFields } from './common_card'; interface HTTPServerDisplayCardProps { - data: OneBotConfig['network']['httpServers'][0] - showType?: boolean - onEdit: () => void - onEnable: () => Promise - onDelete: () => Promise - onEnableDebug: () => Promise + data: OneBotConfig['network']['httpServers'][0]; + showType?: boolean; + onEdit: () => void; + onEnable: () => Promise; + onDelete: () => Promise; + onEnableDebug: () => Promise; } const HTTPServerDisplayCard: React.FC = (props) => { diff --git a/packages/napcat-webui-frontend/src/components/display_card/http_sse_server.tsx b/packages/napcat-webui-frontend/src/components/display_card/http_sse_server.tsx index f6ea34f3..38e3e6bc 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/http_sse_server.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/http_sse_server.tsx @@ -4,12 +4,12 @@ import NetworkDisplayCard from './common_card'; import type { NetworkDisplayCardFields } from './common_card'; interface HTTPSSEServerDisplayCardProps { - data: OneBotConfig['network']['httpSseServers'][0] - showType?: boolean - onEdit: () => void - onEnable: () => Promise - onDelete: () => Promise - onEnableDebug: () => Promise + data: OneBotConfig['network']['httpSseServers'][0]; + showType?: boolean; + onEdit: () => void; + onEnable: () => Promise; + onDelete: () => Promise; + onEnableDebug: () => Promise; } const HTTPSSEServerDisplayCard: React.FC = ( diff --git a/packages/napcat-webui-frontend/src/components/display_card/ws_client.tsx b/packages/napcat-webui-frontend/src/components/display_card/ws_client.tsx index deba3d30..b69c57ea 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/ws_client.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/ws_client.tsx @@ -4,12 +4,12 @@ import NetworkDisplayCard from './common_card'; import type { NetworkDisplayCardFields } from './common_card'; interface WebsocketClientDisplayCardProps { - data: OneBotConfig['network']['websocketClients'][0] - showType?: boolean - onEdit: () => void - onEnable: () => Promise - onDelete: () => Promise - onEnableDebug: () => Promise + data: OneBotConfig['network']['websocketClients'][0]; + showType?: boolean; + onEdit: () => void; + onEnable: () => Promise; + onDelete: () => Promise; + onEnableDebug: () => Promise; } const WebsocketClientDisplayCard: React.FC = ( diff --git a/packages/napcat-webui-frontend/src/components/display_card/ws_server.tsx b/packages/napcat-webui-frontend/src/components/display_card/ws_server.tsx index 1f1e9ece..4c345def 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/ws_server.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/ws_server.tsx @@ -4,12 +4,12 @@ import NetworkDisplayCard from './common_card'; import type { NetworkDisplayCardFields } from './common_card'; interface WebsocketServerDisplayCardProps { - data: OneBotConfig['network']['websocketServers'][0] - showType?: boolean - onEdit: () => void - onEnable: () => Promise - onDelete: () => Promise - onEnableDebug: () => Promise + data: OneBotConfig['network']['websocketServers'][0]; + showType?: boolean; + onEdit: () => void; + onEnable: () => Promise; + onDelete: () => Promise; + onEnableDebug: () => Promise; } const WebsocketServerDisplayCard: React.FC = ( diff --git a/packages/napcat-webui-frontend/src/components/display_network_item.tsx b/packages/napcat-webui-frontend/src/components/display_network_item.tsx index 322977b3..2ad197d5 100644 --- a/packages/napcat-webui-frontend/src/components/display_network_item.tsx +++ b/packages/napcat-webui-frontend/src/components/display_network_item.tsx @@ -1,5 +1,7 @@ import { Card, CardBody } from '@heroui/card'; +import { useLocalStorage } from '@uidotdev/usehooks'; import clsx from 'clsx'; +import key from '@/const/key'; @@ -14,10 +16,16 @@ const NetworkItemDisplay: React.FC = ({ label, size = 'md', }) => { + const [backgroundImage] = useLocalStorage(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; + return ( 名称 - + 类型 - + 大小 - + 修改时间 操作 @@ -194,13 +194,13 @@ export default function FileTable ({ )} - {file.isDirectory ? '目录' : '文件'} - + {file.isDirectory ? '目录' : '文件'} + {isNaN(file.size) || file.isDirectory ? '-' : `${file.size} 字节`} - {new Date(file.mtime).toLocaleString()} + {new Date(file.mtime).toLocaleString()}
- -
- ))} -
- + + + )} + + +
+ } + value={searchValue} + onChange={(e) => setSearchValue(e.target.value)} + onClear={() => setSearchValue('')} + size="sm" + /> +
+ + + {Object.entries(data).map(([apiName, api]) => { + const isMatch = apiName.toLowerCase().includes(searchValue.toLowerCase()) || + api.description?.toLowerCase().includes(searchValue.toLowerCase()); + if (!isMatch) return null; + + const isSelected = apiName === selectedApi; + + return ( +
onSelect(apiName as OneBotHttpApiPath)} + onKeyDown={(e) => e.key === 'Enter' && onSelect(apiName as OneBotHttpApiPath)} + className="cursor-pointer focus:outline-none" + > + + +
+ + {api.description} + + + {apiName} + +
+
+
+
+ ); + })} +
+ + + ); }; diff --git a/packages/napcat-webui-frontend/src/components/qq_info_card.tsx b/packages/napcat-webui-frontend/src/components/qq_info_card.tsx index eb5e2bd2..3bb53cd6 100644 --- a/packages/napcat-webui-frontend/src/components/qq_info_card.tsx +++ b/packages/napcat-webui-frontend/src/components/qq_info_card.tsx @@ -1,8 +1,10 @@ import { Card, CardBody } from '@heroui/card'; import { Image } from '@heroui/image'; +import { useLocalStorage } from '@uidotdev/usehooks'; import clsx from 'clsx'; import { BsTencentQq } from 'react-icons/bs'; +import key from '@/const/key'; import { SelfInfo } from '@/types/user'; import PageLoading from './page_loading'; @@ -14,9 +16,14 @@ export interface QQInfoCardProps { } const QQInfoCard: React.FC = ({ data, error, loading }) => { + const [backgroundImage] = useLocalStorage(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; return ( @@ -32,9 +39,11 @@ const QQInfoCard: React.FC = ({ data, error, loading }) => { ) : ( -
- -
+ {!hasBackground && ( +
+ +
+ )}
= ({ data, error, loading }) => { />
-
+
{data?.nick || '未知用户'}
-
+
{data?.uin || 'Unknown'}
diff --git a/packages/napcat-webui-frontend/src/components/sidebar/index.tsx b/packages/napcat-webui-frontend/src/components/sidebar/index.tsx index 28a419a7..6d7932ed 100644 --- a/packages/napcat-webui-frontend/src/components/sidebar/index.tsx +++ b/packages/napcat-webui-frontend/src/components/sidebar/index.tsx @@ -1,15 +1,17 @@ import { Button } from '@heroui/button'; +import { useLocalStorage } from '@uidotdev/usehooks'; import clsx from 'clsx'; import { AnimatePresence, motion } from 'motion/react'; import React from 'react'; import { IoMdLogOut } from 'react-icons/io'; import { MdDarkMode, MdLightMode } from 'react-icons/md'; +import key from '@/const/key'; import useAuth from '@/hooks/auth'; import useDialog from '@/hooks/use-dialog'; import { useTheme } from '@/hooks/use-theme'; - import type { MenuItem } from '@/config/site'; + import Menus from './menus'; interface SideBarProps { @@ -22,6 +24,7 @@ const SideBar: React.FC = (props) => { const { open, items, onClose } = props; const { toggleTheme, isDark } = useTheme(); const { revokeAuth } = useAuth(); + const [b64img] = useLocalStorage(key.backgroundImage, ''); const dialog = useDialog(); const onRevokeAuth = () => { dialog.confirm({ @@ -47,7 +50,9 @@ const SideBar: React.FC = (props) => { void - name?: string - onBlur?: React.FocusEventHandler - disabled?: boolean - onChange?: React.ChangeEventHandler + label?: string; + description?: string; + value?: boolean; + onValueChange?: (value: boolean) => void; + name?: string; + onBlur?: React.FocusEventHandler; + disabled?: boolean; + onChange?: React.ChangeEventHandler; } const SwitchCard = forwardRef( @@ -22,9 +22,9 @@ const SwitchCard = forwardRef( = ({ @@ -28,12 +30,21 @@ const SystemInfoItem: React.FC = ({ value = '--', icon, endContent, + hasBackground = false, }) => { return ( -
+
{icon}
{title}
-
{value}
+
{value}
{endContent}
); @@ -261,7 +272,11 @@ const NewVersionTip = (props: NewVersionTipProps) => { ); }; -const NapCatVersion = () => { +interface NapCatVersionProps { + hasBackground?: boolean; +} + +const NapCatVersion: React.FC = ({ hasBackground = false }) => { const { data: packageData, loading: packageLoading, @@ -274,6 +289,7 @@ const NapCatVersion = () => { } + hasBackground={hasBackground} value={ packageError ? ( @@ -302,18 +318,28 @@ const SystemInfo: React.FC = (props) => { loading: qqVersionLoading, error: qqVersionError, } = useRequest(WebUIManager.getQQVersion); + const [backgroundImage] = useLocalStorage(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; + return ( - - + + 系统信息
- + } + hasBackground={hasBackground} value={ qqVersionError ? ( @@ -332,11 +358,13 @@ const SystemInfo: React.FC = (props) => { title='WebUI 版本' icon={} value='Next' + hasBackground={hasBackground} /> } value={archInfo} + hasBackground={hasBackground} />
diff --git a/packages/napcat-webui-frontend/src/components/system_status_display.tsx b/packages/napcat-webui-frontend/src/components/system_status_display.tsx index d80afb05..037b1886 100644 --- a/packages/napcat-webui-frontend/src/components/system_status_display.tsx +++ b/packages/napcat-webui-frontend/src/components/system_status_display.tsx @@ -1,10 +1,12 @@ import { Card, CardBody } from '@heroui/card'; import { Image } from '@heroui/image'; +import { useLocalStorage } from '@uidotdev/usehooks'; import clsx from 'clsx'; import { BiSolidMemoryCard } from 'react-icons/bi'; import { GiCpu } from 'react-icons/gi'; import bkg from '@/assets/images/bg/1AD934174C0107F14BAD8776D29C5F90.png'; +import key from '@/const/key'; import UsagePie from './usage_pie'; @@ -13,6 +15,7 @@ export interface SystemStatusItemProps { value?: string | number; size?: 'md' | 'lg'; unit?: string; + hasBackground?: boolean; } const SystemStatusItem: React.FC = ({ @@ -20,16 +23,26 @@ const SystemStatusItem: React.FC = ({ value = '-', size = 'md', unit, + hasBackground = false, }) => { return (
-
{title}
-
+
{title}
+
{value} {unit && {unit}}
@@ -53,9 +66,14 @@ const SystemStatusDisplay: React.FC = ({ data }) => { memoryUsage.system = (systemUsage / system) * 100; memoryUsage.qq = (qqUsage / system) * 100; } + const [backgroundImage] = useLocalStorage(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; return ( - +
= ({ data }) => {
-

+

CPU

- - - + + +
-

+

内存

@@ -98,16 +124,19 @@ const SystemStatusDisplay: React.FC = ({ data }) => { value={data?.memory.total} size='lg' unit='MB' + hasBackground={hasBackground} />
diff --git a/packages/napcat-webui-frontend/src/components/xterm.tsx b/packages/napcat-webui-frontend/src/components/xterm.tsx index 6cb1b2fc..7fb3eb6a 100644 --- a/packages/napcat-webui-frontend/src/components/xterm.tsx +++ b/packages/napcat-webui-frontend/src/components/xterm.tsx @@ -12,21 +12,21 @@ import { useTheme } from '@/hooks/use-theme'; export type XTermRef = { write: ( ...args: Parameters - ) => ReturnType - writeAsync: (data: Parameters[0]) => Promise + ) => ReturnType; + writeAsync: (data: Parameters[0]) => Promise; writeln: ( ...args: Parameters - ) => ReturnType - writelnAsync: (data: Parameters[0]) => Promise - clear: () => void - terminalRef: React.RefObject + ) => ReturnType; + writelnAsync: (data: Parameters[0]) => Promise; + clear: () => void; + terminalRef: React.RefObject; }; export interface XTermProps extends Omit, 'onInput' | 'onResize'> { - onInput?: (data: string) => void - onKey?: (key: string, event: KeyboardEvent) => void - onResize?: (cols: number, rows: number) => void // 新增属性 + onInput?: (data: string) => void; + onKey?: (key: string, event: KeyboardEvent) => void; + onResize?: (cols: number, rows: number) => void; // 新增属性 } const XTerm = forwardRef((props, ref) => { diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/config/index.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/config/index.tsx index f7bed85a..149f2d2a 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/config/index.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/config/index.tsx @@ -1,9 +1,11 @@ import { Card, CardBody } from '@heroui/card'; import { Tab, Tabs } from '@heroui/tabs'; +import { useLocalStorage } from '@uidotdev/usehooks'; import clsx from 'clsx'; -import { useMediaQuery } from 'react-responsive'; import { useNavigate, useSearchParams } from 'react-router-dom'; +import key from '@/const/key'; + import ChangePasswordCard from './change_password'; import LoginConfigCard from './login'; import OneBotConfigCard from './onebot'; @@ -12,24 +14,29 @@ import ThemeConfigCard from './theme'; import WebUIConfigCard from './webui'; export interface ConfigPageProps { - children?: React.ReactNode - size?: 'sm' | 'md' | 'lg' + children?: React.ReactNode; + size?: 'sm' | 'md' | 'lg'; } -const ConfingPageItem: React.FC = ({ +const ConfigPageItem: React.FC = ({ children, size = 'md', }) => { + const [backgroundImage] = useLocalStorage(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; + return ( - - -
+ + +
{children}
@@ -38,7 +45,6 @@ const ConfingPageItem: React.FC = ({ }; export default function ConfigPage () { - const isMediumUp = useMediaQuery({ minWidth: 768 }); const navigate = useNavigate(); const search = useSearchParams({ tab: 'onebot', @@ -46,53 +52,55 @@ export default function ConfigPage () { const tab = search.get('tab') ?? 'onebot'; return ( -
+
+ 其它配置 - NapCat WebUI { navigate(`/config?tab=${key}`); }} classNames={{ - tabList: 'sticky flex top-14 bg-opacity-50 backdrop-blur-sm', - panel: 'w-full relative', - base: 'md:!w-auto flex-grow-0 flex-shrink-0 mr-0', - cursor: 'bg-opacity-60 backdrop-blur-sm', + base: 'w-full flex-col items-center', + tabList: 'bg-white/40 dark:bg-black/20 backdrop-blur-md rounded-2xl p-1.5 shadow-sm border border-white/20 dark:border-white/5 mb-4 md:mb-8 w-full md:w-fit mx-auto overflow-x-auto hide-scrollbar', + cursor: 'bg-white/80 dark:bg-white/10 backdrop-blur-md shadow-sm rounded-xl', + tab: 'h-9 px-4 md:px-6', + tabContent: 'text-default-600 dark:text-default-300 font-medium group-data-[selected=true]:text-primary', + panel: 'w-full relative p-0', }} > - + - + - + - + - + - + - + - + - + - + - + - +
diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/config/onebot.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/config/onebot.tsx index f6423fc2..6c9c4551 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/config/onebot.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/config/onebot.tsx @@ -74,6 +74,11 @@ const OneBotConfigCard = () => { {...field} label='音乐签名地址' placeholder='请输入音乐签名地址' + classNames={{ + inputWrapper: + 'bg-default-100/50 dark:bg-white/5 backdrop-blur-md border border-transparent hover:bg-default-200/50 dark:hover:bg-white/10 transition-all shadow-sm data-[hover=true]:border-default-300', + input: 'bg-transparent text-default-700 placeholder:text-default-400', + }} /> )} /> diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/config/server.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/config/server.tsx index 0d00c325..b1a6e20d 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/config/server.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/config/server.tsx @@ -1,5 +1,4 @@ import { Input } from '@heroui/input'; -import { Switch } from '@heroui/switch'; import { useRequest } from 'ahooks'; import { useEffect } from 'react'; import { Controller, useForm } from 'react-hook-form'; @@ -7,6 +6,7 @@ import toast from 'react-hot-toast'; import SaveButtons from '@/components/button/save_buttons'; import PageLoading from '@/components/page_loading'; +import SwitchCard from '@/components/switch_card'; import WebUIManager from '@/controllers/webui_manager'; @@ -79,8 +79,8 @@ const ServerConfigCard = () => { <> 服务器配置 - NapCat WebUI
-
-
服务器配置
+
+
服务器配置
{ description='服务器监听的IP地址,0.0.0.0表示监听所有网卡' isDisabled={!!configError} errorMessage={configError ? '获取配置失败' : undefined} + classNames={{ + inputWrapper: + 'bg-default-100/50 dark:bg-white/5 backdrop-blur-md border border-transparent hover:bg-default-200/50 dark:hover:bg-white/10 transition-all shadow-sm data-[hover=true]:border-default-300', + input: 'bg-transparent text-default-700 placeholder:text-default-400', + }} /> )} /> @@ -109,6 +114,11 @@ const ServerConfigCard = () => { isDisabled={!!configError} errorMessage={configError ? '获取配置失败' : undefined} onChange={(e) => field.onChange(parseInt(e.target.value) || 0)} + classNames={{ + inputWrapper: + 'bg-default-100/50 dark:bg-white/5 backdrop-blur-md border border-transparent hover:bg-default-200/50 dark:hover:bg-white/10 transition-all shadow-sm data-[hover=true]:border-default-300', + input: 'bg-transparent text-gray-800 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500', + }} /> )} /> @@ -126,47 +136,42 @@ const ServerConfigCard = () => { isDisabled={!!configError} errorMessage={configError ? '获取配置失败' : undefined} onChange={(e) => field.onChange(parseInt(e.target.value) || 0)} + classNames={{ + inputWrapper: + 'bg-default-100/50 dark:bg-white/5 backdrop-blur-md border border-transparent hover:bg-default-200/50 dark:hover:bg-white/10 transition-all shadow-sm data-[hover=true]:border-default-300', + input: 'bg-transparent text-gray-800 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500', + }} /> )} />
-
-
安全配置
+
+
安全配置
( - field.onChange(value)} - isDisabled={!!configError} - > -
- 禁用WebUI - - 启用后将完全禁用WebUI服务,需要重启生效 - -
-
+ field.onChange(value)} + disabled={!!configError} + label='禁用WebUI' + description='启用后将完全禁用WebUI服务,需要重启生效' + /> )} /> ( - field.onChange(value)} - isDisabled={!!configError} - > -
- 禁用非局域网访问 - - 启用后只允许局域网内的设备访问WebUI,提高安全性 - -
-
+ field.onChange(value)} + disabled={!!configError} + label='禁用非局域网访问' + description='启用后只允许局域网内的设备访问WebUI,提高安全性' + /> )} />
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 8feaabe9..af18425f 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/config/webui.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/config/webui.tsx @@ -93,11 +93,13 @@ const WebUIConfigCard = () => { <> WebUI配置 - NapCat WebUI
-
WebUI字体
+
WebUI字体
此项不需要手动保存,上传成功后需清空网页缓存并刷新 { try { await FileManager.uploadWebUIFont(file); @@ -124,26 +126,35 @@ const WebUIConfigCard = () => {
-
背景图
+
背景图
} + render={({ field }) => ( + + )} />
-
自定义图标
+
自定义图标
{siteConfig.navItems.map((item) => ( } + render={({ field }) => ( + + )} /> ))}
-
Passkey认证
+
Passkey认证
注册Passkey后,您可以更便捷地登录WebUI,无需每次输入token
diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/debug/http/index.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/debug/http/index.tsx index 4163a97a..2418a245 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/debug/http/index.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/debug/http/index.tsx @@ -1,6 +1,5 @@ import { Button } from '@heroui/button'; import clsx from 'clsx'; -import { motion } from 'motion/react'; import { useEffect, useRef, useState } from 'react'; import { TbSquareRoundedChevronLeftFilled } from 'react-icons/tb'; @@ -27,36 +26,39 @@ export default function HttpDebug () { return ( <> HTTP调试 - NapCat WebUI - -
- + { + setSelectedApi(api); + // Auto-close sidebar on mobile after selection + if (window.innerWidth < 768) { + setOpenSideBar(false); + } + }} + openSideBar={openSideBar} + onToggle={setOpenSideBar} + /> +
- - - + {/* Toggle Button Container - positioned on top-left of content if sidebar is closed */} +
+ +
+ + +
); diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/debug/websocket/index.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/debug/websocket/index.tsx index f75c53ea..f9a0e942 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/debug/websocket/index.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/debug/websocket/index.tsx @@ -48,8 +48,8 @@ export default function WSDebug () { return ( <> Websocket调试 - NapCat WebUI -
- +
+
(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; + return ( -
-
- +
+
+
+ - + - - + + - {((selectedFiles instanceof Set && selectedFiles.size > 0) || - selectedFiles === 'all') && ( - <> - - + + + + )} +
+ +
+ + {currentPath.split('/').map((part, index, parts) => ( + { - setMoveTargetPath(''); - setIsMoveModalOpen(true); + const newPath = parts.slice(0, index + 1).join('/'); + navigate(`/file_manager#${encodeURIComponent(newPath)}`); }} - className='text-sm' - startContent={} > - ( - {selectedFiles instanceof Set ? selectedFiles.size : files.length} - ) - - - - )} - - {currentPath.split('/').map((part, index, parts) => ( - { - const newPath = parts.slice(0, index + 1).join('/'); - navigate(`/file_manager#${encodeURIComponent(newPath)}`); - }} - > - {part} - - ))} - - setJumpPath(e.target.value)} - onKeyDown={(e) => { - if (e.key === 'Enter' && jumpPath.trim() !== '') { - navigate(`/file_manager#${encodeURIComponent(jumpPath.trim())}`); - } - }} - className='ml-auto w-64' - /> + {part} + + ))} + + setJumpPath(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter' && jumpPath.trim() !== '') { + navigate(`/file_manager#${encodeURIComponent(jumpPath.trim())}`); + } + }} + className='w-full md:w-64' + classNames={{ + inputWrapper: 'bg-white/40 dark:bg-black/20 backdrop-blur-md', + }} + /> +
= ({ setArchInfo }) => { const DashboardIndexPage: React.FC = () => { const [archInfo, setArchInfo] = useState(); + // @ts-ignore + const [backgroundImage] = useLocalStorage(key.backgroundImage, ''); + const hasBackground = !!backgroundImage; return ( <> @@ -105,7 +111,10 @@ const DashboardIndexPage: React.FC = () => {
- + diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx index 5aa4ea93..f6d93253 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx @@ -375,9 +375,8 @@ export default function NetworkPage () { - - ))} - - + {tab.title} + + + ))} + + + )}