Files
newapi-yx-diy/web/src/components/common/ui/CardPro.js
t0ng7u 3fe509757b ♻️ refactor: restructure LogsTable into modular component architecture
Refactor the monolithic LogsTable component (1453 lines) into a modular,
maintainable architecture following the channels table pattern.

## What Changed

### 🏗️ Architecture
- Split single large file into focused, single-responsibility components
- Introduced custom hook `useLogsData` for centralized state management
- Created dedicated column definitions file for better organization
- Implemented modal components for user interactions

### 📁 New Structure
```
web/src/components/table/usage-logs/
├── index.jsx                    # Main page component orchestrator
├── LogsTable.jsx               # Pure table rendering component
├── LogsActions.jsx             # Actions area (stats + compact mode)
├── LogsFilters.jsx             # Search form component
├── LogsColumnDefs.js           # Column definitions and renderers
└── modals/
    ├── ColumnSelectorModal.jsx # Column visibility settings
    └── UserInfoModal.jsx       # User information display

web/src/hooks/logs/
└── useLogsData.js              # Custom hook for state & logic
```

### 🎯 Key Improvements
- **Maintainability**: Clear separation of concerns, easier to understand
- **Reusability**: Modular components can be reused independently
- **Performance**: Optimized with `useMemo` for column rendering
- **Testing**: Single-responsibility components easier to test
- **Developer Experience**: Better code organization and readability

### 🔧 Technical Details
- Preserved all existing functionality and user experience
- Maintained backward compatibility through existing import path
- Centralized all business logic in `useLogsData` custom hook
- Extracted column definitions to separate module with render functions
- Split complex UI into focused components (table, actions, filters, modals)

### 🐛 Fixes
- Fixed Semi UI component import issues (`Typography.Paragraph`)
- Resolved module export dependencies
- Maintained consistent prop passing patterns

## Breaking Changes
None - all existing imports and functionality preserved.
2025-07-18 22:04:54 +08:00

127 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import { Card, Divider, Typography } from '@douyinfe/semi-ui';
import PropTypes from 'prop-types';
const { Text } = Typography;
/**
* CardPro 高级卡片组件
*
* 布局分为5个区域
* 1. 统计信息区域 (statsArea)
* 2. 描述信息区域 (descriptionArea)
* 3. 类型切换/标签区域 (tabsArea)
* 4. 操作按钮区域 (actionsArea)
* 5. 搜索表单区域 (searchArea)
*
* 支持三种布局类型:
* - type1: 操作型 (如TokensTable) - 描述信息 + 操作按钮 + 搜索表单
* - type2: 查询型 (如LogsTable) - 统计信息 + 搜索表单
* - type3: 复杂型 (如ChannelsTable) - 描述信息 + 类型切换 + 操作按钮 + 搜索表单
*/
const CardPro = ({
type = 'type1',
className = '',
children,
// 各个区域的内容
statsArea,
descriptionArea,
tabsArea,
actionsArea,
searchArea,
// 卡片属性
shadows = 'always',
bordered = false,
// 自定义样式
style,
...props
}) => {
// 渲染头部内容
const renderHeader = () => {
const hasContent = statsArea || descriptionArea || tabsArea || actionsArea || searchArea;
if (!hasContent) return null;
return (
<div className="flex flex-col w-full">
{/* 统计信息区域 - 用于type2 */}
{type === 'type2' && statsArea && (
<>
{statsArea}
</>
)}
{/* 描述信息区域 - 用于type1和type3 */}
{(type === 'type1' || type === 'type3') && descriptionArea && (
<>
{descriptionArea}
</>
)}
{/* 第一个分隔线 - 在描述信息或统计信息后面 */}
{((type === 'type1' || type === 'type3') && descriptionArea) ||
(type === 'type2' && statsArea) ? (
<Divider margin="12px" />
) : null}
{/* 类型切换/标签区域 - 主要用于type3 */}
{type === 'type3' && tabsArea && (
<>
{tabsArea}
</>
)}
{/* 操作按钮和搜索表单的容器 */}
<div className="flex flex-col gap-2">
{/* 操作按钮区域 - 用于type1和type3 */}
{(type === 'type1' || type === 'type3') && actionsArea && (
<div className="w-full">
{actionsArea}
</div>
)}
{/* 搜索表单区域 - 所有类型都可能有 */}
{searchArea && (
<div className="w-full">
{searchArea}
</div>
)}
</div>
</div>
);
};
const headerContent = renderHeader();
return (
<Card
className={`table-scroll-card !rounded-2xl ${className}`}
title={headerContent}
shadows={shadows}
bordered={bordered}
style={style}
{...props}
>
{children}
</Card>
);
};
CardPro.propTypes = {
// 布局类型
type: PropTypes.oneOf(['type1', 'type2', 'type3']),
// 样式相关
className: PropTypes.string,
style: PropTypes.object,
shadows: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
bordered: PropTypes.bool,
// 内容区域
statsArea: PropTypes.node,
descriptionArea: PropTypes.node,
tabsArea: PropTypes.node,
actionsArea: PropTypes.node,
searchArea: PropTypes.node,
// 表格内容
children: PropTypes.node,
};
export default CardPro;