feat(ui): Implement unified compact/adaptive table mode + icon refinement

Summary
• Added per-table “Compact / Adaptive” view toggle to all major table components (Tokens, Channels, Logs, MjLogs, TaskLogs, Redemptions, Users).
• Persist user preference in a single localStorage entry (`table_compact_modes`) instead of scattered keys.

Details
1. utils.js
   • Re-implemented `getTableCompactMode` / `setTableCompactMode` to read & write a shared JSON object.
   • Imported storage-key constant from `constants`.

2. hooks/useTableCompactMode.js
   • Hook now consumes the unified helpers and listens to `storage` events via the shared key constant.

3. constants
   • Added `TABLE_COMPACT_MODES_KEY` to `common.constant.js` and re-exported via `constants/index.js`.

4. Table components
   • Integrated `useTableCompactMode('<tableName>')`.
   • Dynamically remove `fixed: 'right'` column and horizontal `scroll` when in compact mode.
   • UI: toggle button placed at card title’s right; responsive layout on small screens.

5. UI polish
   • Replaced all lucide-react `List`/`ListIcon` usages with Semi UI `IconDescend` for consistency.
   • Restored correct icons where `Hash` was intended (TaskLogsTable).

Benefits
• Consistent UX for switching list density across the app.
• Cleaner localStorage footprint with easier future maintenance.
This commit is contained in:
t0ng7u
2025-06-22 18:10:00 +08:00
parent d7c97d4d34
commit 014c9450ba
11 changed files with 284 additions and 118 deletions

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useMemo } from 'react';
import {
API,
copy,
@@ -52,10 +52,12 @@ import {
IconDelete,
IconStop,
IconPlay,
IconMore
IconMore,
IconDescend
} from '@douyinfe/semi-icons';
import EditToken from '../../pages/Token/EditToken';
import { useTranslation } from 'react-i18next';
import { useTableCompactMode } from '../../hooks/useTableCompactMode';
const { Text } = Typography;
@@ -385,6 +387,7 @@ const TokensTable = () => {
const [editingToken, setEditingToken] = useState({
id: undefined,
});
const [compactMode, setCompactMode] = useTableCompactMode('tokens');
// Form 初始值
const formInitValues = {
@@ -610,9 +613,20 @@ const TokensTable = () => {
const renderHeader = () => (
<div className="flex flex-col w-full">
<div className="mb-2">
<div className="flex items-center text-blue-500">
<Key size={16} className="mr-2" />
<Text>{t('令牌用于API访问认证可以设置额度限制和模型权限。')}</Text>
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-2 w-full">
<div className="flex items-center text-blue-500">
<Key size={16} className="mr-2" />
<Text>{t('令牌用于API访问认证可以设置额度限制和模型权限。')}</Text>
</div>
<Button
theme="light"
type="secondary"
icon={<IconDescend />}
className="!rounded-full w-full md:w-auto"
onClick={() => setCompactMode(!compactMode)}
>
{compactMode ? t('自适应列表') : t('紧凑列表')}
</Button>
</div>
</div>
@@ -687,7 +701,6 @@ const TokensTable = () => {
>
{t('复制所选令牌')}
</Button>
<div className="w-full md:hidden"></div>
<Button
theme="light"
type="danger"
@@ -791,9 +804,15 @@ const TokensTable = () => {
bordered={false}
>
<Table
columns={columns}
columns={compactMode ? columns.map(col => {
if (col.dataIndex === 'operate') {
const { fixed, ...rest } = col;
return rest;
}
return col;
}) : columns}
dataSource={tokens}
scroll={{ x: 'max-content' }}
scroll={compactMode ? undefined : { x: 'max-content' }}
pagination={{
currentPage: activePage,
pageSize: pageSize,