From e6b351e39cc13b0d88e539ab6a0ffce0e15677b9 Mon Sep 17 00:00:00 2001 From: imbytecat Date: Tue, 12 May 2026 01:01:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E4=BC=98=E5=8C=96=E7=9C=8B?= =?UTF-8?q?=E6=9D=BF=E5=92=8C=E8=AE=BE=E5=A4=87=E5=88=97=E8=A1=A8=E4=BD=93?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/batteries.tsx | 66 ++++++++++++++++++++++++++++++++-------- src/routes/index.tsx | 35 +++++++++++++-------- 2 files changed, 76 insertions(+), 25 deletions(-) diff --git a/src/routes/batteries.tsx b/src/routes/batteries.tsx index 0deb8d7..fe612c9 100644 --- a/src/routes/batteries.tsx +++ b/src/routes/batteries.tsx @@ -1,12 +1,12 @@ import { useQuery } from '@tanstack/react-query' import { createFileRoute, Link, useNavigate } from '@tanstack/react-router' import { createColumnHelper, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table' -import { ArrowLeft, Battery, BatteryCharging, BatteryLow, FilterX, Search, Zap } from 'lucide-react' +import { ArrowLeft, Battery, BatteryCharging, BatteryLow, FilterX, Search, X, Zap } from 'lucide-react' import { useEffect, useMemo, useState } from 'react' import { z } from 'zod' import { orpc } from '@/client/orpc' import { MotionCardDiv, MotionHeader, MotionSection, MotionTableRow } from '@/components/motion' -import { Badge, Button, Card, Input, SectionTitle, Select, SelectOption } from '@/components/ui' +import { Badge, Button, Card, EmptyState, Input, SectionTitle, Select, SelectOption, Skeleton } from '@/components/ui' import type { BatteryInfo, BatteryListSort, PowerStatus } from '@/domain/battery' import { BATTERY_LIST_SORT, BATTERY_LIST_SORT_VALUES, POWER_STATUS, POWER_STATUS_VALUES } from '@/domain/battery' @@ -14,6 +14,7 @@ const pageSizeOptions = [20, 50, 100] as const type PageSizeOption = (typeof pageSizeOptions)[number] const firstPageCursor = '__FIRST_PAGE__' const allPowerStatusValue = 'all' +const loadingRowKeys = Array.from({ length: 10 }, (_, index) => `loading-row-${index}`) const searchFilterSchema = z.preprocess( (value) => (typeof value === 'string' ? value.trim() || undefined : value), @@ -314,10 +315,20 @@ function BatteriesPage() { type="text" placeholder="搜索设备名称或编号..." maxLength={100} - className="pl-9" + className="pl-9 pr-9" value={localSearch} onChange={(e) => setLocalSearch(e.target.value)} /> + {localSearch && ( + + )} @@ -421,9 +432,9 @@ function BatteriesPage() { -
+
- + {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( @@ -436,15 +447,46 @@ function BatteriesPage() { {isPending && !isPlaceholderData ? ( - - - + loadingRowKeys.map((key) => ( + + + + + + + + )) ) : data?.items.length === 0 ? ( - ) : ( diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 2b56269..b8cde01 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -15,7 +15,7 @@ import { import type { NameType, ValueType } from 'recharts/types/component/DefaultTooltipContent' import { orpc } from '@/client/orpc' import { MotionCardArticle, MotionCardDiv, MotionHeader, MotionSection } from '@/components/motion' -import { Badge, Card, SectionTitle } from '@/components/ui' +import { Badge, Card, EmptyState, SectionTitle } from '@/components/ui' import type { DashboardSnapshot, DeviceStatus } from '@/domain/battery' import { BATTERY_LIST_SORT, DEVICE_STATUS } from '@/domain/battery' @@ -270,19 +270,19 @@ function Dashboard() { - + - + - + Math.floor(min) - 2, (max: number) => Math.ceil(max) + 2]} - tick={{ fill: '#71717A', fontSize: 11 }} + tick={{ fill: '#A1A1AA', fontSize: 12 }} axisLine={false} tickLine={false} tickFormatter={(v: number) => `${v}%`} @@ -295,20 +295,21 @@ function Dashboard() { borderRadius: 8, fontSize: 13, color: '#F4F4F5', + boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.5)', }} - itemStyle={{ color: '#A1A1AA' }} + itemStyle={{ color: '#E4E4E7', fontWeight: 500 }} formatter={formatChartTooltip} - labelStyle={{ color: '#71717A', marginBottom: 4 }} + labelStyle={{ color: '#A1A1AA', marginBottom: 6 }} /> @@ -358,8 +359,12 @@ function Dashboard() { ) : ( -
- 暂无可用的健康趋势数据。 +
+ } + title="暂无健康趋势数据" + description="当前设备数据不足以生成可靠的健康趋势预测,请等待系统收集更多数据。" + />
)}
@@ -590,8 +595,12 @@ function Dashboard() { )) ) : ( - )}
- 加载中… -
+ + + + + +
+ + +
+
+ + + +
- 未找到符合条件的设备 + + } + title="未找到符合条件的设备" + description={ + hasActiveFilters ? '尝试调整筛选条件或清除筛选以查看更多设备。' : '当前暂无设备数据接入。' + } + action={ + hasActiveFilters ? ( + + ) : undefined + } + />
- 暂无设备数据 + + } + title="暂无设备数据" + description="当前没有可用于健康分析的设备记录。" + />