Summary
• Introduced standalone `ModelSelectModal.jsx` for selecting channel models
• Fetch-list now opens modal instead of in-place select, keeping EditChannelModal lean
Modal Features
1. Search bar with `IconSearch`, keyboard clear & mobile full-screen support
2. Tab layout (“New Models” / “Existing Models”) displayed next to title, responsive wrapping
3. Models grouped by vendor via `getModelCategories` and rendered inside always-expanded `Collapse` panels
4. Per-category checkbox in panel extra area for bulk select / deselect
5. Footer checkbox for bulk select of all models in current tab, with real-time counter
6. Empty state uses `IllustrationNoResult` / `IllustrationNoResultDark` for visual consistency
7. Accessible header/footer paddings aligned with Semi UI defaults
Fixes & Improvements
• All indeterminate and full-select states handled correctly
• Consistent “selected X / Y” stats synced with active tab, not global list
• All panels now controlled via `activeKey`, ensuring they remain expanded
• Search, vendor grouping, and responsive layout tested across mobile & desktop
These changes modernise the channel model management workflow and prepare the codebase for upcoming upstream-ratio integration.
Summary
• Added role-specific localStorage keys for column visibility in three hooks:
- `useUsageLogsData.js` → `logs-table-columns-admin` / `logs-table-columns-user`
- `useMjLogsData.js` → `mj-logs-table-columns-admin` / `mj-logs-table-columns-user`
- `useTaskLogsData.js` → `task-logs-table-columns-admin` / `task-logs-table-columns-user`
Details
1. Each hook now derives a `STORAGE_KEY` based on `isAdminUser`, preventing admin and non-admin sessions from overwriting one another’s column settings.
2. Removed the previous “save but strip admin columns” workaround—settings are persisted unmodified to each role’s key.
3. Kept runtime behaviour: non-admin users still see admin-only columns forcibly hidden.
4. Replaced newly added Chinese comments with clear English equivalents for consistency.
Result
Switching between admin and non-admin accounts no longer corrupts column visibility preferences, and codebase comments are fully English-localized.
Summary
• Introduced a unified `selectFilter` helper that matches both `option.value` and `option.label`, ensuring all `<Select>` components support intuitive search (fixes channel “type” dropdown not filtering).
• Replaced all usages of the old `modelSelectFilter` with `selectFilter` in:
• `EditChannelModal.jsx`
• `SettingsPanel.js`
• `EditTokenModal.jsx`
• `EditTagModal.jsx`
• Removed the deprecated `modelSelectFilter` export from `utils.js` (no backward-compat alias).
• Updated documentation comments accordingly.
Why
The old filter only inspected `option.value`, causing searches to fail when `label` carried the meaningful text (e.g., numeric IDs for channel types). The new helper searches both fields, covering all scenarios and unifying the API across the codebase.
Notes
No functional regressions expected; all components have been migrated.
Previously, the "Force Format" switch was displayed for every channel type
although it only applies to OpenAI (type === 1).
This change wraps the switch in a conditional so it renders exclusively when
the selected channel type is OpenAI.
Why:
- Prevents user confusion when configuring non-OpenAI channels
- Keeps the UI clean and context-relevant
Scope:
- web/src/components/table/channels/modals/EditChannelModal.jsx
No backend logic affected.
- Extract channel extra settings into a dedicated Card component for better visual hierarchy
- Replace custom gray background container with consistent Form component styling
- Simplify layout structure by removing complex Row/Col grid layout in favor of native Form component layout
- Unify help text styling by using extraText prop consistently across all form fields
- Move "Settings Documentation" link to card header subtitle for better accessibility
- Improve visual consistency with other setting cards by using matching design patterns
The channel extra settings (force format, thinking content conversion, pass-through body, proxy address, and system prompt) now follow the same design language as other configuration sections, providing a more cohesive user experience.
Affected settings:
- Force Format (OpenAI channels only)
- Thinking Content Conversion
- Pass-through Body
- Proxy Address
- System Prompt
Ensure non-admin users cannot enable columns reserved for administrators
across the following hooks:
* web/src/hooks/usage-logs/useUsageLogsData.js
- Force-hide CHANNEL, USERNAME and RETRY columns for non-admins.
* web/src/hooks/mj-logs/useMjLogsData.js
- Force-hide CHANNEL and SUBMIT_RESULT columns for non-admins.
* web/src/hooks/task-logs/useTaskLogsData.js
- Force-hide CHANNEL column for non-admins.
The checks run when loading column preferences from localStorage, overriding
any tampered settings to keep sensitive information hidden from
unauthorized users.
The VolcEngine Ark/Doubao channel now has a hard-coded base URL inside the backend, so it no longer requires any API-address settings on the front-end side.
Previously, the input field was hidden but the surrounding “API Config” card still rendered, leaving a blank, confusing section.
Changes made
• Added `showApiConfigCard` flag (true when `inputs.type !== 45`) right after the state declarations.
• Wrapped the entire “API Config” card in a conditional render driven by this flag.
• Removed the duplicate declaration of `showApiConfigCard` further down in the component to avoid shadowing and improve readability.
Scope verification
• Checked all other channel types: every remaining type either displays a dedicated API-related input/banner (3, 8, 22, 36, 37, 40, …) or falls back to the generic “custom API address” field.
• Therefore, only type 45 requires the card to be fully hidden.
Result
The “Edit Channel” modal now shows no empty card for the VolcEngine Ark/Doubao channel, leading to a cleaner and more intuitive UI while preserving behaviour for all other channels.
- 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.