🎨 UI/UX: Replace emoji icons with Semi UI components and enhance card design

BREAKING CHANGE: Replace all emoji icons with Semi UI icons in statistics cards

- Replace emoji icons with corresponding Semi UI icons:
  - 💰 -> IconMoneyExchangeStroked
  - 📊 -> IconHistogram
  - 🔄 -> IconRotate
  - 💲 -> IconCoinMoneyStroked
  - 🔤 -> IconTextStroked
  - 📈 -> IconPulse
  - ⏱️ -> IconStopwatchStroked
  - 📝 -> IconTypograph

- Add Avatar component as circular background for icons
  - Implement color-coded avatars for each statistic card
  - Set avatar size to 'medium' for better visual balance
  - Add appropriate color mapping for each statistic type

- Adjust layout spacing
  - Reduce top margin from mb-6 to mb-4 for better vertical rhythm
  - Maintain consistent spacing in card layouts

- Import necessary Semi UI components and icons
  - Add Avatar component import
  - Add required icon imports from @douyinfe/semi-icons

This change improves the overall UI consistency and professional appearance by adopting Semi UI's design system components.
This commit is contained in:
Apple\Apple
2025-05-25 13:30:47 +08:00
parent de98d11d65
commit 18344ae580

View File

@@ -8,8 +8,20 @@ import {
Typography, Typography,
IconButton, IconButton,
Modal, Modal,
Avatar,
} from '@douyinfe/semi-ui'; } from '@douyinfe/semi-ui';
import { IconRefresh, IconSearch } from '@douyinfe/semi-icons'; import {
IconRefresh,
IconSearch,
IconMoneyExchangeStroked,
IconHistogram,
IconRotate,
IconCoinMoneyStroked,
IconTextStroked,
IconPulse,
IconStopwatchStroked,
IconTypograph,
} from '@douyinfe/semi-icons';
import { VChart } from '@visactor/react-vchart'; import { VChart } from '@visactor/react-vchart';
import { import {
API, API,
@@ -436,38 +448,44 @@ const Detail = (props) => {
{ {
title: t('当前余额'), title: t('当前余额'),
value: renderQuota(userState?.user?.quota), value: renderQuota(userState?.user?.quota),
icon: '💰', icon: <IconMoneyExchangeStroked />,
color: 'bg-blue-50', color: 'bg-blue-50',
avatarColor: 'blue',
}, },
{ {
title: t('历史消耗'), title: t('历史消耗'),
value: renderQuota(userState?.user?.used_quota), value: renderQuota(userState?.user?.used_quota),
icon: '📊', icon: <IconHistogram />,
color: 'bg-purple-50', color: 'bg-purple-50',
avatarColor: 'purple',
}, },
{ {
title: t('请求次数'), title: t('请求次数'),
value: userState.user?.request_count, value: userState.user?.request_count,
icon: '🔄', icon: <IconRotate />,
color: 'bg-green-50', color: 'bg-green-50',
avatarColor: 'green',
}, },
{ {
title: t('统计额度'), title: t('统计额度'),
value: renderQuota(consumeQuota), value: renderQuota(consumeQuota),
icon: '💲', icon: <IconCoinMoneyStroked />,
color: 'bg-yellow-50', color: 'bg-yellow-50',
avatarColor: 'yellow',
}, },
{ {
title: t('统计Tokens'), title: t('统计Tokens'),
value: isNaN(consumeTokens) ? 0 : consumeTokens, value: isNaN(consumeTokens) ? 0 : consumeTokens,
icon: '🔤', icon: <IconTextStroked />,
color: 'bg-pink-50', color: 'bg-pink-50',
avatarColor: 'pink',
}, },
{ {
title: t('统计次数'), title: t('统计次数'),
value: times, value: times,
icon: '📈', icon: <IconPulse />,
color: 'bg-teal-50', color: 'bg-teal-50',
avatarColor: 'cyan',
}, },
{ {
title: t('平均RPM'), title: t('平均RPM'),
@@ -475,8 +493,9 @@ const Detail = (props) => {
times / times /
((Date.parse(end_timestamp) - Date.parse(start_timestamp)) / 60000) ((Date.parse(end_timestamp) - Date.parse(start_timestamp)) / 60000)
).toFixed(3), ).toFixed(3),
icon: '⏱️', icon: <IconStopwatchStroked />,
color: 'bg-indigo-50', color: 'bg-indigo-50',
avatarColor: 'indigo',
}, },
{ {
title: t('平均TPM'), title: t('平均TPM'),
@@ -485,8 +504,9 @@ const Detail = (props) => {
((Date.parse(end_timestamp) - Date.parse(start_timestamp)) / 60000); ((Date.parse(end_timestamp) - Date.parse(start_timestamp)) / 60000);
return isNaN(tpm) ? '0' : tpm.toFixed(3); return isNaN(tpm) ? '0' : tpm.toFixed(3);
})(), })(),
icon: '📝', icon: <IconTypograph />,
color: 'bg-orange-50', color: 'bg-orange-50',
avatarColor: 'orange',
}, },
]; ];
@@ -511,7 +531,7 @@ const Detail = (props) => {
return ( return (
<div className="bg-gray-50 min-h-screen"> <div className="bg-gray-50 min-h-screen">
<div className="flex items-center justify-between mb-6"> <div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-semibold text-gray-800">{getGreeting()}</h2> <h2 className="text-2xl font-semibold text-gray-800">{getGreeting()}</h2>
<div className="flex gap-3"> <div className="flex gap-3">
<IconButton <IconButton
@@ -600,7 +620,13 @@ const Detail = (props) => {
headerLine={false} headerLine={false}
> >
<div className="flex items-center"> <div className="flex items-center">
<div className="text-2xl mr-3">{stat.icon}</div> <Avatar
className="mr-3"
size="medium"
color={stat.avatarColor}
>
{stat.icon}
</Avatar>
<div> <div>
<div className="text-sm text-gray-500">{stat.title}</div> <div className="text-sm text-gray-500">{stat.title}</div>
<div className="text-xl font-semibold">{stat.value}</div> <div className="text-xl font-semibold">{stat.value}</div>