- Unify TopUp into a single-page layout and remove tabs
- Replace custom inputs with Semi UI Form components (Form.Input, Form.InputNumber, Form.Slot)
- Move online recharge form into the stats Card content for tighter, consistent layout
- Add account stats Card with blue theme (consistent with InvitationCard style)
- Remove RightStatsCard and inline the stats UI directly in RechargeCard
- Change preset amount UI to horizontal quick-action Buttons; swap order with payment methods
- Replace payment method Cards with Semi UI Buttons
- Use Button icon prop for Alipay/WeChat/Stripe with brand colors
- Use built-in Button loading; remove custom “processing...” text
- Replace custom spinners with Semi UI Spin and keep Skeleton for amount loading
- Wrap Redeem Code in a Card; use Typography for “Looking for a code? Buy Redeem Code” link
- Show info Banner when online recharge is disabled (instead of warning)
TopUp data flow and logic
- Generate preset amounts from min_topup using multipliers [1,5,10,30,50,100,300,500]
- Deduplicate /api/user/aff using a ref guard; fetch only once on mount
- Simplify user self fetch: update context only; remove unused local states and helpers
- Normalize payment method keys to alipay/wxpay/stripe and assign default colors
Cleanup
- Delete web/src/components/topup/RightStatsCard.jsx
- Remove unused helpers and local states in index.jsx (userQuota, userDataLoading, getUsername)
Dev notes
- No API changes; UI/UX refactor only
- Lint clean (no new linter errors)
Files
- web/src/components/topup/RechargeCard.jsx
- web/src/components/topup/index.jsx
- web/src/components/topup/InvitationCard.jsx (visual parity reference)
- web/src/components/topup/RightStatsCard.jsx (removed)
- Move card titles (earnings, total revenue, invitations) to Card title prop for consistency
- Remove custom color classes in favor of Semi-UI's built-in type system
- Standardize Text component usage with strong and tertiary types
- Improve code maintainability and visual consistency across all cards
- Align structure with existing reward description card pattern
Summary of changes
1. SetupWizard.jsx
• Center card (`min-h-screen flex items-center justify-center`) and remove top margin.
• Merge step indicator/content into single card; added `Divider` separator.
• Added sweep-shine animation to current step title via existing `shine-text` class.
• Simplified imports (removed Avatar / Typography) and deleted unused modal state.
2. Step components
• Stripped outer `Card` and header sections from `DatabaseStep.jsx`, `AdminStep.jsx`, `UsageModeStep.jsx`, `CompleteStep.jsx` to fit single-card layout.
• Removed unused imports and props.
3. Components cleanup
• Deleted obsolete files:
- `components/setup/components/SetupSteps.jsx`
- `components/setup/components/modals/UsageModeInfoModal.jsx`
• Updated `setup/index.jsx` exports accordingly.
4. Styling
• Ensured global sweep-shine effect already present in `index.css` is reused for step titles.
5. i18n
• Pruned unused translation keys related to removed components from `i18n/locales/en.json`.
6. Miscellaneous
• Removed redundant Avatar/Icon imports from multiple files.
• All linter checks pass with no new warnings.
This commit consolidates the initialization flow into a cleaner, centered single-card wizard, adds visual polish, and reduces dead code for easier maintenance.
- AccountManagement.js
- Prevent action button from shifting when account IDs are long by adding gap, min-w-0, and flex-shrink-0; keep buttons in a fixed position.
- Add copyable Popover for account identifiers (email/GitHub/OIDC/Telegram/LinuxDO) using Typography.Paragraph with copyable; reveal full text on hover.
- Ensure ellipsis works by rendering the popover trigger as `block max-w-full truncate`.
- Import Popover and wire up `renderAccountInfo` across all binding rows.
- UserInfoHeader.js
- Apply unified `with-pastel-balls` background to match PricingVendorIntro.
- Remove legacy absolute-positioned circles and top gradient bar to avoid visual overlap.
- RechargeCard.jsx
- Colorize non-Alipay/WeChat/Stripe payment icons using backend `pay_methods[].color`; fallback to `var(--semi-color-text-2)`.
- Add `showClear` to the redemption code input for quicker clearing.
Notes:
- No linter errors introduced.
- i18n strings and behavior remain unchanged except for improved UX and visual consistency.
- Add RightStatsCard and place it in RechargeCard header
- Shows current balance, historical spend, and request count
- Mobile: stacks under title; three metrics split equally (flex-1); vertical dividers hidden on small screens
- Remove extra margins; small card styling
- RechargeCard
- Replace redeem code Input icon with Semi UI IconGift
- Style “Payable amount” number in red and bold; keep same style in confirm modal
- Always render payment methods as Cards (remove Button variant) with adaptive grid
- Use brand color icons: SiAlipay (#1677FF), SiWechat (#07C160), SiStripe (#635BFF)
- Replace Stripe icon with SiStripe
- Integrate RightStatsCard props; adjust header to flex-col on mobile and flex-row on desktop
- Hide Banner close button when online top-up is disabled (closeIcon={null})
- InvitationCard
- Simplify to match RechargeCard’s minimalist slate style
- Use Card title for “Rewards” and place content directly in body
- Improve link input and copy button; use Badge dots for bullet points
- TopUp index
- Remove separate right-column stats card; pass userState and renderQuota to RechargeCard
- Cleanup
- Lint passes; no functional changes to APIs or business logic
- Split the 1554-line PersonalSetting.js file into smaller, maintainable components
- Created organized folder structure under personal/:
- components/: UserInfoHeader for shared user info display
- tabs/: ModelsList, AccountBinding, SecuritySettings, NotificationSettings
- modals/: EmailBindModal, WeChatBindModal, AccountDeleteModal, ChangePasswordModal
- Refactored main PersonalSetting component to use composition pattern
- Improved code maintainability and separation of concerns
- Added collapsible prop to ModelsList tabs for better UX
- Fixed import path for TwoFASetting component in SecuritySettings
- Preserved all existing functionality and user interactions
This refactoring reduces the main file from 1554 to 484 lines and makes
the codebase more modular, testable, and easier to maintain.
- Add comprehensive i18n support to TwoFASetting.js component
- Add all required English translations to en.json for 2FA settings
- Update component to accept t function as prop and use translation keys
- Fix prop passing in PersonalSetting.js to provide t function
- Maintain all existing UI improvements and functionality
- Support both Chinese and English interfaces for:
* Main 2FA settings card with status indicators
* Setup modal with guided steps (QR scan, backup codes, verification)
* Disable 2FA modal with impact warnings and confirmation
* Regenerate backup codes modal with success states
* All buttons, placeholders, messages, and notifications
- Follow project i18n conventions using t('key') pattern
- Ensure seamless language switching for enhanced user experience
This enables the 2FA settings to be fully localized while preserving
the modern UI design and improved user workflow from previous updates.
- Add new Forbidden page at /forbidden (`web/src/pages/Forbidden/index.js`)
- Use Semi-UI Empty with IllustrationNoAccess (250x250)
- Update i18n description to: '您无权访问此页面,请联系管理员~'
- Align visual style with existing 404 page
- Introduce `AdminRoute` in `web/src/helpers/auth.js`
- Use `UserContext`/localStorage; redirect to `/forbidden` when `!user` or `user.role < 10`
- Protect console/admin routes with `AdminRoute` and register `/forbidden` in `web/src/App.js`
- Update `web/src/i18n/locales/en.json`
- Add English translation for the new forbidden message
- Remove legacy "没有权限" entry
- Lint passes; no runtime errors observed
Summary:
• Updated `helpers/utils.js` to display the “group” label without a colon, ensuring consistent typography with other price elements.
Details:
1. `formatPriceInfo`
– Changed `{t('分组')}:` to `{t('分组')}` for a cleaner look.
– Keeps spacing intact between label and selected group name.
2. No functional impact; purely visual polish.
Overview:
• Introduced a new “Model Tag” filter across pricing screens
• Refactored `usePricingFilterCounts` to eliminate duplicated logic
• Improved tag handling to be case-insensitive and deduplicated
• Extended utilities to reset & persist the new filter
Details:
1. Added `filterTag` state to `useModelPricingData` and integrated it into all filtering paths.
2. Created reusable `PricingTags` component using `SelectableButtonGroup`.
3. Incorporated tag filter into `PricingSidebar` and mobile `PricingFilterModal`, including reset support.
4. Enhanced `resetPricingFilters` (helpers/utils) to restore tag filter defaults.
5. Refactored `usePricingFilterCounts.js`:
• Centralized predicate `matchesFilters` to remove redundancy
• Normalized tag parsing via `normalizeTags` helper
• Memoized model subsets with concise filter calls
6. Updated lints – zero errors after refactor.
Result:
Users can now filter models by custom tags with consistent UX, and internal logic is cleaner, faster, and easier to extend.
Backend:
- Model: Add `icon` field to `model.Model` (gorm: varchar(128)); auto-migrated via GORM.
- Pricing API: Extend `model.Pricing` with `icon` and populate from model meta in `GetPricing()`.
Frontend:
- EditModelModal: Add `icon` input (with @lobehub/icons helper link); wire into init/load/submit flows.
- ModelHeader / PricingCardView: Prefer rendering `model.icon`; fallback to `vendor_icon`; final fallback to initials avatar.
- Models table: Add leading “Icon” column, rendering `model.icon` or `vendor` icon via `getLobeHubIcon`.
Notes:
- Backward-compatible. Existing data without `icon` remain unaffected.
- No manual SQL needed; column is added by AutoMigrate.
Affected files:
- model/model_meta.go
- model/pricing.go
- web/src/components/table/models/modals/EditModelModal.jsx
- web/src/components/table/model-pricing/modal/components/ModelHeader.jsx
- web/src/components/table/model-pricing/view/card/PricingCardView.jsx
- web/src/components/table/models/ModelsColumnDefs.js
- Replace custom dots with Semi Badge types (success/danger/warning); add compact Progress bars
- Remove pie chart and related deps/config; move total key count and mode tags into the modal title
- Rework header using Row/Col; three equal stat cards (enabled/manual-disabled/auto-disabled)
- Integrate toolbar into Table title; wrap content with Card; use Table’s native empty state
- Make “Enable All” conditional (hidden when all keys are enabled), mirroring “Disable All”
- Unify numeric typography (current/total same size) for better readability
- Default page size set to 10; fallback to 10 when backend page_size is absent; page-size options: 10/20/50/100
- Cleanup imports and dead code (remove VChart and pie-spec logic)
- Minor spacing polish (extra bottom margin before table), no footer buttons
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.
- 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
- Remove K/M switch from model price column header in pricing table
- Add "Display in K units" option to pricing display settings panel
- Update parameter passing for tokenUnit and setTokenUnit across components:
- PricingDisplaySettings: Add tokenUnit toggle functionality
- PricingSidebar: Pass tokenUnit props to display settings
- PricingFilterModal: Include tokenUnit in mobile filter modal
- Enhance resetPricingFilters utility to reset token unit to default 'M'
- Clean up PricingTableColumns by removing unused setTokenUnit parameter
- Add English translation for "按K显示单位" as "Display in K units"
This change improves UX by consolidating all display-related controls
in the filter settings panel, making the interface more organized and
the token unit setting more discoverable alongside other display options.
Affected components:
- PricingTableColumns.js
- PricingDisplaySettings.jsx
- PricingSidebar.jsx
- PricingFilterModal.jsx
- PricingTable.jsx
- utils.js (resetPricingFilters)
- en.json (translations)
* **PricingDisplaySettings.jsx**
• Extracted display settings (recharge price, currency, ratio toggle) from PricingSidebar
• Maintains complete styling and functionality as standalone component
* **SelectableButtonGroup.jsx**
• Added isMobile detection with conditional Col spans
• Mobile: `span={12}` (2 buttons per row) for better touch experience
• Desktop: preserved responsive grid `xs={24} sm={24} md={24} lg={12} xl={8}`
* **PricingSidebar.jsx**
• Updated imports to use new PricingDisplaySettings component
• Simplified component structure while preserving reset logic
These changes enhance code modularity and provide optimized mobile UX for filter button groups across the pricing interface.
- 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.
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
-------
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)
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.
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.
* Removed `prompt` prop from `Loading` and switched to built-in Spin indicator with default size `small`
* Dropped overlay background to make the spinner more reusable
* Replaced custom text span; callers can now supply tip via their own UI if needed
* Cleaned up `OAuth2Callback`:
- Eliminated unused state/variables
- Added MAX_RETRIES with incremental back-off
- Centralized error handling via try/catch
- Streamlined navigation logic on success/failure
- Updated imports to match new Loading signature
BREAKING CHANGE: `Loading` no longer accepts a `prompt` prop. Update all invocations accordingly.
Backend
1. controller/channel.go
• Always hydrate `ChannelInfo` from DB in `UpdateChannel`, keeping `IsMultiKey` true so `MultiKeySize` is recalculated.
2. model/channel.go
• getKeys(): accept both newline-separated keys and JSON array (`[ {...}, {...} ]`).
• Update(): reuse new parser-logic to recalc `MultiKeySize`; prune stale indices in `MultiKeyStatusList`.
Frontend
1. pages/Channel/EditChannel.js
• `handleVertexUploadChange`
– Reset `vertexErroredNames` on every change so the “ignored files” prompt always re-appears.
– In single-key mode keep only the last file; in batch mode keep all valid files.
– Parse files, display “以下文件解析失败,已忽略:…”.
• Batch-toggle checkbox
– When switching from batch→single while multiple files are present, show a confirm dialog and retain only the first file (synchronises state, form and local caches).
• On opening the “new channel” side-sheet, clear `vertexErroredNames` to restore error prompts.
Result
• “已启用 x/x” count updates immediately after editing multi-key channels.
• Vertex-AI key upload works intuitively: proper error feedback, no duplicated files, and safe down-switch from batch to single mode.
- Remove flex layout from uptime service card to eliminate bottom spacing
- Remove flex-1 and mt-auto classes that caused unnecessary stretching
- Replace IconRotate with IconSend for request count to better represent the semantic meaning
- Legend now sits directly below content instead of being pushed to bottom
Fixes the visual issue where uptime service availability card had unwanted white space at the bottom when content was minimal.
* Refactored the render logic of the **Channel** column
* Wrapped tooltip around the first `Tag` only to restore hover behavior when multi-key mode is enabled
* Added i18n-friendly fallback (`t('未知渠道')`) for cases where `channel_name` is missing
* Improves user experience for administrators by reliably showing channel names even with multiple keys
Adds UI fallback in TokensTable “Available Models” column:
• Tracks models already matched to a known vendor icon.
• Collects unmatched models and renders a neutral “Other” avatar (labelled via `t('其他')`) with a tooltip listing the model names.
• Removes previous generic fallback so every model is now either vendor-specific or grouped under “Other”.
This improves clarity for users by explicitly indicating models from unrecognized providers rather than leaving them unlabelled.
Add custom validator to the `expired_time` DatePicker in `EditToken.js`
to ensure that selected expiration timestamps are strictly in the future.
- Introduce Promise-based validator that:
• Rejects invalid date formats with a clear error message
• Prevents past or current dates and shows “Expiration time cannot be earlier than the current time!”
- Keeps support for the special “never expires” value (-1)
- Blocks form submission until a valid future datetime is provided
This change prevents accidental creation of already expired tokens and
improves overall robustness of token management.
This commit overhauls the `TokensTable` component to deliver a cleaner, more intuitive experience.
Key changes
1. Quota
• Merged “Used” & “Remaining” into a single “Quota” column.
• Uses a circular `Progress` with %-label; full details shown on tooltip.
2. Status
• Tag now embeds a small `Switch` (prefixIcon) to enable/disable a token in-place.
• Removed enable/disable actions from the old dropdown.
3. Columns & layout
• Added dedicated “Group” column (moved from Status).
• Added “Key” column:
– Read-only `Input` styled like Home page base-URL field.
– Masked value (`sk-abc********xyz`) by default.
– Eye button toggles reveal/hide; Copy button copies full key (without modal).
• Dropped “More” menu; Delete is now a direct button in the action area.
4. Model limits
• Shows vendor icons inside an `AvatarGroup`; tooltip lists the exact models.
5. IP restriction
• Displays first IP, extra count as “+N” Tag with tooltip.
• Unlimited shows white Tag.
6. Cleanup / misc.
• Removed unused helpers (`getQuotaPerUnit`), icons (`IconMore`, eye/copy duplicates, etc.).
• Replaced legacy modal view of key with inline input behaviour.
• Tweaked paddings, themes, sizes to align with design system.
BREAKING CHANGE: Table column order & names have changed; update any tests or docs referencing the old structure.
Summary
• **EditChannel.js**
– Relocated the following conditional inputs from “Advanced Settings” to the initial “Basic Info” card:
• Model version (type 18)
• Deployment region (type 41)
• Knowledge-base ID (type 21)
• Account ID (type 39)
• Agent ID (type 49)
• OpenAI organization (type 1)
– No functional changes; layout only.
Why
These fields are commonly filled during the first steps of channel creation. Surfacing them earlier reduces scrolling and streamlines the user workflow.
Summary
• **en.json**
– Added translation for “是否自动禁用” → “Whether to automatically disable”.
– Stubbed/added key for helper text “仅当自动禁用开启时有效,关闭后不会自动禁用该渠道” (translation placeholder left for future update).
Why
These keys were previously untranslated, causing mixed-language UI for the “Auto Disable” toggle in the channel edit form. Filling them (or at least registering the keys) ensures consistent localization and prevents runtime fallbacks.
Summary
• **EditChannel.js**
– Displays “Fetch Model List” button for both *create* and *edit* modes (removed `isEdit` guard).
– Unified model selector placeholder to “Please choose supported models”.
– Added null-safety checks when parsing Axios responses.
– Sends requests with `{ skipErrorHandler: true }`, preventing generic *500 Internal Server Error* toasts and relying on context-specific messages instead.
• **helpers/api.js**
– Introduced `skipErrorHandler` flag in the Axios response interceptor.
If present, global `showError` is bypassed, giving callers full control over user-facing notifications.
– Ensures `Promise.reject(error)` is returned for proper error propagation.
Why
Channel creators now enjoy the same convenience as editors when importing upstream model lists.
Meanwhile, suppressing redundant toasts removes confusion caused by simultaneous custom and generic error messages.
This commit brings System Settings in line with Payment Settings and
prepares the whole component for multi-language deployments.
Key points
----------
• Introduced a “General Settings” card in `SystemSetting.js`
- Adds a `ServerAddress` field (copied from Payment Settings).
- Explains that this URL is used for payment callback & default homepage.
- Implements `submitServerAddress` to persist the option.
• Internationalisation
- Imported `useTranslation` and wrapped **all** Chinese UI strings in `t()`.
- Localised section titles, labels, placeholders, banners, buttons,
modal texts and toast messages.
- Dynamic banner/tool-tip descriptions now combine `t()` fragments with
template literals for runtime URLs.
• UX improvements
- Added contextual `extraText` under the ServerAddress input.
- Ensured placeholders like “sensitive info…” are translatable.
With these changes, administrators can configure the server URL from the
System Settings tab, and the entire page is ready for seamless language
switching via the existing i18n framework.