🎨 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:
@@ -1234,9 +1234,7 @@ const LogsTable = () => {
|
||||
<Space>
|
||||
<Tag
|
||||
color='blue'
|
||||
size='large'
|
||||
style={{
|
||||
padding: 15,
|
||||
fontWeight: 500,
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
|
||||
}}
|
||||
@@ -1246,9 +1244,7 @@ const LogsTable = () => {
|
||||
</Tag>
|
||||
<Tag
|
||||
color='pink'
|
||||
size='large'
|
||||
style={{
|
||||
padding: 15,
|
||||
fontWeight: 500,
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
|
||||
}}
|
||||
@@ -1258,9 +1254,7 @@ const LogsTable = () => {
|
||||
</Tag>
|
||||
<Tag
|
||||
color='white'
|
||||
size='large'
|
||||
style={{
|
||||
padding: 15,
|
||||
border: 'none',
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
|
||||
fontWeight: 500,
|
||||
@@ -1276,6 +1270,7 @@ const LogsTable = () => {
|
||||
type='secondary'
|
||||
className="w-full md:w-auto"
|
||||
onClick={() => setCompactMode(!compactMode)}
|
||||
size="small"
|
||||
>
|
||||
{compactMode ? t('自适应列表') : t('紧凑列表')}
|
||||
</Button>
|
||||
@@ -1306,6 +1301,7 @@ const LogsTable = () => {
|
||||
placeholder={[t('开始时间'), t('结束时间')]}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1316,6 +1312,7 @@ const LogsTable = () => {
|
||||
placeholder={t('令牌名称')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
|
||||
<Form.Input
|
||||
@@ -1324,6 +1321,7 @@ const LogsTable = () => {
|
||||
placeholder={t('模型名称')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
|
||||
<Form.Input
|
||||
@@ -1332,6 +1330,7 @@ const LogsTable = () => {
|
||||
placeholder={t('分组')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
|
||||
{isAdminUser && (
|
||||
@@ -1342,6 +1341,7 @@ const LogsTable = () => {
|
||||
placeholder={t('渠道 ID')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
<Form.Input
|
||||
field='username'
|
||||
@@ -1349,6 +1349,7 @@ const LogsTable = () => {
|
||||
placeholder={t('用户名称')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -1370,6 +1371,7 @@ const LogsTable = () => {
|
||||
refresh();
|
||||
}, 0);
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<Form.Select.Option value='0'>
|
||||
{t('全部')}
|
||||
@@ -1397,6 +1399,7 @@ const LogsTable = () => {
|
||||
type='primary'
|
||||
htmlType='submit'
|
||||
loading={loading}
|
||||
size="small"
|
||||
>
|
||||
{t('查询')}
|
||||
</Button>
|
||||
@@ -1411,6 +1414,7 @@ const LogsTable = () => {
|
||||
}, 100);
|
||||
}
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('重置')}
|
||||
</Button>
|
||||
@@ -1418,6 +1422,7 @@ const LogsTable = () => {
|
||||
theme='light'
|
||||
type='tertiary'
|
||||
onClick={() => setShowColumnSelector(true)}
|
||||
size="small"
|
||||
>
|
||||
{t('列设置')}
|
||||
</Button>
|
||||
|
||||
@@ -522,6 +522,7 @@ const LogsTable = () => {
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setModalImageUrl(text);
|
||||
setIsModalOpenurl(true);
|
||||
@@ -834,6 +835,7 @@ const LogsTable = () => {
|
||||
type='secondary'
|
||||
className="w-full md:w-auto"
|
||||
onClick={() => setCompactMode(!compactMode)}
|
||||
size="small"
|
||||
>
|
||||
{compactMode ? t('自适应列表') : t('紧凑列表')}
|
||||
</Button>
|
||||
@@ -863,6 +865,7 @@ const LogsTable = () => {
|
||||
placeholder={[t('开始时间'), t('结束时间')]}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -873,6 +876,7 @@ const LogsTable = () => {
|
||||
placeholder={t('任务 ID')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
|
||||
{/* 渠道 ID - 仅管理员可见 */}
|
||||
@@ -883,6 +887,7 @@ const LogsTable = () => {
|
||||
placeholder={t('渠道 ID')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -895,6 +900,7 @@ const LogsTable = () => {
|
||||
type='primary'
|
||||
htmlType='submit'
|
||||
loading={loading}
|
||||
size="small"
|
||||
>
|
||||
{t('查询')}
|
||||
</Button>
|
||||
@@ -909,6 +915,7 @@ const LogsTable = () => {
|
||||
}, 100);
|
||||
}
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('重置')}
|
||||
</Button>
|
||||
@@ -916,6 +923,7 @@ const LogsTable = () => {
|
||||
theme='light'
|
||||
type='tertiary'
|
||||
onClick={() => setShowColumnSelector(true)}
|
||||
size="small"
|
||||
>
|
||||
{t('列设置')}
|
||||
</Button>
|
||||
|
||||
@@ -428,6 +428,7 @@ const RedemptionsTable = () => {
|
||||
type='secondary'
|
||||
className="w-full md:w-auto"
|
||||
onClick={() => setCompactMode(!compactMode)}
|
||||
size="small"
|
||||
>
|
||||
{compactMode ? t('自适应列表') : t('紧凑列表')}
|
||||
</Button>
|
||||
@@ -449,6 +450,7 @@ const RedemptionsTable = () => {
|
||||
});
|
||||
setShowEdit(true);
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('添加兑换码')}
|
||||
</Button>
|
||||
@@ -467,6 +469,7 @@ const RedemptionsTable = () => {
|
||||
}
|
||||
await copyText(keys);
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('复制所选兑换码到剪贴板')}
|
||||
</Button>
|
||||
@@ -492,6 +495,7 @@ const RedemptionsTable = () => {
|
||||
},
|
||||
});
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('清除失效兑换码')}
|
||||
</Button>
|
||||
@@ -519,6 +523,7 @@ const RedemptionsTable = () => {
|
||||
placeholder={t('关键字(id或者名称)')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 w-full md:w-auto">
|
||||
@@ -527,6 +532,7 @@ const RedemptionsTable = () => {
|
||||
htmlType="submit"
|
||||
loading={loading || searching}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
>
|
||||
{t('查询')}
|
||||
</Button>
|
||||
@@ -543,6 +549,7 @@ const RedemptionsTable = () => {
|
||||
}
|
||||
}}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
>
|
||||
{t('重置')}
|
||||
</Button>
|
||||
|
||||
@@ -682,6 +682,7 @@ const LogsTable = () => {
|
||||
type='secondary'
|
||||
className="w-full md:w-auto"
|
||||
onClick={() => setCompactMode(!compactMode)}
|
||||
size="small"
|
||||
>
|
||||
{compactMode ? t('自适应列表') : t('紧凑列表')}
|
||||
</Button>
|
||||
@@ -711,6 +712,7 @@ const LogsTable = () => {
|
||||
placeholder={[t('开始时间'), t('结束时间')]}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -721,6 +723,7 @@ const LogsTable = () => {
|
||||
placeholder={t('任务 ID')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
|
||||
{/* 渠道 ID - 仅管理员可见 */}
|
||||
@@ -731,6 +734,7 @@ const LogsTable = () => {
|
||||
placeholder={t('渠道 ID')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -743,6 +747,7 @@ const LogsTable = () => {
|
||||
type='primary'
|
||||
htmlType='submit'
|
||||
loading={loading}
|
||||
size="small"
|
||||
>
|
||||
{t('查询')}
|
||||
</Button>
|
||||
@@ -757,6 +762,7 @@ const LogsTable = () => {
|
||||
}, 100);
|
||||
}
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('重置')}
|
||||
</Button>
|
||||
@@ -764,6 +770,7 @@ const LogsTable = () => {
|
||||
theme='light'
|
||||
type='tertiary'
|
||||
onClick={() => setShowColumnSelector(true)}
|
||||
size="small"
|
||||
>
|
||||
{t('列设置')}
|
||||
</Button>
|
||||
|
||||
@@ -132,7 +132,7 @@ const TokensTable = () => {
|
||||
key: 'token_key',
|
||||
render: (text, record) => {
|
||||
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];
|
||||
|
||||
return (
|
||||
@@ -173,7 +173,7 @@ const TokensTable = () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('额度'),
|
||||
title: t('剩余额度'),
|
||||
key: 'quota',
|
||||
render: (text, record) => {
|
||||
if (record.unlimited_quota) {
|
||||
@@ -183,12 +183,15 @@ const TokensTable = () => {
|
||||
const used = parseInt(record.used_quota) || 0;
|
||||
const remain = parseInt(record.remain_quota) || 0;
|
||||
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) => {
|
||||
if (pct >= 90) return 'var(--semi-color-danger)';
|
||||
if (pct >= 70) return 'var(--semi-color-warning)';
|
||||
return undefined; // default color
|
||||
if (pct === 100) return 'var(--semi-color-success)';
|
||||
if (pct <= 10) return 'var(--semi-color-danger)';
|
||||
if (pct <= 30) return 'var(--semi-color-warning)';
|
||||
return undefined; // 默认颜色
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -196,7 +199,7 @@ const TokensTable = () => {
|
||||
content={
|
||||
<div className='text-xs'>
|
||||
<div>{t('已用额度')}: {renderQuota(used)}</div>
|
||||
<div>{t('剩余额度')}: {renderQuota(remain)}</div>
|
||||
<div>{t('剩余额度')}: {renderQuota(remain)} ({percent.toFixed(0)}%)</div>
|
||||
<div>{t('总额度')}: {renderQuota(total)}</div>
|
||||
</div>
|
||||
}
|
||||
@@ -205,11 +208,10 @@ const TokensTable = () => {
|
||||
<Progress
|
||||
percent={percent}
|
||||
stroke={getProgressColor(percent)}
|
||||
showInfo
|
||||
showInfo={false}
|
||||
aria-label='quota usage'
|
||||
format={percent => <span className="text-xs">{percent.toFixed(0)}%</span>}
|
||||
type="circle"
|
||||
width={30}
|
||||
size='small'
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
@@ -698,6 +700,7 @@ const TokensTable = () => {
|
||||
type="secondary"
|
||||
className="w-full md:w-auto"
|
||||
onClick={() => setCompactMode(!compactMode)}
|
||||
size="small"
|
||||
>
|
||||
{compactMode ? t('自适应列表') : t('紧凑列表')}
|
||||
</Button>
|
||||
@@ -718,6 +721,7 @@ const TokensTable = () => {
|
||||
});
|
||||
setShowEdit(true);
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('添加令牌')}
|
||||
</Button>
|
||||
@@ -768,6 +772,7 @@ const TokensTable = () => {
|
||||
),
|
||||
});
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('复制所选令牌')}
|
||||
</Button>
|
||||
@@ -790,6 +795,7 @@ const TokensTable = () => {
|
||||
onOk: () => batchDeleteTokens(),
|
||||
});
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('删除所选令牌')}
|
||||
</Button>
|
||||
@@ -814,6 +820,7 @@ const TokensTable = () => {
|
||||
placeholder={t('搜索关键字')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative w-full md:w-56">
|
||||
@@ -823,6 +830,7 @@ const TokensTable = () => {
|
||||
placeholder={t('密钥')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 w-full md:w-auto">
|
||||
@@ -831,6 +839,7 @@ const TokensTable = () => {
|
||||
htmlType="submit"
|
||||
loading={loading || searching}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
>
|
||||
{t('查询')}
|
||||
</Button>
|
||||
@@ -846,6 +855,7 @@ const TokensTable = () => {
|
||||
}
|
||||
}}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
>
|
||||
{t('重置')}
|
||||
</Button>
|
||||
|
||||
@@ -524,6 +524,7 @@ const UsersTable = () => {
|
||||
type='secondary'
|
||||
className="w-full md:w-auto"
|
||||
onClick={() => setCompactMode(!compactMode)}
|
||||
size="small"
|
||||
>
|
||||
{compactMode ? t('自适应列表') : t('紧凑列表')}
|
||||
</Button>
|
||||
@@ -541,6 +542,7 @@ const UsersTable = () => {
|
||||
onClick={() => {
|
||||
setShowAddUser(true);
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
{t('添加用户')}
|
||||
</Button>
|
||||
@@ -568,6 +570,7 @@ const UsersTable = () => {
|
||||
placeholder={t('支持搜索用户的 ID、用户名、显示名称和邮箱地址')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full md:w-48">
|
||||
@@ -585,6 +588,7 @@ const UsersTable = () => {
|
||||
className="w-full"
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 w-full md:w-auto">
|
||||
@@ -593,6 +597,7 @@ const UsersTable = () => {
|
||||
htmlType="submit"
|
||||
loading={loading || searching}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
>
|
||||
{t('查询')}
|
||||
</Button>
|
||||
@@ -609,6 +614,7 @@ const UsersTable = () => {
|
||||
}
|
||||
}}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
>
|
||||
{t('重置')}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user