🎨 refactor: TokensTable UI for clearer quota info & compact controls

• Display remaining-quota percentage instead of used-quota in the Progress indicator
  - 100 % when quota is untouched, shown in green
  - Warn at ≤ 30 % (yellow) and at ≤ 10 % (red)
  - Hide internal label (`showInfo={false}`) and move the percentage text into the Tooltip
  - Switch Progress `size` to `small` for a lighter visual footprint

• Update Tooltip to list used, remaining, total quota and the new percentage value

• Uniformly set `size="small"` on all header Buttons and Form inputs within the table
  — enhances readability and keeps the main content centered

UI/UX improvement only; no backend logic affected.
This commit is contained in:
t0ng7u
2025-07-13 01:02:55 +08:00
parent 31d82a3169
commit 9d2a56bff4
6 changed files with 59 additions and 16 deletions

View File

@@ -1234,9 +1234,7 @@ const LogsTable = () => {
<Space> <Space>
<Tag <Tag
color='blue' color='blue'
size='large'
style={{ style={{
padding: 15,
fontWeight: 500, fontWeight: 500,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
}} }}
@@ -1246,9 +1244,7 @@ const LogsTable = () => {
</Tag> </Tag>
<Tag <Tag
color='pink' color='pink'
size='large'
style={{ style={{
padding: 15,
fontWeight: 500, fontWeight: 500,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
}} }}
@@ -1258,9 +1254,7 @@ const LogsTable = () => {
</Tag> </Tag>
<Tag <Tag
color='white' color='white'
size='large'
style={{ style={{
padding: 15,
border: 'none', border: 'none',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
fontWeight: 500, fontWeight: 500,
@@ -1276,6 +1270,7 @@ const LogsTable = () => {
type='secondary' type='secondary'
className="w-full md:w-auto" className="w-full md:w-auto"
onClick={() => setCompactMode(!compactMode)} onClick={() => setCompactMode(!compactMode)}
size="small"
> >
{compactMode ? t('自适应列表') : t('紧凑列表')} {compactMode ? t('自适应列表') : t('紧凑列表')}
</Button> </Button>
@@ -1306,6 +1301,7 @@ const LogsTable = () => {
placeholder={[t('开始时间'), t('结束时间')]} placeholder={[t('开始时间'), t('结束时间')]}
showClear showClear
pure pure
size="small"
/> />
</div> </div>
@@ -1316,6 +1312,7 @@ const LogsTable = () => {
placeholder={t('令牌名称')} placeholder={t('令牌名称')}
showClear showClear
pure pure
size="small"
/> />
<Form.Input <Form.Input
@@ -1324,6 +1321,7 @@ const LogsTable = () => {
placeholder={t('模型名称')} placeholder={t('模型名称')}
showClear showClear
pure pure
size="small"
/> />
<Form.Input <Form.Input
@@ -1332,6 +1330,7 @@ const LogsTable = () => {
placeholder={t('分组')} placeholder={t('分组')}
showClear showClear
pure pure
size="small"
/> />
{isAdminUser && ( {isAdminUser && (
@@ -1342,6 +1341,7 @@ const LogsTable = () => {
placeholder={t('渠道 ID')} placeholder={t('渠道 ID')}
showClear showClear
pure pure
size="small"
/> />
<Form.Input <Form.Input
field='username' field='username'
@@ -1349,6 +1349,7 @@ const LogsTable = () => {
placeholder={t('用户名称')} placeholder={t('用户名称')}
showClear showClear
pure pure
size="small"
/> />
</> </>
)} )}
@@ -1370,6 +1371,7 @@ const LogsTable = () => {
refresh(); refresh();
}, 0); }, 0);
}} }}
size="small"
> >
<Form.Select.Option value='0'> <Form.Select.Option value='0'>
{t('全部')} {t('全部')}
@@ -1397,6 +1399,7 @@ const LogsTable = () => {
type='primary' type='primary'
htmlType='submit' htmlType='submit'
loading={loading} loading={loading}
size="small"
> >
{t('查询')} {t('查询')}
</Button> </Button>
@@ -1411,6 +1414,7 @@ const LogsTable = () => {
}, 100); }, 100);
} }
}} }}
size="small"
> >
{t('重置')} {t('重置')}
</Button> </Button>
@@ -1418,6 +1422,7 @@ const LogsTable = () => {
theme='light' theme='light'
type='tertiary' type='tertiary'
onClick={() => setShowColumnSelector(true)} onClick={() => setShowColumnSelector(true)}
size="small"
> >
{t('列设置')} {t('列设置')}
</Button> </Button>

View File

@@ -522,6 +522,7 @@ const LogsTable = () => {
} }
return ( return (
<Button <Button
size="small"
onClick={() => { onClick={() => {
setModalImageUrl(text); setModalImageUrl(text);
setIsModalOpenurl(true); setIsModalOpenurl(true);
@@ -834,6 +835,7 @@ const LogsTable = () => {
type='secondary' type='secondary'
className="w-full md:w-auto" className="w-full md:w-auto"
onClick={() => setCompactMode(!compactMode)} onClick={() => setCompactMode(!compactMode)}
size="small"
> >
{compactMode ? t('自适应列表') : t('紧凑列表')} {compactMode ? t('自适应列表') : t('紧凑列表')}
</Button> </Button>
@@ -863,6 +865,7 @@ const LogsTable = () => {
placeholder={[t('开始时间'), t('结束时间')]} placeholder={[t('开始时间'), t('结束时间')]}
showClear showClear
pure pure
size="small"
/> />
</div> </div>
@@ -873,6 +876,7 @@ const LogsTable = () => {
placeholder={t('任务 ID')} placeholder={t('任务 ID')}
showClear showClear
pure pure
size="small"
/> />
{/* 渠道 ID - 仅管理员可见 */} {/* 渠道 ID - 仅管理员可见 */}
@@ -883,6 +887,7 @@ const LogsTable = () => {
placeholder={t('渠道 ID')} placeholder={t('渠道 ID')}
showClear showClear
pure pure
size="small"
/> />
)} )}
</div> </div>
@@ -895,6 +900,7 @@ const LogsTable = () => {
type='primary' type='primary'
htmlType='submit' htmlType='submit'
loading={loading} loading={loading}
size="small"
> >
{t('查询')} {t('查询')}
</Button> </Button>
@@ -909,6 +915,7 @@ const LogsTable = () => {
}, 100); }, 100);
} }
}} }}
size="small"
> >
{t('重置')} {t('重置')}
</Button> </Button>
@@ -916,6 +923,7 @@ const LogsTable = () => {
theme='light' theme='light'
type='tertiary' type='tertiary'
onClick={() => setShowColumnSelector(true)} onClick={() => setShowColumnSelector(true)}
size="small"
> >
{t('列设置')} {t('列设置')}
</Button> </Button>

View File

@@ -428,6 +428,7 @@ const RedemptionsTable = () => {
type='secondary' type='secondary'
className="w-full md:w-auto" className="w-full md:w-auto"
onClick={() => setCompactMode(!compactMode)} onClick={() => setCompactMode(!compactMode)}
size="small"
> >
{compactMode ? t('自适应列表') : t('紧凑列表')} {compactMode ? t('自适应列表') : t('紧凑列表')}
</Button> </Button>
@@ -449,6 +450,7 @@ const RedemptionsTable = () => {
}); });
setShowEdit(true); setShowEdit(true);
}} }}
size="small"
> >
{t('添加兑换码')} {t('添加兑换码')}
</Button> </Button>
@@ -467,6 +469,7 @@ const RedemptionsTable = () => {
} }
await copyText(keys); await copyText(keys);
}} }}
size="small"
> >
{t('复制所选兑换码到剪贴板')} {t('复制所选兑换码到剪贴板')}
</Button> </Button>
@@ -492,6 +495,7 @@ const RedemptionsTable = () => {
}, },
}); });
}} }}
size="small"
> >
{t('清除失效兑换码')} {t('清除失效兑换码')}
</Button> </Button>
@@ -519,6 +523,7 @@ const RedemptionsTable = () => {
placeholder={t('关键字(id或者名称)')} placeholder={t('关键字(id或者名称)')}
showClear showClear
pure pure
size="small"
/> />
</div> </div>
<div className="flex gap-2 w-full md:w-auto"> <div className="flex gap-2 w-full md:w-auto">
@@ -527,6 +532,7 @@ const RedemptionsTable = () => {
htmlType="submit" htmlType="submit"
loading={loading || searching} loading={loading || searching}
className="flex-1 md:flex-initial md:w-auto" className="flex-1 md:flex-initial md:w-auto"
size="small"
> >
{t('查询')} {t('查询')}
</Button> </Button>
@@ -543,6 +549,7 @@ const RedemptionsTable = () => {
} }
}} }}
className="flex-1 md:flex-initial md:w-auto" className="flex-1 md:flex-initial md:w-auto"
size="small"
> >
{t('重置')} {t('重置')}
</Button> </Button>

