Просмотр исходного кода

♻️ refactor(InvitationCard): restructure cards with title prop and clean up styling

- Move card titles (earnings, total revenue, invitations) to Card title prop for consistency
- Remove custom color classes in favor of Semi-UI's built-in type system
- Standardize Text component usage with strong and tertiary types
- Improve code maintainability and visual consistency across all cards
- Align structure with existing reward description card pattern
t0ng7u 6 месяцев назад
Родитель
Сommit
6c94573323

+ 18 - 2
web/src/components/dashboard/StatsCards.jsx

@@ -18,8 +18,10 @@ For commercial licensing, please contact support@quantumnous.com
 */
 */
 
 
 import React from 'react';
 import React from 'react';
-import { Card, Avatar, Skeleton } from '@douyinfe/semi-ui';
+import { Card, Avatar, Skeleton, Tag } from '@douyinfe/semi-ui';
 import { VChart } from '@visactor/react-vchart';
 import { VChart } from '@visactor/react-vchart';
+import { useNavigate } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
 
 
 const StatsCards = ({
 const StatsCards = ({
   groupedStatsData,
   groupedStatsData,
@@ -28,6 +30,8 @@ const StatsCards = ({
   CARD_PROPS,
   CARD_PROPS,
   CHART_CONFIG
   CHART_CONFIG
 }) => {
 }) => {
+  const navigate = useNavigate();
+  const { t } = useTranslation();
   return (
   return (
     <div className="mb-4">
     <div className="mb-4">
       <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
       <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
@@ -72,7 +76,19 @@ const StatsCards = ({
                       </div>
                       </div>
                     </div>
                     </div>
                   </div>
                   </div>
-                  {(loading || (item.trendData && item.trendData.length > 0)) && (
+                  {item.title === t('当前余额') ? (
+                    <Tag
+                      color="white"
+                      shape='circle'
+                      size="large"
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        navigate('/console/topup');
+                      }}
+                    >
+                      {t('充值')}
+                    </Tag>
+                  ) : (loading || (item.trendData && item.trendData.length > 0)) && (
                     <div className="w-24 h-10">
                     <div className="w-24 h-10">
                       <VChart
                       <VChart
                         spec={getTrendSpec(item.trendData, item.trendColor)}
                         spec={getTrendSpec(item.trendData, item.trendColor)}

+ 75 - 52
web/src/components/topup/InvitationCard.jsx

@@ -25,6 +25,7 @@ import {
   Button,
   Button,
   Input,
   Input,
   Badge,
   Badge,
+  Space,
 } from '@douyinfe/semi-ui';
 } from '@douyinfe/semi-ui';
 import { Copy, Users, BarChart2, TrendingUp, Gift, Zap } from 'lucide-react';
 import { Copy, Users, BarChart2, TrendingUp, Gift, Zap } from 'lucide-react';
 
 
@@ -52,55 +53,77 @@ const InvitationCard = ({
       </div>
       </div>
 
 
       {/* 收益展示区域 */}
       {/* 收益展示区域 */}
-      <div className='space-y-4'>
-        {/* 主要收益卡片 - 待使用收益 */}
-        <Card className='!rounded-xl'>
-          <div className='flex justify-between items-center mb-3'>
-            <div className="flex items-center">
-              <TrendingUp size={16} className="mr-2 text-slate-600 dark:text-slate-300" />
-              <Text strong className='text-slate-700 dark:text-slate-200'>{t('待使用收益')}</Text>
-            </div>
-            <Button
-              type='primary'
-              theme='solid'
-              size='small'
-              disabled={!userState?.user?.aff_quota || userState?.user?.aff_quota <= 0}
-              onClick={() => setOpenTransfer(true)}
-              className='!rounded-lg !bg-slate-600 hover:!bg-slate-700'
+      <Space vertical style={{ width: '100%' }}>
+        {/* 统计数据统一卡片 */}
+        <Card
+          className='!rounded-xl w-full'
+          cover={
+            <div
+              className="relative h-30"
+              style={{
+                '--palette-primary-darkerChannel': '0 75 80',
+                backgroundImage: `linear-gradient(0deg, rgba(var(--palette-primary-darkerChannel) / 80%), rgba(var(--palette-primary-darkerChannel) / 80%)), url('/cover-4.webp')`,
+                backgroundSize: 'cover',
+                backgroundPosition: 'center',
+                backgroundRepeat: 'no-repeat'
+              }}
             >
             >
-              <Zap size={12} className="mr-1" />
-              {t('划转到余额')}
-            </Button>
-          </div>
-          <div className='text-2xl sm:text-3xl font-bold text-slate-900 dark:text-slate-100 mb-1'>
-            {renderQuota(userState?.user?.aff_quota || 0)}
-          </div>
-        </Card>
+              {/* 标题和按钮 */}
+              <div className="relative z-10 h-full flex flex-col justify-between p-4">
+                <div className='flex justify-between items-center'>
+                  <Text strong style={{ color: 'white', fontSize: '16px' }}>{t('收益统计')}</Text>
+                  <Button
+                    type='primary'
+                    theme='solid'
+                    size='small'
+                    disabled={!userState?.user?.aff_quota || userState?.user?.aff_quota <= 0}
+                    onClick={() => setOpenTransfer(true)}
+                    className='!rounded-lg'
+                  >
+                    <Zap size={12} className="mr-1" />
+                    {t('划转到余额')}
+                  </Button>
+                </div>
 
 
-        {/* 统计数据网格 */}
-        <div className='grid grid-cols-2 gap-4'>
-          <Card className='!rounded-xl bg-slate-50 dark:bg-slate-800'>
-            <div className='flex items-center mb-2'>
-              <BarChart2 size={16} className='mr-2 text-slate-600 dark:text-slate-300' />
-              <Text type='tertiary' className='text-slate-600 dark:text-slate-300'>{t('总收益')}</Text>
-            </div>
-            <div className='text-xl font-semibold text-slate-900 dark:text-slate-100'>
-              {renderQuota(userState?.user?.aff_history_quota || 0)}
-            </div>
-          </Card>
+                {/* 统计数据 */}
+                <div className='grid grid-cols-3 gap-6 mt-4'>
+                  {/* 待使用收益 */}
+                  <div className='text-center'>
+                    <div className='text-2xl font-bold mb-2' style={{ color: 'white' }}>
+                      {renderQuota(userState?.user?.aff_quota || 0)}
+                    </div>
+                    <div className='flex items-center justify-center text-sm'>
+                      <TrendingUp size={14} className="mr-1" style={{ color: 'rgba(255,255,255,0.8)' }} />
+                      <Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: '12px' }}>{t('待使用收益')}</Text>
+                    </div>
+                  </div>
 
 
-          <Card className='!rounded-xl bg-slate-50 dark:bg-slate-800'>
-            <div className='flex items-center mb-2'>
-              <Users size={16} className='mr-2 text-slate-600 dark:text-slate-300' />
-              <Text type='tertiary' className='text-slate-600 dark:text-slate-300'>{t('邀请人数')}</Text>
-            </div>
-            <div className='text-xl font-semibold text-slate-900 dark:text-slate-100 flex items-center'>
-              {userState?.user?.aff_count || 0} {t('人')}
-            </div>
-          </Card>
-        </div>
+                  {/* 总收益 */}
+                  <div className='text-center'>
+                    <div className='text-2xl font-bold mb-2' style={{ color: 'white' }}>
+                      {renderQuota(userState?.user?.aff_history_quota || 0)}
+                    </div>
+                    <div className='flex items-center justify-center text-sm'>
+                      <BarChart2 size={14} className="mr-1" style={{ color: 'rgba(255,255,255,0.8)' }} />
+                      <Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: '12px' }}>{t('总收益')}</Text>
+                    </div>
+                  </div>
 
 
-        <div className='!mb-4'>
+                  {/* 邀请人数 */}
+                  <div className='text-center'>
+                    <div className='text-2xl font-bold mb-2' style={{ color: 'white' }}>
+                      {userState?.user?.aff_count || 0}
+                    </div>
+                    <div className='flex items-center justify-center text-sm'>
+                      <Users size={14} className="mr-1" style={{ color: 'rgba(255,255,255,0.8)' }} />
+                      <Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: '12px' }}>{t('邀请人数')}</Text>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          }
+        >
           {/* 邀请链接部分 */}
           {/* 邀请链接部分 */}
           <Input
           <Input
             value={affLink}
             value={affLink}
@@ -119,13 +142,13 @@ const InvitationCard = ({
               </Button>
               </Button>
             }
             }
           />
           />
-        </div>
+        </Card>
 
 
         {/* 奖励说明 */}
         {/* 奖励说明 */}
         <Card
         <Card
-          className='!rounded-xl with-pastel-balls-warm'
+          className='!rounded-xl w-full'
           title={
           title={
-            <Text strong className='text-slate-700'>
+            <Text type='tertiary'>
               {t('奖励说明')}
               {t('奖励说明')}
             </Text>
             </Text>
           }
           }
@@ -133,27 +156,27 @@ const InvitationCard = ({
           <div className='space-y-3'>
           <div className='space-y-3'>
             <div className='flex items-start gap-2'>
             <div className='flex items-start gap-2'>
               <Badge dot type='success' />
               <Badge dot type='success' />
-              <Text type='tertiary' className='text-sm text-slate-600'>
+              <Text type='tertiary' className='text-sm'>
                 {t('邀请好友注册,好友充值后您可获得相应奖励')}
                 {t('邀请好友注册,好友充值后您可获得相应奖励')}
               </Text>
               </Text>
             </div>
             </div>
 
 
             <div className='flex items-start gap-2'>
             <div className='flex items-start gap-2'>
               <Badge dot type='success' />
               <Badge dot type='success' />
-              <Text type='tertiary' className='text-sm text-slate-600'>
+              <Text type='tertiary' className='text-sm'>
                 {t('通过划转功能将奖励额度转入到您的账户余额中')}
                 {t('通过划转功能将奖励额度转入到您的账户余额中')}
               </Text>
               </Text>
             </div>
             </div>
 
 
             <div className='flex items-start gap-2'>
             <div className='flex items-start gap-2'>
               <Badge dot type='success' />
               <Badge dot type='success' />
-              <Text type='tertiary' className='text-sm text-slate-600'>
+              <Text type='tertiary' className='text-sm'>
                 {t('邀请的好友越多,获得的奖励越多')}
                 {t('邀请的好友越多,获得的奖励越多')}
               </Text>
               </Text>
             </div>
             </div>
           </div>
           </div>
         </Card>
         </Card>
-      </div>
+      </Space>
     </Card>
     </Card>
   );
   );
 };
 };

+ 0 - 1
web/src/hooks/dashboard/useDashboardStats.jsx

@@ -52,7 +52,6 @@ export const useDashboardStats = (
           value: renderQuota(userState?.user?.quota),
           value: renderQuota(userState?.user?.quota),
           icon: <IconMoneyExchangeStroked />,
           icon: <IconMoneyExchangeStroked />,
           avatarColor: 'blue',
           avatarColor: 'blue',
-          onClick: () => navigate('/console/topup'),
           trendData: [],
           trendData: [],
           trendColor: '#3b82f6'
           trendColor: '#3b82f6'
         },
         },

+ 0 - 1
web/src/i18n/locales/en.json

@@ -855,7 +855,6 @@
   "邀请人数": "Number of people invited",
   "邀请人数": "Number of people invited",
   "兑换码充值": "Redemption code recharge",
   "兑换码充值": "Redemption code recharge",
   "奖励说明": "Reward description",
   "奖励说明": "Reward description",
-  "人": "",
   "选择支付方式": "Select payment method",
   "选择支付方式": "Select payment method",
   "处理中": "Processing",
   "处理中": "Processing",
   "账户充值": "Account recharge",
   "账户充值": "Account recharge",

+ 5 - 53
web/src/index.css

@@ -683,59 +683,6 @@ html.dark .with-pastel-balls::before {
   mix-blend-mode: screen;
   mix-blend-mode: screen;
 }
 }
 
 
-/* ==================== 卡片马卡龙模糊球(温暖色系) ==================== */
-.with-pastel-balls-warm {
-  position: relative;
-  overflow: hidden;
-  /* 温暖色系变量(明亮模式) */
-  --pb1: #ffe4b5;
-  /* 桃杏 */
-  --pb2: #d4ffdd;
-  /* 薄荷绿 */
-  --pb3: #ffecb3;
-  /* 浅金 */
-  --pb4: #e8f5e8;
-  /* 淡绿 */
-  --pb-opacity: 0.55;
-}
-
-.with-pastel-balls-warm::before {
-  content: '';
-  position: absolute;
-  inset: 0;
-  pointer-events: none;
-  z-index: 0;
-  background:
-    radial-gradient(circle at -5% -10%, var(--pb1) 0%, transparent 60%),
-    radial-gradient(circle at 105% -10%, var(--pb2) 0%, transparent 55%),
-    radial-gradient(circle at 5% 110%, var(--pb3) 0%, transparent 55%),
-    radial-gradient(circle at 105% 110%, var(--pb4) 0%, transparent 50%);
-  opacity: var(--pb-opacity);
-}
-
-.with-pastel-balls-warm>* {
-  position: relative;
-  z-index: 1;
-}
-
-/* 暗黑模式下更柔和的色彩和透明度 */
-html.dark .with-pastel-balls-warm {
-  --pb1: #ffe4b5;
-  /* 桃杏 */
-  --pb2: #d4ffdd;
-  /* 薄荷绿 */
-  --pb3: #ffecb3;
-  /* 浅金 */
-  --pb4: #e8f5e8;
-  /* 淡绿 */
-  --pb-opacity: 0.36;
-}
-
-/* 暗黑模式下用更柔和的混合模式 */
-html.dark .with-pastel-balls-warm::before {
-  mix-blend-mode: screen;
-}
-
 /* ==================== 表格卡片滚动设置 ==================== */
 /* ==================== 表格卡片滚动设置 ==================== */
 .table-scroll-card {
 .table-scroll-card {
   display: flex;
   display: flex;
@@ -814,4 +761,9 @@ html.dark .with-pastel-balls-warm::before {
   flex: 1;
   flex: 1;
   overflow: auto;
   overflow: auto;
   min-height: 0;
   min-height: 0;
+}
+
+/* ==================== semi-ui 组件自定义样式 ==================== */
+.semi-card-header {
+  padding: 10px !important;
 }
 }