- Add left-right pagination layout for desktop (total info on left, controls on right)
- Keep mobile layout centered with pagination controls only
- Implement proper i18n support for pagination text using react-i18next
- Add pagination translations for Chinese and English
- Standardize t function usage across all table components to use xxxData.t pattern
- Update CardPro footer layout to support justify-between on desktop
- Use CSS variable --semi-color-text-2 for consistent text styling
- Disable built-in Pagination showTotal to avoid duplication
Components updated:
- CardPro: Enhanced footer layout with responsive design
- createCardProPagination: Added i18n support and custom total text
- All table components: Unified t function usage pattern
- i18n files: Added pagination-related translations
The pagination now displays "Showing X to Y of Z items" on desktop
and maintains existing centered layout on mobile devices.
- Break down monolithic ModelPricing.js (685 lines) into focused components:
* ModelPricingHeader.jsx - top status card with pricing information
* ModelPricingTabs.jsx - model category navigation tabs
* ModelPricingFilters.jsx - search and action controls
* ModelPricingTable.jsx - data table with pricing details
* ModelPricingColumnDefs.js - table column definitions and renderers
- Create custom hook useModelPricingData.js for centralized state management:
* Consolidate all business logic and API calls
* Manage pricing calculations and data transformations
* Handle search, filtering, and UI interactions
- Follow project conventions matching other table components:
* Adopt same file structure as channels/, users/, tokens/ modules
* Maintain consistent naming patterns and component organization
* Preserve all original functionality including responsive design
- Update import paths:
* Remove obsolete ModelPricing.js file
* Update Pricing page to use new ModelPricingPage component
* Fix missing import references
Benefits:
- Improved maintainability with single-responsibility components
- Enhanced code reusability and testability
- Better team collaboration with modular structure
- Consistent codebase architecture across all table components
Ensure the header logo is shown only after the image has fully loaded to eliminate flicker:
• Introduced `logoLoaded` state to track image load completion.
• Pre-loaded the logo using `new Image()` inside a `useEffect` hook and set state on `onload`.
• Replaced the previous Skeleton wrapper with a stacked layout:
– A `Skeleton.Image` placeholder is rendered while the logo is loading.
– The real `<img>` element fades in with an opacity transition once both global
`isLoading` and `logoLoaded` are true.
• Added automatic reset of `logoLoaded` whenever the logo source changes.
• Removed redundant `onLoad` on the `<img>` tag to avoid double triggers.
• Ensured placeholder and image sizes match via absolute positioning to prevent layout shift.
This delivers a smoother visual experience by keeping the skeleton visible until the logo is completely ready and then revealing it seamlessly.
- Update license text from "Apache-2.0协议" to "AGPL v3.0协议"
- Update license link to point to official AGPL v3.0 license page
- Align About page license references with actual project license
## Overview
Refactored the monolithic dashboard page (~1200 lines) into a modular architecture following the project's global layout pattern. The main `Detail/index.js` is now simplified to match other page entry files like `Midjourney/index.js`.
## Changes Made
### 🏗️ Architecture Changes
- **Before**: Single large file `pages/Detail/index.js` containing all dashboard logic
- **After**: Modular structure with dedicated hooks, components, and helpers
### 📁 New Files Created
- `hooks/dashboard/useDashboardData.js` - Core data management and API calls
- `hooks/dashboard/useDashboardStats.js` - Statistics computation and memoization
- `hooks/dashboard/useDashboardCharts.js` - Chart specifications and data processing
- `constants/dashboard.constants.js` - UI config, time options, and chart defaults
- `helpers/dashboard.js` - Utility functions for data processing and UI helpers
- `components/dashboard/index.jsx` - Main dashboard component integrating all modules
- `components/dashboard/modals/SearchModal.jsx` - Search modal component
### 🔧 Updated Files
- `constants/index.js` - Added dashboard constants export
- `helpers/index.js` - Added dashboard helpers export
- `pages/Detail/index.js` - Simplified to minimal wrapper (~20 lines)
### 🐛 Bug Fixes
- Fixed SearchModal DatePicker onChange to properly convert Date objects to timestamp strings
- Added missing localStorage update for `data_export_default_time` persistence
- Corrected data flow between search confirmation and chart updates
- Ensured proper chart data refresh after search parameter changes
### ✨ Key Improvements
- **Separation of Concerns**: Data, stats, and charts logic isolated into dedicated hooks
- **Reusability**: Components and hooks can be easily reused across the application
- **Maintainability**: Smaller, focused files easier to understand and modify
- **Consistency**: Follows established project patterns for global folder organization
- **Performance**: Proper memoization and callback optimization maintained
### 🎯 Functional Verification
- ✅ All dashboard panels (model analysis, resource consumption, performance metrics) update correctly
- ✅ Search functionality works with proper parameter validation
- ✅ Chart data refreshes properly after search/filter operations
- ✅ User interface remains identical to original implementation
- ✅ All existing features preserved without regression
### 🔄 Data Flow
```
User Input → SearchModal → useDashboardData → API Call → useDashboardCharts → UI Update
```
## Breaking Changes
None. All existing functionality preserved.
## Migration Notes
The refactored dashboard maintains 100% API compatibility and identical user experience while providing a cleaner, more maintainable codebase structure.
- Create new ScrollableContainer component in @/components/common/ui
- Provides automatic scroll detection and fade indicator
- Supports customizable height, styling, and event callbacks
- Includes comprehensive PropTypes for type safety
- Optimized with useCallback for better performance
- Refactor Detail page to use ScrollableContainer
- Remove manual scroll detection functions (checkApiScrollable, checkCardScrollable)
- Remove scroll event handlers (handleApiScroll, handleCardScroll)
- Remove scroll-related refs and state variables
- Replace all card scroll containers with ScrollableContainer component
* API info card
* System announcements card
* FAQ card
* Uptime monitoring card (both single and multi-tab scenarios)
- Benefits:
- Improved code reusability and maintainability
- Reduced code duplication across components
- Consistent scroll behavior throughout the application
- Easier to maintain and extend scroll functionality
Breaking changes: None
Migration: Existing scroll behavior is preserved with no user-facing changes
Fix pagination component flickering issue across multiple table views
by initializing count states to 0 instead of ITEMS_PER_PAGE. This
prevents the pagination component from briefly appearing and then
disappearing when tables are empty.
Changes:
- usage-logs: logCount initial value 0 (was ITEMS_PER_PAGE)
- users: userCount initial value 0 (was ITEMS_PER_PAGE)
- tokens: tokenCount initial value 0 (was ITEMS_PER_PAGE)
- channels: channelCount initial value 0 (was ITEMS_PER_PAGE)
- redemptions: tokenCount initial value 0 (was ITEMS_PER_PAGE)
The createCardProPagination function already handles total <= 0 by
returning null, so this ensures consistent behavior across all table
components and improves user experience by eliminating visual flicker.
Affected files:
- web/src/hooks/usage-logs/useUsageLogsData.js
- web/src/hooks/users/useUsersData.js
- web/src/hooks/tokens/useTokensData.js
- web/src/hooks/channels/useChannelsData.js
- web/src/hooks/redemptions/useRedemptionsData.js
Fix "Rendered fewer hooks than expected" error caused by conditional hook calls
in createCardProPagination function. The issue occurred when paginationArea was
commented out, breaking React's hooks rules.
**Problem:**
- createCardProPagination() internally called useIsMobile() hook
- When paginationArea was disabled, the hook was not called
- This violated React's rule that hooks must be called in the same order on every render
**Solution:**
- Refactor createCardProPagination to accept isMobile as a parameter
- Move useIsMobile() hook calls to component level
- Ensure consistent hook call order regardless of pagination usage
**Changes:**
- Update createCardProPagination function to accept isMobile parameter
- Add useIsMobile hook calls to all table components
- Pass isMobile parameter to createCardProPagination in all usage locations
**Files modified:**
- web/src/helpers/utils.js
- web/src/components/table/channels/index.jsx
- web/src/components/table/redemptions/index.jsx
- web/src/components/table/usage-logs/index.jsx
- web/src/components/table/tokens/index.jsx
- web/src/components/table/users/index.jsx
- web/src/components/table/mj-logs/index.jsx
- web/src/components/table/task-logs/index.jsx
Fixes critical runtime error and ensures stable pagination behavior across all table components.
Users table (UsersColumnDefs.js)
• Merged “Status” into the “Statistics” tag: unified text-color logic, removed duplicate renderStatus / renderOverallStatus helpers.
• Switch now disabled for deleted users.
• Replaced dropdown “More” menu with explicit action buttons (Edit / Promote / Demote / Delete) and set column width to 200 px.
• Deleted unused Dropdown & IconMore imports and tidied redundant code.
Users filters & hooks
• UsersFilters.jsx – store formApi in a ref; reset button clears form then reloads data after 100 ms.
• useUsersData.js – call setLoading(true) at the start of loadUsers so the Query button shows loading on reset / reload.
TokensFilters.jsx & RedemptionsFilters.jsx
• Same ref-based reset pattern with 100 ms debounce to restore working “Reset” buttons.
Other clean-ups
• Removed repeated status strings and unused helper functions.
• Updated import lists to reflect component changes.
Result
– Reset buttons now reliably clear filters and reload data with proper loading feedback.
– Users table shows concise status information and all operation buttons without extra clicks.
Summary of changes
1. UI clean-up
• Removed all `prefixIcon` props from `Tag` components in `UsersColumnDefs.js`.
• Corrected i18n string in invite info (`${t('邀请人')}: …`).
2. “Statistics” column overhaul
• Added a Switch (enable / disable) and quota Progress bar, mirroring the Tokens table design.
• Moved enable / disable action out of the “More” dropdown; user status is now toggled directly via the Switch.
• Disabled the Switch for deleted (注销) users.
• Restored column title to “Statistics” to avoid duplication.
3. State consistency / refresh
• Updated `manageUser` in `useUsersData.js` to:
– set `loading` while processing actions;
– update users list immutably (new objects & array) to trigger React re-render.
4. Imports / plumbing
• Added `Progress` and `Switch` to UI imports in `UsersColumnDefs.js`.
These changes streamline the user table’s appearance, align interaction patterns with the token table, and ensure immediate visual feedback after user status changes.
- Redesign modal layout from single column to responsive two-column grid
- Add new user information fields: display name, user group, invitation code,
invitation count, invitation quota, and remarks
- Implement Badge components with color-coded categories for better visual hierarchy:
* Primary (blue): basic identity info (username, display name)
* Success (green): positive/earning info (balance, invitation quota)
* Warning (orange): usage/consumption info (used quota, request count)
* Tertiary (gray): supplementary info (user group, invitation details, remarks)
- Optimize spacing and typography for better readability:
* Reduce row spacing from 24px to 16px
* Decrease font size from 16px to 14px for values
* Adjust label margins from 4px to 2px
- Implement conditional rendering for optional fields
- Add proper text wrapping for long remarks content
- Reduce overall modal height while maintaining information clarity
This update significantly improves the user experience by presenting
comprehensive user information in a more organized and visually appealing format.
Summary
1. CardTable
• Added collapsible “Details / Collapse” section on mobile cards using Semi-UI Button + Collapsible with chevron icons.
• Integrated i18n (`useTranslation`) for the toggle labels.
• Restored original variable-width skeleton placeholders (50 % / 60 % / 70 % …) for more natural loading states.
2. UsageLogsColumnDefs
• Wrapped each `Tag` inside a native `<span>` when used as Tooltip trigger, removing `findDOMNode` deprecation warnings in React StrictMode.
Impact
• Cleaner, shorter rows on small screens with optional expansion.
• Fully translated UI controls.
• No more console noise in development & CI caused by StrictMode warnings.
Summary
• Swapped out the obsolete `<Spin>` loader for a modern, animated Semi-UI `<Skeleton>` implementation in `UsageLogsActions.jsx`.
Details
1. Added animated Skeleton placeholders mirroring real Tag sizes (108 × 26, 65 × 26, 64 × 26).
2. Introduced `showSkeleton` state with 500 ms minimum display to eliminate flicker.
3. Leveraged existing `showStat` flag to decide when real data is ready.
4. Ensured only the three Tags are under loading state - `CompactModeToggle` renders immediately.
5. Adopted CardTable‐style `Skeleton` pattern (`loading` + `placeholder`) for consistency.
6. Removed all references to the original `Spin` component.
Outcome
A smoother and more consistent loading experience across devices, aligning UI behaviour with the project’s latest Skeleton standards.
Provide a consistent UX by ensuring the status column tooltip is shown for all tokens, including those with unlimited quota.
Details:
• Removed early‐return that skipped tooltip rendering when `record.unlimited_quota` was true.
• Refactored tooltip content:
– Unlimited quota: shows only “used quota”.
– Limited quota: continues to show used, remaining (with percentage) and total.
• Leaves existing tag, switch and progress-bar behaviour unchanged.
This prevents missing hover information for unlimited tokens and avoids meaningless “remaining / total” figures (e.g. Infinity), improving clarity for administrators.
This patch standardises how all “model” (and related) `<Select>` components handle searching.
Highlights
• Added a shared helper `modelSelectFilter` to `helpers/utils.js` – performs case-insensitive value-based matching, independent of ReactNode labels.
• Removed the temporary `helpers/selectFilter.js`; all components now import from the core helpers barrel.
• Updated Selects to use the new filter *and* set `autoClearSearchValue={false}` so the query text is preserved after a choice is made.
Affected components
• Channel editor (EditChannelModal) – channel type & model lists
• Tag editor (EditTagModal) – model list
• Token editor (EditTokenModal) – model-limit list
• Playground SettingsPanel – model selector
Benefits
✓ Consistent search behaviour across the app
✓ Better user experience when selecting multiple items
✓ Cleaner codebase with one canonical filter implementation
• Accept an array for `actionsArea`, enabling multiple action blocks in one card
• Automatically insert a `Divider` between consecutive action blocks
• Add a `Divider` between `actionsArea` and `searchArea` when both exist
• Standardize `Divider` spacing by removing custom `margin` props
• Update `PropTypes`: `actionsArea` now supports `arrayOf(node)`
These changes improve visual separation and usability for complex table cards (e.g., Channels), making the UI cleaner and more consistent.
Previously the component unmounted the Modal as soon as `showModelTestModal` became
false, preventing Semi UI from running its cleanup routine. This left `body`
stuck with `overflow: hidden`, disabling page scroll after the dialog closed.
Changes made
– Removed the early `return null` and always keep the Modal mounted; visibility
is now controlled solely via the `visible` prop.
– Introduced a `hasChannel` guard to safely skip data processing/rendering when
no channel is selected.
– Added defensive checks for table data, footer and title to avoid undefined
access when the Modal is hidden.
This fix ensures that closing the test-model dialog correctly restores the
page’s scroll behaviour on both desktop and mobile.
This commit addresses an issue where RPM and TPM statistics did not load automatically on mobile devices.
Key changes
• Replaced conditional rendering with persistent rendering of `actionsArea` and `searchArea` in `CardPro` and applied the `hidden` CSS class when the sections should be concealed.
• Ensures internal hooks (e.g. `useUsageLogsData`) always run, allowing stats to be fetched without requiring the user to tap “Show Actions”.
• Maintains existing desktop behaviour; only mobile handling is affected.
Files updated
• `web/src/components/common/ui/CardPro.js`
Result
Mobile users now see up-to-date RPM/TPM (and other statistics) immediately after page load, improving usability and consistency with the desktop experience.
• Imported Semi-UI `Empty` component.
• Detect when `dataSource` is empty on mobile card view:
– Renders supplied `empty` placeholder (`tableProps.empty`) or a default `<Empty description="No Data" />`.
– Suppresses the mobile `Pagination` component to avoid blank pages.
• Pagination now renders only when `dataSource.length > 0`, preserving UX parity with desktop tables.
1. Add `web/src/components/common/ui/CardTable.js`
• Renders Semi-UI `Table` on desktop; on mobile, transforms each row into a rounded `Card`.
• Supports all standard `Table` props, including `rowSelection`, `scroll`, `pagination`, etc.
• Adds mobile pagination via Semi-UI `Pagination`.
• Implements a 500 ms minimum, active Skeleton loader that mimics real column layout (including operation-button row).
2. Replace legacy `Table` with `CardTable`
• Updated all major data pages: Channels, MJ-Logs, Redemptions, Tokens, Task-Logs, Usage-Logs and Users.
• Removed unused `Table` imports; kept behaviour on desktop unchanged.
3. UI polish
• Right-aligned operation buttons and sensitive fields (e.g., token keys) inside mobile cards.
• Improved Skeleton placeholders to better reflect actual UI hierarchy and preserve the active animation.
These changes dramatically improve the mobile experience while retaining full functionality on larger screens.
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)
Move EditChannel and EditTagModal from standalone pages to modal components
within the channels module structure for consistency with other table modules.
Changes:
- Move EditChannel.js → components/table/channels/modals/EditChannelModal.jsx
- Move EditTagModal.js → components/table/channels/modals/EditTagModal.jsx
- Update import paths in channels/index.jsx
- Remove standalone routes for EditChannel from App.js
- Delete original files from pages/Channel/
This change aligns the channels module with the established modular pattern
used by tokens, users, redemptions, and other table modules, centralizing
all channel management functionality within integrated modal components
instead of separate page routes.
BREAKING CHANGE: EditChannel standalone routes (/console/channel/edit/:id
and /console/channel/add) have been removed. All channel editing is now
handled through modal components within the main channels page.
BREAKING CHANGE: Removed standalone user edit routes (/console/user/edit, /console/user/edit/:id)
- Decompose 673-line monolithic UsersTable.js into 8 specialized components
- Extract column definitions to UsersColumnDefs.js with render functions
- Create dedicated UsersActions.jsx for action buttons
- Create UsersFilters.jsx for search and filtering logic
- Create UsersDescription.jsx for description area
- Extract all data management logic to useUsersData.js hook
- Move AddUser.js and EditUser.js to users/modals/ folder as modal components
- Create 4 new confirmation modal components (Promote, Demote, EnableDisable, Delete)
- Implement pure UsersTable.jsx component for table rendering only
- Create main container component users/index.jsx to compose all subcomponents
- Update import paths in pages/User/index.js to use new modular structure
- Remove obsolete EditUser imports and routes from App.js
- Delete original monolithic files: UsersTable.js, AddUser.js, EditUser.js
The new architecture follows the same modular pattern as tokens and redemptions modules:
- Consistent file organization across all table modules
- Better separation of concerns and maintainability
- Enhanced reusability and testability
- Unified modal management approach
All existing functionality preserved with improved code organization.
Refactor the monolithic RedemptionsTable component (614 lines) into a clean,
modular structure following the established tokens component pattern.
### Changes Made:
**New Components:**
- `RedemptionsColumnDefs.js` - Extract table column definitions and render logic
- `RedemptionsActions.jsx` - Extract action buttons (add, batch copy, clear invalid)
- `RedemptionsFilters.jsx` - Extract search and filter form components
- `RedemptionsDescription.jsx` - Extract description area component
- `redemptions/index.jsx` - Main container component managing state and composition
**New Hook:**
- `useRedemptionsData.js` - Extract all data management, CRUD operations, and business logic
**New Constants:**
- `redemption.constants.js` - Extract redemption status, actions, and form constants
**Architecture Changes:**
- Transform RedemptionsTable.jsx into pure table rendering component
- Move state management and component composition to index.jsx
- Implement consistent prop drilling pattern matching tokens module
- Add memoization for performance optimization
- Centralize translation function distribution
### Benefits:
- **Maintainability**: Each component has single responsibility
- **Reusability**: Components and hooks can be used elsewhere
- **Testability**: Individual modules can be unit tested
- **Team Collaboration**: Multiple developers can work on different modules
- **Consistency**: Follows established architectural patterns
### File Structure:
```
redemptions/
├── index.jsx # Main container (state + composition)
├── RedemptionsTable.jsx # Pure table component
├── RedemptionsActions.jsx # Action buttons
├── RedemptionsFilters.jsx # Search/filter form
├── RedemptionsDescription.jsx # Description area
└── RedemptionsColumnDefs.js # Column definitions
- Split monolithic 922-line TokensTable.js into modular components:
* useTokensData.js: Custom hook for centralized state and logic management
* TokensColumnDefs.js: Column definitions and rendering functions
* TokensTable.jsx: Pure table component for rendering
* TokensActions.jsx: Actions area (add, copy, delete tokens)
* TokensFilters.jsx: Search form component with keyword and token filters
* TokensDescription.jsx: Description area with compact mode toggle
* index.jsx: Main orchestrator component
- Features preserved:
* Token status management with switch controls
* Quota progress bars and visual indicators
* Model limitations display with vendor avatars
* IP restrictions handling and display
* Chat integrations with dropdown menu
* Batch operations (copy, delete) with confirmations
* Key visibility toggle and copy functionality
* Compact mode for responsive layouts
* Search and filtering capabilities
* Pagination and loading states
- Improvements:
* Better separation of concerns
* Enhanced reusability and testability
* Simplified maintenance and debugging
* Consistent modular architecture pattern
* Performance optimizations with useMemo
* Backward compatibility maintained
This refactoring follows the same successful pattern used for LogsTable, MjLogsTable, and TaskLogsTable, significantly improving code maintainability while preserving all existing functionality.
Refactor the monolithic TaskLogsTable component (802 lines) into a modular,
maintainable architecture following the established pattern from LogsTable
and MjLogsTable refactors.
## What Changed
### 🏗️ Architecture
- Split large single file into focused, single-responsibility components
- Introduced custom hook `useTaskLogsData` for centralized state management
- Created dedicated column definitions file for better organization
- Implemented modal components for user interactions
### 📁 New Structure
```
web/src/components/table/task-logs/
├── index.jsx # Main page component orchestrator
├── TaskLogsTable.jsx # Pure table rendering component
├── TaskLogsActions.jsx # Actions area (task records + compact mode)
├── TaskLogsFilters.jsx # Search form component
├── TaskLogsColumnDefs.js # Column definitions and renderers
└── modals/
├── ColumnSelectorModal.jsx # Column visibility settings
└── ContentModal.jsx # Content viewer for JSON data
web/src/hooks/task-logs/
└── useTaskLogsData.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
### 🎨 Task-Specific Features Preserved
- All task type rendering with icons (MUSIC, LYRICS, video generation)
- Platform-specific rendering (Suno, Kling, Jimeng) with distinct colors
- Progress indicators for task completion status
- Video preview links for successful video generation tasks
- Admin-only columns for channel information
- Status rendering with appropriate colors and icons
### 🔧 Technical Details
- Centralized all business logic in `useTaskLogsData` custom hook
- Extracted comprehensive column definitions with Lucide React icons
- Split complex UI into focused components (table, actions, filters, modals)
- Maintained responsive design patterns for mobile compatibility
- Preserved admin permission handling for restricted features
- Optimized spacing and layout (reduced gap from 4 to 2 for better density)
### 🎮 Platform Support
- **Suno**: Music and lyrics generation with music icons
- **Kling**: Video generation with video icons
- **Jimeng**: Video generation with distinct purple styling
### 🐛 Fixes
- Improved component prop passing patterns
- Enhanced type safety through better state management
- Optimized rendering performance with proper memoization
- Streamlined export pattern using `export { default }`
## Breaking Changes
None - all existing imports and functionality preserved.
Refactor the monolithic MjLogsTable component (971 lines) into a modular,
maintainable architecture following the same pattern as LogsTable refactor.
## What Changed
### 🏗️ Architecture
- Split large single file into focused, single-responsibility components
- Introduced custom hook `useMjLogsData` for centralized state management
- Created dedicated column definitions file for better organization
- Implemented specialized modal components for Midjourney-specific features
### 📁 New Structure
```
web/src/components/table/mj-logs/
├── index.jsx # Main page component orchestrator
├── MjLogsTable.jsx # Pure table rendering component
├── MjLogsActions.jsx # Actions area (banner + compact mode)
├── MjLogsFilters.jsx # Search form component
├── MjLogsColumnDefs.js # Column definitions and renderers
└── modals/
├── ColumnSelectorModal.jsx # Column visibility settings
└── ContentModal.jsx # Content viewer (text + image preview)
web/src/hooks/mj-logs/
└── useMjLogsData.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
### 🎨 Midjourney-Specific Features Preserved
- All task type rendering with icons (IMAGINE, UPSCALE, VARIATION, etc.)
- Status rendering with appropriate colors and icons
- Image preview functionality for generated artwork
- Progress indicators for task completion
- Admin-only columns for channel and submission results
- Banner notification system for callback settings
### 🔧 Technical Details
- Centralized all business logic in `useMjLogsData` custom hook
- Extracted comprehensive column definitions with Lucide React icons
- Split complex UI into focused components (table, actions, filters, modals)
- Maintained responsive design patterns for mobile compatibility
- Preserved admin permission handling for restricted features
### 🐛 Fixes
- Improved component prop passing patterns
- Enhanced type safety through better state management
- Optimized rendering performance with proper memoization
## Breaking Changes
None - all existing imports and functionality preserved.
Eliminated the manual `formatPageText` function that previously rendered
pagination text (e.g. “第 {{start}} - {{end}} 条,共 {{total}} 条”) in each
Table. Pagination now relies on the default Semi UI text or the global
i18n configuration, reducing duplication and making future language
updates centralized.
Why
---
* Keeps table components cleaner and more maintainable.
* Ensures pagination text automatically respects the app-wide i18n
settings without per-component overrides.
Add Semi UI internationalization to the project by wrapping the root
component tree with `LocaleProvider`. A new `SemiLocaleWrapper`
component maps the current `i18next` language code to the corresponding
Semi locale (currently `zh_CN` and `en_GB`) and falls back to Chinese
when no match is found.
Key changes
-----------
1. web/src/index.js
• Import `LocaleProvider`, `useTranslation`, and Semi locale files.
• Introduce `SemiLocaleWrapper` to determine `semiLocale` from
`i18next.language` using a concise prefix-based mapping.
• Wrap `PageLayout` with `SemiLocaleWrapper` inside the existing
`ThemeProvider`.
2. Ensures that all Semi components automatically display the correct
language when the app language is switched via i18next.
BREAKING CHANGE
---------------
Applications embedding this project must now ensure that `i18next`
initialization occurs before React render so that `LocaleProvider`
receives the correct initial language.
Summary
Implement a dedicated, reusable scrolling mechanism for all console-table pages while keeping header and sidebar fixed, plus related layout improvements.
Key Changes
• Added `.table-scroll-card` utility class
– Provides flex column layout and internal vertical scrolling
– Desktop height: `calc(100vh - 110px)`; Mobile (<768 px) height: `calc(100vh - 77px)`
– Hides scrollbars cross-browser (`-ms-overflow-style`, `scrollbar-width`, `::-webkit-scrollbar`)
• Replaced global `.semi-card` scrolling rules with `.table-scroll-card` to avoid affecting non-table cards
• Updated table components (Channels, Tokens, Users, Logs, MjLogs, TaskLogs, Redemptions) to use the new class
• PageLayout
– Footer is now suppressed for all `/console` routes
– Confirmed only central content area scrolls; header & sidebar remain fixed
• Restored hidden scrollbar rules for `.semi-layout-content` and removed unnecessary global overrides
• Minor CSS cleanup & comment improvements for readability
Result
Console table pages now fill the viewport with smooth, internal scrolling and no visible scrollbars, while other cards and pages remain unaffected.
Backend
- setting/payment.go: introduce default `USDExchangeRate` (7.3)
- model/option.go:
• inject `USDExchangeRate` into `InitOptionMap`
• persist & sync value in `updateOptionMap`
- controller/misc.go: expose `usd_exchange_rate` via `/api/status`
Frontend
- OperationSetting.js & SettingsGeneral.js:
• extend state/inputs with `USDExchangeRate`
• add form field “美元汇率 (non-top-up rate, pricing only)”
- ModelPricing.js already consumes `status.usd_exchange_rate`; no change needed
API
- Administrators can update the rate via `PUT /api/option` (key: `USDExchangeRate`)
- All clients receive the latest rate through `GET /api/status`
This closes the end-to-end flow for displaying model prices in both USD and CNY based on a configurable exchange rate.
* Introduced `showWithRecharge` switch in the actions bar to display model prices based on recharge cost.
* Added a `Select` dropdown (USD / CNY) that appears only when the recharge-price mode is enabled.
* Implemented `displayPrice()` helper to:
* Convert USD prices to recharge prices using `status.price` and `status.usd_exchange_rate`.
* Format output according to the selected currency.
* Updated price rendering for both quota types to use the new helper and respect K/M unit conversion.
* Removed the old currency switch from the header, retaining only the K/M unit toggle.
* Extended `SearchAndActions` memo dependencies; imported `Select` from Semi UI.
* Minor refactors and comment clean-up.
No breaking changes.