🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
• `channels/index.jsx` – composition entry
• `ChannelsTable.jsx` – pure `<Table>` rendering
• `ChannelsActions.jsx` – bulk & settings toolbar
• `ChannelsFilters.jsx` – search / create / column-settings form
• `ChannelsTabs.jsx` – type tabs
• `ChannelsColumnDefs.js` – column definitions & render helpers
• `modals/` – BatchTag, ColumnSelector, ModelTest modals
2. Extract domain hook
• Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
– centralises state, API calls, pagination, filters, batch ops
– now exports `setActivePage`, fixing tab / status switch errors
3. Update wiring
• All sub-components consume data via `useChannelsData` props
• Adjusted import paths after hook relocation
4. Clean legacy file
• Legacy `components/table/ChannelsTable.js` now re-exports new module
5. Bug fixes
• Tab switching, status filter & tag aggregation restored
• Column selector & batch actions operate via unified hook
This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00
|
|
|
import React from 'react';
|
|
|
|
|
import {
|
|
|
|
|
Button,
|
|
|
|
|
Dropdown,
|
|
|
|
|
Modal,
|
|
|
|
|
Switch,
|
|
|
|
|
Typography,
|
|
|
|
|
Select
|
|
|
|
|
} from '@douyinfe/semi-ui';
|
🌟 feat(ui): reusable CompactModeToggle & mobile-friendly CardPro
Summary
-------
Introduce a reusable compact-mode toggle component and greatly improve the CardPro header for small screens. Removes duplicated code, adds i18n support, and refines overall responsiveness.
Details
-------
🎨 UI / Components
• Create `common/ui/CompactModeToggle.js`
– Provides a single source of truth for switching between “Compact list” and “Adaptive list”
– Automatically hides itself on mobile devices via `useIsMobile()`
• Refactor table modules to use the new component
– `Users`, `Tokens`, `Redemptions`, `Channels`, `TaskLogs`, `MjLogs`, `UsageLogs`
– Deletes legacy in-file toggle buttons & reduces repetition
📱 CardPro improvements
• Hide `actionsArea` and `searchArea` on mobile, showing a single “Show Actions / Hide Actions” toggle button
• Add i18n: texts are now pulled from injected `t()` function (`显示操作项` / `隐藏操作项` etc.)
• Extend PropTypes to accept the `t` prop; supply a safe fallback
• Minor cleanup: remove legacy DOM observers & flag CSS, simplify logic
🔧 Integration
• Pass the `t` translation function to every `CardPro` usage across table pages
• Remove temporary custom class hooks after logic simplification
Benefits
--------
✓ Consistent, DRY compact-mode handling across the entire dashboard
✓ Better mobile experience with decluttered headers
✓ Full translation support for newly added strings
✓ Easier future maintenance (single compact toggle, unified CardPro API)
2025-07-19 01:34:59 +08:00
|
|
|
import CompactModeToggle from '../../common/ui/CompactModeToggle';
|
🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
• `channels/index.jsx` – composition entry
• `ChannelsTable.jsx` – pure `<Table>` rendering
• `ChannelsActions.jsx` – bulk & settings toolbar
• `ChannelsFilters.jsx` – search / create / column-settings form
• `ChannelsTabs.jsx` – type tabs
• `ChannelsColumnDefs.js` – column definitions & render helpers
• `modals/` – BatchTag, ColumnSelector, ModelTest modals
2. Extract domain hook
• Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
– centralises state, API calls, pagination, filters, batch ops
– now exports `setActivePage`, fixing tab / status switch errors
3. Update wiring
• All sub-components consume data via `useChannelsData` props
• Adjusted import paths after hook relocation
4. Clean legacy file
• Legacy `components/table/ChannelsTable.js` now re-exports new module
5. Bug fixes
• Tab switching, status filter & tag aggregation restored
• Column selector & batch actions operate via unified hook
This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00
|
|
|
|
|
|
|
|
const ChannelsActions = ({
|
|
|
|
|
enableBatchDelete,
|
|
|
|
|
batchDeleteChannels,
|
|
|
|
|
setShowBatchSetTag,
|
|
|
|
|
testAllChannels,
|
|
|
|
|
fixChannelsAbilities,
|
|
|
|
|
updateAllChannelsBalance,
|
|
|
|
|
deleteAllDisabledChannels,
|
|
|
|
|
compactMode,
|
|
|
|
|
setCompactMode,
|
|
|
|
|
idSort,
|
|
|
|
|
setIdSort,
|
|
|
|
|
setEnableBatchDelete,
|
|
|
|
|
enableTagMode,
|
|
|
|
|
setEnableTagMode,
|
|
|
|
|
statusFilter,
|
|
|
|
|
setStatusFilter,
|
|
|
|
|
getFormValues,
|
|
|
|
|
loadChannels,
|
|
|
|
|
searchChannels,
|
|
|
|
|
activeTypeKey,
|
|
|
|
|
activePage,
|
|
|
|
|
pageSize,
|
|
|
|
|
setActivePage,
|
|
|
|
|
t
|
|
|
|
|
}) => {
|
|
|
|
|
return (
|
2025-07-18 22:04:54 +08:00
|
|
|
<div className="flex flex-col gap-2">
|
🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
• `channels/index.jsx` – composition entry
• `ChannelsTable.jsx` – pure `<Table>` rendering
• `ChannelsActions.jsx` – bulk & settings toolbar
• `ChannelsFilters.jsx` – search / create / column-settings form
• `ChannelsTabs.jsx` – type tabs
• `ChannelsColumnDefs.js` – column definitions & render helpers
• `modals/` – BatchTag, ColumnSelector, ModelTest modals
2. Extract domain hook
• Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
– centralises state, API calls, pagination, filters, batch ops
– now exports `setActivePage`, fixing tab / status switch errors
3. Update wiring
• All sub-components consume data via `useChannelsData` props
• Adjusted import paths after hook relocation
4. Clean legacy file
• Legacy `components/table/ChannelsTable.js` now re-exports new module
5. Bug fixes
• Tab switching, status filter & tag aggregation restored
• Column selector & batch actions operate via unified hook
This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00
|
|
|
{/* 第一行:批量操作按钮 + 设置开关 */}
|
2025-07-18 22:04:54 +08:00
|
|
|
<div className="flex flex-col md:flex-row justify-between gap-2">
|
🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
• `channels/index.jsx` – composition entry
• `ChannelsTable.jsx` – pure `<Table>` rendering
• `ChannelsActions.jsx` – bulk & settings toolbar
• `ChannelsFilters.jsx` – search / create / column-settings form
• `ChannelsTabs.jsx` – type tabs
• `ChannelsColumnDefs.js` – column definitions & render helpers
• `modals/` – BatchTag, ColumnSelector, ModelTest modals
2. Extract domain hook
• Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
– centralises state, API calls, pagination, filters, batch ops
– now exports `setActivePage`, fixing tab / status switch errors
3. Update wiring
• All sub-components consume data via `useChannelsData` props
• Adjusted import paths after hook relocation
4. Clean legacy file
• Legacy `components/table/ChannelsTable.js` now re-exports new module
5. Bug fixes
• Tab switching, status filter & tag aggregation restored
• Column selector & batch actions operate via unified hook
This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00
|
|
|
{/* 左侧:批量操作按钮 */}
|
|
|
|
|
<div className="flex flex-wrap md:flex-nowrap items-center gap-2 w-full md:w-auto order-2 md:order-1">
|
|
|
|
|
<Button
|
|
|
|
|
size='small'
|
|
|
|
|
disabled={!enableBatchDelete}
|
|
|
|
|
type='danger'
|
|
|
|
|
className="w-full md:w-auto"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: t('确定是否要删除所选通道?'),
|
|
|
|
|
content: t('此修改将不可逆'),
|
|
|
|
|
onOk: () => batchDeleteChannels(),
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{t('删除所选通道')}
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
size='small'
|
|
|
|
|
disabled={!enableBatchDelete}
|
|
|
|
|
type='tertiary'
|
|
|
|
|
onClick={() => setShowBatchSetTag(true)}
|
|
|
|
|
className="w-full md:w-auto"
|
|
|
|
|
>
|
|
|
|
|
{t('批量设置标签')}
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
|
|
<Dropdown
|
|
|
|
|
size='small'
|
|
|
|
|
trigger='click'
|
|
|
|
|
render={
|
|
|
|
|
<Dropdown.Menu>
|
|
|
|
|
<Dropdown.Item>
|
|
|
|
|
<Button
|
|
|
|
|
size='small'
|
|
|
|
|
type='tertiary'
|
|
|
|
|
className="w-full"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: t('确定?'),
|
|
|
|
|
content: t('确定要测试所有通道吗?'),
|
|
|
|
|
onOk: () => testAllChannels(),
|
|
|
|
|
size: 'small',
|
|
|
|
|
centered: true,
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{t('测试所有通道')}
|
|
|
|
|
</Button>
|
|
|
|
|
</Dropdown.Item>
|
|
|
|
|
<Dropdown.Item>
|
|
|
|
|
<Button
|
|
|
|
|
size='small'
|
|
|
|
|
className="w-full"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: t('确定是否要修复数据库一致性?'),
|
|
|
|
|
content: t('进行该操作时,可能导致渠道访问错误,请仅在数据库出现问题时使用'),
|
|
|
|
|
onOk: () => fixChannelsAbilities(),
|
|
|
|
|
size: 'sm',
|
|
|
|
|
centered: true,
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{t('修复数据库一致性')}
|
|
|
|
|
</Button>
|
|
|
|
|
</Dropdown.Item>
|
|
|
|
|
<Dropdown.Item>
|
|
|
|
|
<Button
|
|
|
|
|
size='small'
|
|
|
|
|
type='secondary'
|
|
|
|
|
className="w-full"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: t('确定?'),
|
|
|
|
|
content: t('确定要更新所有已启用通道余额吗?'),
|
|
|
|
|
onOk: () => updateAllChannelsBalance(),
|
|
|
|
|
size: 'sm',
|
|
|
|
|
centered: true,
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{t('更新所有已启用通道余额')}
|
|
|
|
|
</Button>
|
|
|
|
|
</Dropdown.Item>
|
|
|
|
|
<Dropdown.Item>
|
|
|
|
|
<Button
|
|
|
|
|
size='small'
|
|
|
|
|
type='danger'
|
|
|
|
|
className="w-full"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: t('确定是否要删除禁用通道?'),
|
|
|
|
|
content: t('此修改将不可逆'),
|
|
|
|
|
onOk: () => deleteAllDisabledChannels(),
|
|
|
|
|
size: 'sm',
|
|
|
|
|
centered: true,
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{t('删除禁用通道')}
|
|
|
|
|
</Button>
|
|
|
|
|
</Dropdown.Item>
|
|
|
|
|
</Dropdown.Menu>
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<Button size='small' theme='light' type='tertiary' className="w-full md:w-auto">
|
|
|
|
|
{t('批量操作')}
|
|
|
|
|
</Button>
|
|
|
|
|
</Dropdown>
|
|
|
|
|
|
🌟 feat(ui): reusable CompactModeToggle & mobile-friendly CardPro
Summary
-------
Introduce a reusable compact-mode toggle component and greatly improve the CardPro header for small screens. Removes duplicated code, adds i18n support, and refines overall responsiveness.
Details
-------
🎨 UI / Components
• Create `common/ui/CompactModeToggle.js`
– Provides a single source of truth for switching between “Compact list” and “Adaptive list”
– Automatically hides itself on mobile devices via `useIsMobile()`
• Refactor table modules to use the new component
– `Users`, `Tokens`, `Redemptions`, `Channels`, `TaskLogs`, `MjLogs`, `UsageLogs`
– Deletes legacy in-file toggle buttons & reduces repetition
📱 CardPro improvements
• Hide `actionsArea` and `searchArea` on mobile, showing a single “Show Actions / Hide Actions” toggle button
• Add i18n: texts are now pulled from injected `t()` function (`显示操作项` / `隐藏操作项` etc.)
• Extend PropTypes to accept the `t` prop; supply a safe fallback
• Minor cleanup: remove legacy DOM observers & flag CSS, simplify logic
🔧 Integration
• Pass the `t` translation function to every `CardPro` usage across table pages
• Remove temporary custom class hooks after logic simplification
Benefits
--------
✓ Consistent, DRY compact-mode handling across the entire dashboard
✓ Better mobile experience with decluttered headers
✓ Full translation support for newly added strings
✓ Easier future maintenance (single compact toggle, unified CardPro API)
2025-07-19 01:34:59 +08:00
|
|
|
<CompactModeToggle
|
|
|
|
|
compactMode={compactMode}
|
|
|
|
|
setCompactMode={setCompactMode}
|
|
|
|
|
t={t}
|
|
|
|
|
/>
|
🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
• `channels/index.jsx` – composition entry
• `ChannelsTable.jsx` – pure `<Table>` rendering
• `ChannelsActions.jsx` – bulk & settings toolbar
• `ChannelsFilters.jsx` – search / create / column-settings form
• `ChannelsTabs.jsx` – type tabs
• `ChannelsColumnDefs.js` – column definitions & render helpers
• `modals/` – BatchTag, ColumnSelector, ModelTest modals
2. Extract domain hook
• Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
– centralises state, API calls, pagination, filters, batch ops
– now exports `setActivePage`, fixing tab / status switch errors
3. Update wiring
• All sub-components consume data via `useChannelsData` props
• Adjusted import paths after hook relocation
4. Clean legacy file
• Legacy `components/table/ChannelsTable.js` now re-exports new module
5. Bug fixes
• Tab switching, status filter & tag aggregation restored
• Column selector & batch actions operate via unified hook
This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* 右侧:设置开关区域 */}
|
2025-07-18 22:04:54 +08:00
|
|
|
<div className="flex flex-col md:flex-row items-start md:items-center gap-2 w-full md:w-auto order-1 md:order-2">
|
🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
• `channels/index.jsx` – composition entry
• `ChannelsTable.jsx` – pure `<Table>` rendering
• `ChannelsActions.jsx` – bulk & settings toolbar
• `ChannelsFilters.jsx` – search / create / column-settings form
• `ChannelsTabs.jsx` – type tabs
• `ChannelsColumnDefs.js` – column definitions & render helpers
• `modals/` – BatchTag, ColumnSelector, ModelTest modals
2. Extract domain hook
• Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
– centralises state, API calls, pagination, filters, batch ops
– now exports `setActivePage`, fixing tab / status switch errors
3. Update wiring
• All sub-components consume data via `useChannelsData` props
• Adjusted import paths after hook relocation
4. Clean legacy file
• Legacy `components/table/ChannelsTable.js` now re-exports new module
5. Bug fixes
• Tab switching, status filter & tag aggregation restored
• Column selector & batch actions operate via unified hook
This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00
|
|
|
<div className="flex items-center justify-between w-full md:w-auto">
|
|
|
|
|
<Typography.Text strong className="mr-2">
|
|
|
|
|
{t('使用ID排序')}
|
|
|
|
|
</Typography.Text>
|
|
|
|
|
<Switch
|
|
|
|
|
size='small'
|
|
|
|
|
checked={idSort}
|
|
|
|
|
onChange={(v) => {
|
|
|
|
|
localStorage.setItem('id-sort', v + '');
|
|
|
|
|
setIdSort(v);
|
|
|
|
|
const { searchKeyword, searchGroup, searchModel } = getFormValues();
|
|
|
|
|
if (searchKeyword === '' && searchGroup === '' && searchModel === '') {
|
|
|
|
|
loadChannels(activePage, pageSize, v, enableTagMode);
|
|
|
|
|
} else {
|
|
|
|
|
searchChannels(enableTagMode, activeTypeKey, statusFilter, activePage, pageSize, v);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center justify-between w-full md:w-auto">
|
|
|
|
|
<Typography.Text strong className="mr-2">
|
|
|
|
|
{t('开启批量操作')}
|
|
|
|
|
</Typography.Text>
|
|
|
|
|
<Switch
|
|
|
|
|
size='small'
|
|
|
|
|
checked={enableBatchDelete}
|
|
|
|
|
onChange={(v) => {
|
|
|
|
|
localStorage.setItem('enable-batch-delete', v + '');
|
|
|
|
|
setEnableBatchDelete(v);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center justify-between w-full md:w-auto">
|
|
|
|
|
<Typography.Text strong className="mr-2">
|
|
|
|
|
{t('标签聚合模式')}
|
|
|
|
|
</Typography.Text>
|
|
|
|
|
<Switch
|
|
|
|
|
size='small'
|
|
|
|
|
checked={enableTagMode}
|
|
|
|
|
onChange={(v) => {
|
|
|
|
|
localStorage.setItem('enable-tag-mode', v + '');
|
|
|
|
|
setEnableTagMode(v);
|
|
|
|
|
setActivePage(1);
|
|
|
|
|
loadChannels(1, pageSize, idSort, v);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center justify-between w-full md:w-auto">
|
|
|
|
|
<Typography.Text strong className="mr-2">
|
|
|
|
|
{t('状态筛选')}
|
|
|
|
|
</Typography.Text>
|
|
|
|
|
<Select
|
|
|
|
|
size='small'
|
|
|
|
|
value={statusFilter}
|
|
|
|
|
onChange={(v) => {
|
|
|
|
|
localStorage.setItem('channel-status-filter', v);
|
|
|
|
|
setStatusFilter(v);
|
|
|
|
|
setActivePage(1);
|
|
|
|
|
loadChannels(1, pageSize, idSort, enableTagMode, activeTypeKey, v);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Select.Option value="all">{t('全部')}</Select.Option>
|
|
|
|
|
<Select.Option value="enabled">{t('已启用')}</Select.Option>
|
|
|
|
|
<Select.Option value="disabled">{t('已禁用')}</Select.Option>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default ChannelsActions;
|