View File

@@ -682,6 +682,7 @@ const LogsTable = () => {
type='secondary' type='secondary'
className="w-full md:w-auto" className="w-full md:w-auto"
onClick={() => setCompactMode(!compactMode)} onClick={() => setCompactMode(!compactMode)}
size="small"
> >
{compactMode ? t('自适应列表') : t('紧凑列表')} {compactMode ? t('自适应列表') : t('紧凑列表')}
</Button> </Button>
@@ -711,6 +712,7 @@ const LogsTable = () => {
placeholder={[t('开始时间'), t('结束时间')]} placeholder={[t('开始时间'), t('结束时间')]}
showClear showClear
pure pure
size="small"
/> />
</div> </div>
@@ -721,6 +723,7 @@ const LogsTable = () => {
placeholder={t('任务 ID')} placeholder={t('任务 ID')}
showClear showClear
pure pure
size="small"
/> />
{/* 渠道 ID - 仅管理员可见 */} {/* 渠道 ID - 仅管理员可见 */}
@@ -731,6 +734,7 @@ const LogsTable = () => {
placeholder={t('渠道 ID')} placeholder={t('渠道 ID')}
showClear showClear
pure pure
size="small"
/> />
)} )}
</div> </div>
@@ -743,6 +747,7 @@ const LogsTable = () => {
type='primary' type='primary'
htmlType='submit' htmlType='submit'
loading={loading} loading={loading}
size="small"
> >
{t('查询')} {t('查询')}
</Button> </Button>
@@ -757,6 +762,7 @@ const LogsTable = () => {
}, 100); }, 100);
} }
}} }}
size="small"
> >
{t('重置')} {t('重置')}
</Button> </Button>
@@ -764,6 +770,7 @@ const LogsTable = () => {
theme='light' theme='light'
type='tertiary' type='tertiary'
onClick={() => setShowColumnSelector(true)} onClick={() => setShowColumnSelector(true)}
size="small"
> >
{t('列设置')} {t('列设置')}
</Button> </Button>

View File

@@ -132,7 +132,7 @@ const TokensTable = () => {
key: 'token_key', key: 'token_key',
render: (text, record) => { render: (text, record) => {
const fullKey = 'sk-' + record.key; const fullKey = 'sk-' + record.key;
const maskedKey = 'sk-' + record.key.slice(0, 3) + '********' + record.key.slice(-3); const maskedKey = 'sk-' + record.key.slice(0, 4) + '**********' + record.key.slice(-4);
const revealed = !!showKeys[record.id]; const revealed = !!showKeys[record.id];
return ( return (
@@ -173,7 +173,7 @@ const TokensTable = () => {
}, },
}, },
{ {
title: t('额度'), title: t('剩余额度'),
key: 'quota', key: 'quota',
render: (text, record) => { render: (text, record) => {
if (record.unlimited_quota) { if (record.unlimited_quota) {
@@ -183,12 +183,15 @@ const TokensTable = () => {
const used = parseInt(record.used_quota) || 0; const used = parseInt(record.used_quota) || 0;
const remain = parseInt(record.remain_quota) || 0; const remain = parseInt(record.remain_quota) || 0;
const total = used + remain; const total = used + remain;
const percent = total > 0 ? (used / total) * 100 : 0; // 计算剩余额度百分比100% 表示额度未使用
const percent = total > 0 ? (remain / total) * 100 : 0;
// 根据剩余百分比动态设置颜色100% 绿色,<=10% 红色,<=30% 黄色,其余默认
const getProgressColor = (pct) => { const getProgressColor = (pct) => {
if (pct >= 90) return 'var(--semi-color-danger)'; if (pct === 100) return 'var(--semi-color-success)';
if (pct >= 70) return 'var(--semi-color-warning)'; if (pct <= 10) return 'var(--semi-color-danger)';
return undefined; // default color if (pct <= 30) return 'var(--semi-color-warning)';
return undefined; // 默认颜色
}; };
return ( return (
@@ -196,7 +199,7 @@ const TokensTable = () => {
content={ content={
<div className='text-xs'> <div className='text-xs'>
<div>{t('已用额度')}: {renderQuota(used)}</div> <div>{t('已用额度')}: {renderQuota(used)}</div>
<div>{t('剩余额度')}: {renderQuota(remain)}</div> <div>{t('剩余额度')}: {renderQuota(remain)} ({percent.toFixed(0)}%)</div>
<div>{t('总额度')}: {renderQuota(total)}</div> <div>{t('总额度')}: {renderQuota(total)}</div>
</div> </div>
} }
@@ -205,11 +208,10 @@ const TokensTable = () => {
<Progress <Progress
percent={percent} percent={percent}
stroke={getProgressColor(percent)} stroke={getProgressColor(percent)}
showInfo showInfo={false}
aria-label='quota usage' aria-label='quota usage'
format={percent => <span className="text-xs">{percent.toFixed(0)}%</span>}
type="circle" type="circle"
width={30} size='small'
/> />
</div> </div>
</Tooltip> </Tooltip>
@@ -698,6 +700,7 @@ const TokensTable = () => {
type="secondary" type="secondary"
className="w-full md:w-auto" className="w-full md:w-auto"
onClick={() => setCompactMode(!compactMode)} onClick={() => setCompactMode(!compactMode)}
size="small"
> >
{compactMode ? t('自适应列表') : t('紧凑列表')} {compactMode ? t('自适应列表') : t('紧凑列表')}
</Button> </Button>
@@ -718,6 +721,7 @@ const TokensTable = () => {
}); });
setShowEdit(true); setShowEdit(true);
}} }}
size="small"
> >
{t('添加令牌')} {t('添加令牌')}
</Button> </Button>
@@ -768,6 +772,7 @@ const TokensTable = () => {
), ),
}); });
}} }}
size="small"
> >
{t('复制所选令牌')} {t('复制所选令牌')}
</Button> </Button>
@@ -790,6 +795,7 @@ const TokensTable = () => {
onOk: () => batchDeleteTokens(), onOk: () => batchDeleteTokens(),
}); });
}} }}
size="small"
> >
{t('删除所选令牌')} {t('删除所选令牌')}
</Button> </Button>
@@ -814,6 +820,7 @@ const TokensTable = () => {
placeholder={t('搜索关键字')} placeholder={t('搜索关键字')}
showClear showClear
pure pure
size="small"
/> />
</div> </div>
<div className="relative w-full md:w-56"> <div className="relative w-full md:w-56">
@@ -823,6 +830,7 @@ const TokensTable = () => {
placeholder={t('密钥')} placeholder={t('密钥')}
showClear showClear
pure pure
size="small"
/> />
</div> </div>
<div className="flex gap-2 w-full md:w-auto"> <div className="flex gap-2 w-full md:w-auto">
@@ -831,6 +839,7 @@ const TokensTable = () => {
htmlType="submit" htmlType="submit"
loading={loading || searching} loading={loading || searching}
className="flex-1 md:flex-initial md:w-auto" className="flex-1 md:flex-initial md:w-auto"
size="small"
> >
{t('查询')} {t('查询')}
</Button> </Button>
@@ -846,6 +855,7 @@ const TokensTable = () => {
} }
}} }}
className="flex-1 md:flex-initial md:w-auto" className="flex-1 md:flex-initial md:w-auto"
size="small"
> >
{t('重置')} {t('重置')}
</Button> </Button>

