Summary
1. Load `channel_info` when editing:
• Detect if the channel is in multi-key mode (`is_multi_key`).
• Auto-initialize `batch`, `multiToSingle`, and `multiKeyMode` from backend data.
2. Visibility logic
• Creation page: “Batch create / Multi-key mode” always available.
• Edit page: show these controls **only when** the channel itself is multi-key.
3. State consistency
• `multi_key_mode` added to `inputs`; `setValues(inputs)` now preserves the user’s selection.
Result
Single-key channels no longer display irrelevant “key aggregation” options, while multi-key channels open with the correct defaults, providing a cleaner and more accurate editing experience.
Introduce two new visualizations to the “Model Data Analysis” panel:
1. Model Consumption Trend (line chart)
• Added `spec_model_line` state and legend support.
• Calculates per-model counts over time and updates via `updateChartData`.
2. Model Call Ranking (bar chart)
• Added `spec_rank_bar` state with `seriesField` and legend enabled.
• Ranks models by total call count.
Additional changes:
• Extended tab navigation with two new `TabPane`s and adjusted chart rendering logic.
• Swapped icons/texts to match new chart purposes.
• Reused existing color mapping to ensure consistent palette.
No breaking changes; UI now offers richer insights into model usage patterns.
Summary:
• Imported InputNumber from @douyinfe/semi-ui.
• Swapped plain Input for InputNumber in “Add Quota” modal.
• Added UX tweaks: full-width styling, showClear, step = 500 000.
• Initialized addQuotaLocal to an empty string so the field starts blank.
• Adjusted state handling and kept quota calculation logic unchanged.
This improves numeric input accuracy and overall user experience without breaking existing functionality.
Motivation
• Remove unused UI components to keep the bundle lean and silence linter warnings.
• Ensure every time the side-sheet opens it reflects the latest tag data, avoiding stale form values (e.g., model / group mismatches).
Key Changes
1. UI Imports
– Dropped `Input`, `Select`, `TextArea` from `@douyinfe/semi-ui` (unused in Form-based version).
2. State Reset & Form Sync
– On `visible` or `tag` change:
• Refresh model & group options.
• Reset `inputs` to clean defaults (`originInputs`) carrying the current `tag`.
• Pre-fill Form through `formApiRef` to keep controlled fields aligned.
3. Minor Cleanup
– Added inline comment clarifying local state reset purpose.
Result
Opening the “Edit Tag” side-sheet now always displays accurate data without residual selections, and build output is cleaner due to removed dead imports.
Overview
• Migrated both `EditChannel.js` and `EditToken.js` to fully leverage Semi UI `Form.*` components, removing legacy `Input/Select/TextArea` + manual labels.
• Unified data-loading strategy: when the drawer becomes visible we load (or reset) data via `props.visible + id` effect and `formApi.setValues()`, guaranteeing fields are always populated; form resets on close.
• Fixed blank-form bug when opening the same record twice.
Key improvements
1. Validation
• `type`, `models` always required.
• `key` required only while creating (not on edit).
2. Batch key creation
• Checkbox moved into `extraText`; hidden when editing or when channel type = 41.
3. Layout & UI
• `Row / Col` (12 + 12) for “Priority” and “Weight”.
• Placeholders revised; model selector now shows creation hint; removed obsolete banner.
• Help / extraText used for long hints, template buttons (`model_mapping`, `status_code_mapping`, `param_override`, etc.), and API address notice.
• Added `showClear`, `min`, rounded card class names for consistency.
4. Reusable helpers
• `batchAllowed`, `batchExtra` utilities.
• `getInitValues()` + centralized `inputs`→form synchronization.
5. Token editor aligned to the same pattern (`props.visiable` watcher).
Result
Cleaner code, consistent UX, instant field population on every open, and clearer validation/error feedback across both editors.
* backend
- constant/endpoint_type.go
• Add EndpointTypeMidjourney, EndpointTypeSuno, EndpointTypeKling, EndpointTypeJimeng.
- common/endpoint_type.go
• Map Midjourney / MidjourneyPlus, SunoAPI, Kling, Jimeng channel types to the new endpoint types.
* frontend
- ModelPricing.js
• Add “Supported Endpoint Type” column.
• Implement renderSupportedEndpoints with `stringToColor` for consistent tag colors.
These changes allow `/api/pricing` and model lists to return accurate
`supported_endpoint_types` covering all non-OpenAI providers and display
them clearly in the UI.
No breaking changes.
Previously, the "Fetch Model List" button was visible in the channel-creation view even though
it only functions once a channel record exists, leading to user confusion.
Changes introduced:
• Render the "Fetch Model List" button only when editing an existing channel (`isEdit === true`).
• Display an informational Banner in creation mode to remind users that the upstream model list
can be fetched after the channel has been created.
• Refactored JSX to apply the above conditional rendering without altering existing logic.
This update streamlines the creation workflow and sets clearer expectations for users.
Changes in `web/src/pages/User/EditUser.js`:
• Added `rules` to
– `Form.Select group`: now required with error “Please select group”.
– `Form.InputNumber quota`: now required with error “Please enter quota”.
• Added `step={500000}` to quota `InputNumber` for quicker numeric input.
• Replaced invalid `readonly` with React-correct `readOnly`, and added descriptive placeholders for all binding-info fields (GitHub/OIDC/WeChat/Email/Telegram).
• Removed unused `downloadTextAsFile` import.
These updates tighten form validation, improve data entry ergonomics, and restore clear read-only indicators for third-party bindings.
Summary:
The redemption list occasionally displayed an invalid range such as “Items -9 - 0” and failed to highlight page 1 after a refresh. This was caused by the table being initialized with `currentPage = 0`.
Changes:
• update `useEffect` to load data starting from page 1 instead of page 0
• refactor `loadRedemptions` to accept `page` (default 1) and sanitize backend‐returned pages (`<= 0` coerced to 1)
• keep other logic unchanged
Impact:
Pagination text and page selection now show correct values on first load or refresh, eliminating negative ranges and ensuring the first page is properly highlighted.
Previously, the table did not enter the loading state after performing actions such as deleting, enabling, or disabling a redemption code. This caused a brief period where the UI appeared unresponsive while awaiting the backend response.
Changes made:
• Added `setLoading(true)` at the beginning of `loadRedemptions` to activate the loading spinner whenever data is (re)fetched.
• Added an explanatory code comment to clarify the intent.
This improves user experience by clearly indicating that the system is processing and prevents confusion during data refresh operations.
SUMMARY
• Re-implemented `EditToken.js` with Semi Form components, eliminating manual state handling and reducing re-renders.
• Added grid-based layout; “Expiration Time” selector now sits inline with quick-set buttons for consistent alignment on desktop & mobile.
• Introduced dedicated “Quota”, “Access”, “Model Limits”, and “Group” cards for clearer field grouping.
• Reworked model-limit interaction: single multi-select list replaces checkbox toggle; backend flag `model_limits_enabled` is now inferred automatically.
• Applied required validation rules to critical fields (`name`, `remain_quota`, `group`, `expired_time`, `tokenCount`) with localized messages.
• Enabled dynamic option loading for models & groups; default auto-group honoured.
• Added unlimited-quota switch, quota presets, and helpful extraText/tooltips.
• Removed obsolete `handleInputChange` & `setUnlimitedQuota` helpers; formApi now manages all data flow.
• Cleaned imports (e.g., dropped unused `IconUserGroup`), fixed linter errors, and updated submit logic to use `formApi.submitForm()`.
RESULT
The token creation/editing experience is faster, more accessible, and easier to maintain, fully aligned with Semi Design best practices.
Summary
• Replaced gradient header blocks with compact, neutral headers wrapped in `Avatar` across the following pages:
- Channel / EditChannel.js
- Channel / EditTagModal.js
- Redemption / EditRedemption.js
- Token / EditToken.js
- User / EditUser.js
- User / AddUser.js
Details
1. Added `Avatar` import and substituted raw icon elements, assigning semantic colors (`blue`, `green`, `purple`, `orange`, etc.) and consistent 16 px icons for a cleaner look.
2. Removed gradient backgrounds, decorative “blur-ball” shapes, and extra paddings from header containers to achieve a tight, flat design.
3. Stripped all `size="large"` attributes from `Button`, `Input`, `Select`, `DatePicker`, `AutoComplete`, and `Avatar` components, allowing default sizing for better visual density.
4. Eliminated redundant `bodyStyle` background overrides in some `SideSheet` components.
5. No business logic touched; all changes are purely presentational.
Result
The editing and creation dialogs now share a unified, compact style consistent with the latest design language, improving readability and user experience without altering functionality.
• Add conditional rendering (`!status.self_use_mode_enabled`) to LoginForm
• Suppress “Don't have an account? Register” CTA in self-hosted scenarios
• Keeps UI clean and prevents unintended user sign-ups under self-use mode
• No impact on regular multi-user deployments
Login Form used to display the message “未登录或登录已过期,请重新登录” twice
because the `useEffect` that inspects the `expired` query parameter was
re-executed on every re-render (e.g. language change or React StrictMode’s
double-mount in development).
### What's changed
• **LoginForm.js** – `useEffect` that shows the toast now has an empty
dependency array so it runs only once on initial mount.
• Reviewed **PasswordResetConfirm.js**, **PasswordResetForm.js** and
**RegisterForm.js** and confirmed they do not contain the same issue;
no changes were required.
### Impact
Users now see the “session expired” notification exactly once, removing
confusion and improving the overall UX.
Why
Clicking the “Continue” button on the login page no longer triggered the submission logic. The issue was introduced when `useState`/`useContext` hooks were destructured incorrectly, breaking the setter reference and omitting required values.
What’s changed
• **LoginForm.js**
– Re-added setter in `useSearchParams` (`[searchParams, setSearchParams]`).
– Corrected order of destructuring for `inputs` so `username`/`password` are available after hooks.
– Switched `useContext` to `[userState, userDispatch]` for consistency.
• **RegisterForm.js**
– Adopted `[userState, userDispatch]` from `UserContext` to mirror LoginForm and retain full state access.
Outcome
Login button now successfully invokes `handleSubmit`, and both auth components have consistent, fully-featured hook destructuring, preventing runtime errors and ensuring future state usage is straightforward.
This commit refreshes the visual design of the authentication pages and aligns them with the Home banner style.
Details
• LoginForm.js / RegisterForm.js / PasswordResetForm.js / PasswordResetConfirm.js
– Wrap top-level container with `relative overflow-hidden` to provide a positioning context.
– Inject two decorative blur balls:
▸ Indigo ball on the top-right (`blur-ball-indigo`).
▸ Teal ball on the middle-left (`blur-ball-teal`).
– Disabled the default X-axis transform on the indigo ball to keep the ball anchored to the corner.
– Removed redundant `mt-[64px]` from the outer container and shifted it to the inner wrapper to maintain vertical rhythm without affecting the background placement.
Result
The auth screens now feature subtle, non-intrusive atmospheric gradients in the top-right and mid-left corners, offering a cohesive look & feel across the application without obstructing the main content.
• LoginForm / RegisterForm now initialise `status` directly from localStorage,
avoiding a post-mount state update that caused a UI flash between OAuth
options and email/username forms.
• Move Turnstile configuration into a dedicated effect that depends on
`status`, ensuring setState is not called during rendering.
• Remove unused `setStatus` setter to resolve ESLint “declared but never read”
warnings.
• Minor refactors: reorder hooks, de-duplicate navigate/context variables and
streamline state destructuring for improved readability.
• Removed the custom `renderArrow` helper and its `Dropdown`-based arrow navigation, simplifying the component logic.
• Switched the `<Tabs>` component to rely on Semi UI’s built-in behaviour (no more `renderArrow` override).
• Kept `type="card"` and `collapsible` props for consistent visual appearance while still using the default style.
• Eliminated the now-unused `Dropdown` import.
This cleanup reduces bespoke UI code, makes future maintenance easier, and keeps the interface consistent with the rest of the application.
• Added read-only Base URL input that shows `status.server_address` (fallback `window.location.origin`) and copies value on click.
• Embedded `ScrollList` as input `suffix`; auto-cycles common endpoints every 3 s and allows manual selection.
• Introduced `API_ENDPOINTS` array in `web/src/constants/common.constant.js` for centralized endpoint management.
• Implemented custom CSS to hide ScrollList wheel indicators / scrollbars for a cleaner look.
• Created two blurred colour spheres behind the banner (`blur-ball-indigo`, `blur-ball-teal`) with light-/dark-mode opacity tweaks and lower vertical placement.
• Increased letter-spacing for Chinese heading via conditional `tracking-wide` / `md:tracking-wider` classes to improve readability.
• Misc: updated imports, helper functions, and responsive sizes to keep UI consistent across devices.
• Removed the dropdown menu previously used for tag-level operations.
• Added a standalone “Edit” button directly after the “Disable All” button, reducing the number of clicks required to edit a tag group.
• Deleted the now-unused `IconEdit` import and its icon reference.
This streamlines the tag management flow and keeps the UI cleaner and more accessible.
All operation-related UI controls in `ChannelsTable` (buttons, dropdowns,
switches, inputs, tags, etc.) now explicitly use `size="small"`.
Reasons & benefits:
- Creates a more compact and consistent look across the table and modals.
- Improves visual coherence between desktop and mobile views.
- Purely presentational; no functional logic is affected.
No database changes or API interactions are involved.