Revert "Refactor UI components for consistent styling"

This reverts commit 7e6035d98b.
This commit is contained in:
手瓜一十雪 2025-12-22 14:04:26 +08:00
parent 7e6035d98b
commit 7f81bf45ee
6 changed files with 137 additions and 65 deletions

View File

@ -188,20 +188,10 @@ export const UpdateNapCatHandler: RequestHandler = async (_req, res) => {
try {
// 获取最新release信息
const latestRelease = await getLatestRelease() as Release;
// 验证 release 响应
if (!latestRelease || !latestRelease.tag_name) {
throw new Error('无法获取最新版本信息,请稍后重试');
}
if (!latestRelease.assets || !Array.isArray(latestRelease.assets)) {
throw new Error('无法获取下载资源列表,可能是 GitHub API 请求限制,请稍后重试');
}
const ReleaseName = WebUiDataRuntime.getWorkingEnv() === NapCatCoreWorkingEnv.Framework ? 'NapCat.Framework.zip' : 'NapCat.Shell.zip';
const shellZipAsset = latestRelease.assets.find(asset => asset.name === ReleaseName);
if (!shellZipAsset) {
throw new Error(`未找到${ReleaseName}文件,可用的资源: ${latestRelease.assets.map(a => a.name).join(', ')}`);
throw new Error(`未找到${ReleaseName}文件`);
}
// 创建临时目录
@ -289,13 +279,12 @@ export const UpdateNapCatHandler: RequestHandler = async (_req, res) => {
// 发送成功响应
const message = failedFiles.length > 0
? `更新完成,重启应用以应用剩余${failedFiles.length}个文件的更新`
: '更新完成,请重启 NapCat 以应用更新';
: '更新完成';
sendSuccess(res, {
status: 'completed',
message,
newVersion: latestRelease.tag_name,
failedFilesCount: failedFiles.length,
needRestart: true
failedFilesCount: failedFiles.length
});
} catch (error) {

View File

@ -1,22 +1,29 @@
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';
export interface QQInfoCardProps {
data?: SelfInfo
error?: Error
loading?: boolean
data?: SelfInfo;
error?: Error;
loading?: boolean;
}
const QQInfoCard: React.FC<QQInfoCardProps> = ({ data, error, loading }) => {
const [backgroundImage] = useLocalStorage<string>(key.backgroundImage, '');
const hasBackground = !!backgroundImage;
return (
<Card
className='relative bg-primary-100 bg-opacity-60 overflow-hidden flex-shrink-0 shadow-md shadow-primary-300 dark:shadow-primary-50'
className={clsx(
'relative backdrop-blur-sm border border-white/40 dark:border-white/10 overflow-hidden flex-shrink-0 shadow-sm',
hasBackground ? 'bg-white/10 dark:bg-black/10' : 'bg-white/60 dark:bg-black/40'
)}
shadow='none'
radius='lg'
>
@ -31,28 +38,40 @@ const QQInfoCard: React.FC<QQInfoCardProps> = ({ data, error, loading }) => {
</CardBody>
)
: (
<CardBody className='flex-row items-center gap-2 overflow-hidden relative'>
<div className='absolute right-0 bottom-0 text-5xl text-primary-400'>
<BsTencentQq />
</div>
<CardBody className='flex-row items-center gap-4 overflow-hidden relative p-4'>
{!hasBackground && (
<div className='absolute right-[-10px] bottom-[-10px] text-7xl text-default-400/10 rotate-12 pointer-events-none'>
<BsTencentQq />
</div>
)}
<div className='relative flex-shrink-0 z-10'>
<Image
src={
data?.avatarUrl ??
`https://q1.qlogo.cn/g?b=qq&nk=${data?.uin}&s=1`
}
className='shadow-md rounded-full w-12 aspect-square'
data?.avatarUrl ??
`https://q1.qlogo.cn/g?b=qq&nk=${data?.uin}&s=1`
}
className='shadow-sm rounded-full w-14 aspect-square ring-2 ring-white/50 dark:ring-white/10'
/>
<div
className={clsx(
'w-4 h-4 rounded-full absolute right-0.5 bottom-0 border-2 border-primary-100 z-10',
data?.online ? 'bg-green-500' : 'bg-gray-500'
'w-3.5 h-3.5 rounded-full absolute right-0.5 bottom-0.5 border-2 border-white dark:border-zinc-900 z-10',
data?.online ? 'bg-success-500' : 'bg-default-400'
)}
/>
</div>
<div className='flex-col justify-center'>
<div className='text-lg truncate'>{data?.nick}</div>
<div className='text-primary-500 text-sm'>{data?.uin}</div>
<div className='flex-col justify-center z-10'>
<div className={clsx(
'text-xl font-bold truncate mb-0.5',
hasBackground ? 'text-white drop-shadow-sm' : 'text-default-800 dark:text-gray-100'
)}>
{data?.nick || '未知用户'}
</div>
<div className={clsx(
'font-mono text-xs tracking-wider',
hasBackground ? 'text-white/80' : 'text-default-500 opacity-80'
)}>
{data?.uin || 'Unknown'}
</div>
</div>
</CardBody>
)}

View File

@ -3,15 +3,16 @@ import { Button } from '@heroui/button';
import { Chip } from '@heroui/chip';
import { Spinner } from '@heroui/spinner';
import { Tooltip } from '@heroui/tooltip';
import { useLocalStorage } from '@uidotdev/usehooks';
import { useRequest } from 'ahooks';
import clsx from 'clsx';
import { FaCircleInfo, FaInfo, FaQq } from 'react-icons/fa6';
import { IoLogoChrome, IoLogoOctocat } from 'react-icons/io';
import { RiMacFill } from 'react-icons/ri';
import { useState } from 'react';
import toast from 'react-hot-toast';
import key from '@/const/key';
import WebUIManager from '@/controllers/webui_manager';
import useDialog from '@/hooks/use-dialog';
@ -21,6 +22,7 @@ export interface SystemInfoItemProps {
icon?: React.ReactNode;
value?: React.ReactNode;
endContent?: React.ReactNode;
hasBackground?: boolean;
}
const SystemInfoItem: React.FC<SystemInfoItemProps> = ({
@ -28,12 +30,21 @@ const SystemInfoItem: React.FC<SystemInfoItemProps> = ({
value = '--',
icon,
endContent,
hasBackground = false,
}) => {
return (
<div className='flex text-sm gap-1 p-2 items-center shadow-sm shadow-primary-100 dark:shadow-primary-100 rounded text-primary-400'>
{icon}
<div className='w-24'>{title}</div>
<div className='text-primary-200'>{value}</div>
<div className={clsx(
'flex text-sm gap-2 p-3 items-center rounded-lg border border-white/20 transition-colors',
hasBackground
? 'bg-white/10 hover:bg-white/20 text-white/90'
: 'bg-white/50 dark:bg-white/5 hover:bg-white/70 dark:hover:bg-white/10 text-default-600 dark:text-gray-300'
)}>
<div className="text-lg opacity-80">{icon}</div>
<div className='w-24 font-medium'>{title}</div>
<div className={clsx(
'text-xs font-mono',
hasBackground ? 'text-white/70' : 'text-default-500'
)}>{value}</div>
<div className='ml-auto'>{endContent}</div>
</div>
);
@ -261,7 +272,11 @@ const NewVersionTip = (props: NewVersionTipProps) => {
);
};
const NapCatVersion = () => {
interface NapCatVersionProps {
hasBackground?: boolean;
}
const NapCatVersion: React.FC<NapCatVersionProps> = ({ hasBackground = false }) => {
const {
data: packageData,
loading: packageLoading,
@ -274,6 +289,7 @@ const NapCatVersion = () => {
<SystemInfoItem
title='NapCat 版本'
icon={<IoLogoOctocat className='text-xl' />}
hasBackground={hasBackground}
value={
packageError
? (
@ -302,18 +318,28 @@ const SystemInfo: React.FC<SystemInfoProps> = (props) => {
loading: qqVersionLoading,
error: qqVersionError,
} = useRequest(WebUIManager.getQQVersion);
const [backgroundImage] = useLocalStorage<string>(key.backgroundImage, '');
const hasBackground = !!backgroundImage;
return (
<Card className='bg-opacity-60 shadow-sm shadow-primary-100 dark:shadow-primary-100 overflow-visible flex-1'>
<CardHeader className='pb-0 items-center gap-1 text-primary-500 font-extrabold'>
<FaCircleInfo className='text-lg' />
<Card className={clsx(
'backdrop-blur-sm border border-white/40 dark:border-white/10 shadow-sm overflow-visible flex-1',
hasBackground ? 'bg-white/10 dark:bg-black/10' : 'bg-white/60 dark:bg-black/40'
)}>
<CardHeader className={clsx(
'pb-0 items-center gap-2 font-bold px-4 pt-4',
hasBackground ? 'text-white drop-shadow-sm' : 'text-default-700 dark:text-white'
)}>
<FaCircleInfo className='text-lg opacity-80' />
<span></span>
</CardHeader>
<CardBody className='flex-1'>
<div className='flex flex-col justify-between h-full'>
<NapCatVersion />
<div className='flex flex-col gap-2 justify-between h-full'>
<NapCatVersion hasBackground={hasBackground} />
<SystemInfoItem
title='QQ 版本'
icon={<FaQq className='text-lg' />}
hasBackground={hasBackground}
value={
qqVersionError
? (
@ -332,11 +358,13 @@ const SystemInfo: React.FC<SystemInfoProps> = (props) => {
title='WebUI 版本'
icon={<IoLogoChrome className='text-xl' />}
value='Next'
hasBackground={hasBackground}
/>
<SystemInfoItem
title='系统版本'
icon={<RiMacFill className='text-xl' />}
value={archInfo}
hasBackground={hasBackground}
/>
</div>
</CardBody>

View File

@ -1,18 +1,21 @@
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';
export interface SystemStatusItemProps {
title: string
value?: string | number
size?: 'md' | 'lg'
unit?: string
title: string;
value?: string | number;
size?: 'md' | 'lg';
unit?: string;
hasBackground?: boolean;
}
const SystemStatusItem: React.FC<SystemStatusItemProps> = ({
@ -20,25 +23,35 @@ const SystemStatusItem: React.FC<SystemStatusItemProps> = ({
value = '-',
size = 'md',
unit,
hasBackground = false,
}) => {
return (
<div
className={clsx(
'shadow-sm shadow-primary-100 p-2 rounded-md text-sm bg-content1 bg-opacity-30',
size === 'lg' ? 'col-span-2' : 'col-span-1 flex justify-between'
'p-2 rounded-lg text-sm border border-white/20 transition-colors',
size === 'lg' ? 'col-span-2' : 'col-span-1 flex justify-between',
hasBackground
? 'bg-white/10 hover:bg-white/20'
: 'bg-white/50 dark:bg-white/5 hover:bg-white/70 dark:hover:bg-white/10'
)}
>
<div className='w-24'>{title}</div>
<div className='text-default-400'>
<div className={clsx(
'w-24 font-medium',
hasBackground ? 'text-white/90' : 'text-default-600'
)}>{title}</div>
<div className={clsx(
'font-mono text-xs',
hasBackground ? 'text-white/70' : 'text-default-500'
)}>
{value}
{unit}
{unit && <span className="ml-0.5 opacity-70">{unit}</span>}
</div>
</div>
);
};
export interface SystemStatusDisplayProps {
data?: SystemStatus
data?: SystemStatus;
}
const SystemStatusDisplay: React.FC<SystemStatusDisplayProps> = ({ data }) => {
@ -53,9 +66,14 @@ const SystemStatusDisplay: React.FC<SystemStatusDisplayProps> = ({ data }) => {
memoryUsage.system = (systemUsage / system) * 100;
memoryUsage.qq = (qqUsage / system) * 100;
}
const [backgroundImage] = useLocalStorage<string>(key.backgroundImage, '');
const hasBackground = !!backgroundImage;
return (
<Card className='bg-opacity-60 shadow-sm shadow-primary-100 col-span-1 lg:col-span-2 relative overflow-hidden'>
<Card className={clsx(
'backdrop-blur-sm border border-white/40 dark:border-white/10 shadow-sm col-span-1 lg:col-span-2 relative overflow-hidden',
hasBackground ? 'bg-white/10 dark:bg-black/10' : 'bg-white/60 dark:bg-black/40'
)}>
<div className='absolute h-full right-0 top-0'>
<Image
src={bkg}
@ -69,27 +87,35 @@ const SystemStatusDisplay: React.FC<SystemStatusDisplayProps> = ({ data }) => {
</div>
<CardBody className='overflow-visible md:flex-row gap-4 items-center justify-stretch z-10'>
<div className='flex-1 w-full md:max-w-96'>
<h2 className='text-lg font-semibold flex items-center gap-1 text-primary-400'>
<GiCpu className='text-xl' />
<h2 className={clsx(
'text-lg font-semibold flex items-center gap-2 mb-2',
hasBackground ? 'text-white drop-shadow-sm' : 'text-default-700 dark:text-gray-200'
)}>
<GiCpu className='text-xl opacity-80' />
<span>CPU</span>
</h2>
<div className='grid grid-cols-2 gap-2'>
<SystemStatusItem title='型号' value={data?.cpu.model} size='lg' />
<SystemStatusItem title='内核数' value={data?.cpu.core} />
<SystemStatusItem title='主频' value={data?.cpu.speed} unit='GHz' />
<SystemStatusItem title='型号' value={data?.cpu.model} size='lg' hasBackground={hasBackground} />
<SystemStatusItem title='内核数' value={data?.cpu.core} hasBackground={hasBackground} />
<SystemStatusItem title='主频' value={data?.cpu.speed} unit='GHz' hasBackground={hasBackground} />
<SystemStatusItem
title='使用率'
value={data?.cpu.usage.system}
unit='%'
hasBackground={hasBackground}
/>
<SystemStatusItem
title='QQ主线程'
value={data?.cpu.usage.qq}
unit='%'
hasBackground={hasBackground}
/>
</div>
<h2 className='text-lg font-semibold flex items-center gap-1 text-primary-400 mt-2'>
<BiSolidMemoryCard className='text-xl' />
<h2 className={clsx(
'text-lg font-semibold flex items-center gap-2 mb-2 mt-4',
hasBackground ? 'text-white drop-shadow-sm' : 'text-default-700 dark:text-gray-200'
)}>
<BiSolidMemoryCard className='text-xl opacity-80' />
<span></span>
</h2>
<div className='grid grid-cols-2 gap-2'>
@ -98,16 +124,19 @@ const SystemStatusDisplay: React.FC<SystemStatusDisplayProps> = ({ data }) => {
value={data?.memory.total}
size='lg'
unit='MB'
hasBackground={hasBackground}
/>
<SystemStatusItem
title='使用量'
value={data?.memory.usage.system}
unit='MB'
hasBackground={hasBackground}
/>
<SystemStatusItem
title='QQ主线程'
value={data?.memory.usage.qq}
unit='MB'
hasBackground={hasBackground}
/>
</div>
</div>

View File

@ -99,10 +99,8 @@ const Layout: React.FC<{ children: React.ReactNode; }> = ({ children }) => {
transition={{ duration: 0.4 }}
className={clsx(
'flex-1 overflow-y-auto',
'bg-white/60 dark:bg-black/40 backdrop-blur-xl',
'shadow-[0_8px_32px_0_rgba(31,38,135,0.07)]',
'transition-all duration-300 ease-in-out',
openSideBar ? 'm-3 ml-0 rounded-3xl border border-white/40 dark:border-white/10' : 'm-0 rounded-none',
openSideBar ? 'ml-0' : 'ml-0',
'pb-10 md:pb-0'
)}
>

View File

@ -1,6 +1,9 @@
import { Card, CardBody } from '@heroui/card';
import { useLocalStorage } from '@uidotdev/usehooks';
import { useRequest } from 'ahooks';
import clsx from 'clsx';
import { useCallback, useEffect, useState, useRef } from 'react';
import key from '@/const/key';
import toast from 'react-hot-toast';
@ -92,6 +95,9 @@ const SystemStatusCard: React.FC<SystemStatusCardProps> = ({ setArchInfo }) => {
const DashboardIndexPage: React.FC = () => {
const [archInfo, setArchInfo] = useState<string>();
// @ts-ignore
const [backgroundImage] = useLocalStorage<string>(key.backgroundImage, '');
const hasBackground = !!backgroundImage;
return (
<>
@ -105,7 +111,10 @@ const DashboardIndexPage: React.FC = () => {
<SystemStatusCard setArchInfo={setArchInfo} />
</div>
<Networks />
<Card className='bg-opacity-60 shadow-sm shadow-primary-100'>
<Card className={clsx(
'backdrop-blur-sm border border-white/40 dark:border-white/10 shadow-sm transition-all',
hasBackground ? 'bg-white/10 dark:bg-black/10' : 'bg-white/60 dark:bg-black/40'
)}>
<CardBody>
<Hitokoto />
</CardBody>