View File

@@ -524,6 +524,7 @@ const UsersTable = () => {
type='secondary' type='secondary'
className="w-full md:w-auto" className="w-full md:w-auto"
onClick={() => setCompactMode(!compactMode)} onClick={() => setCompactMode(!compactMode)}
size="small"
> >
{compactMode ? t('自适应列表') : t('紧凑列表')} {compactMode ? t('自适应列表') : t('紧凑列表')}
</Button> </Button>
@@ -541,6 +542,7 @@ const UsersTable = () => {
onClick={() => { onClick={() => {
setShowAddUser(true); setShowAddUser(true);
}} }}
size="small"
> >
{t('添加用户')} {t('添加用户')}
</Button> </Button>
@@ -568,6 +570,7 @@ const UsersTable = () => {
placeholder={t('支持搜索用户的 ID、用户名、显示名称和邮箱地址')} placeholder={t('支持搜索用户的 ID、用户名、显示名称和邮箱地址')}
showClear showClear
pure pure
size="small"
/> />
</div> </div>
<div className="w-full md:w-48"> <div className="w-full md:w-48">
@@ -585,6 +588,7 @@ const UsersTable = () => {
className="w-full" className="w-full"
showClear showClear
pure pure
size="small"
/> />
</div> </div>
<div className="flex gap-2 w-full md:w-auto"> <div className="flex gap-2 w-full md:w-auto">
@@ -593,6 +597,7 @@ const UsersTable = () => {
htmlType="submit" htmlType="submit"
loading={loading || searching} loading={loading || searching}
className="flex-1 md:flex-initial md:w-auto" className="flex-1 md:flex-initial md:w-auto"
size="small"
> >
{t('查询')} {t('查询')}
</Button> </Button>
@@ -609,6 +614,7 @@ const UsersTable = () => {
} }
}} }}
className="flex-1 md:flex-initial md:w-auto" className="flex-1 md:flex-initial md:w-auto"
size="small"
> >
{t('重置')} {t('重置')}
</Button> </Button>