Commit Graph

807 Commits

Author SHA1 Message Date
t0ng7u
5407a8345f ♻️ refactor: restructure MjLogsTable into modular component architecture
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.
2025-07-18 22:19:58 +08:00
t0ng7u
3fe509757b ♻️ refactor: restructure LogsTable into modular component architecture
Refactor the monolithic LogsTable component (1453 lines) into a modular,
maintainable architecture following the channels table pattern.

## What Changed

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

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

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

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

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

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

## Breaking Changes
None - all existing imports and functionality preserved.
2025-07-18 22:04:54 +08:00
t0ng7u
6799daacd1 🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
   • `channels/index.jsx` – composition entry
   • `ChannelsTable.jsx` – pure `<Table>` rendering
   • `ChannelsActions.jsx` – bulk & settings toolbar
   • `ChannelsFilters.jsx` – search / create / column-settings form
   • `ChannelsTabs.jsx` – type tabs
   • `ChannelsColumnDefs.js` – column definitions & render helpers
   • `modals/` – BatchTag, ColumnSelector, ModelTest modals

2. Extract domain hook
   • Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
     – centralises state, API calls, pagination, filters, batch ops
     – now exports `setActivePage`, fixing tab / status switch errors

3. Update wiring
   • All sub-components consume data via `useChannelsData` props
   • Adjusted import paths after hook relocation

4. Clean legacy file
   • Legacy `components/table/ChannelsTable.js` now re-exports new module

5. Bug fixes
   • Tab switching, status filter & tag aggregation restored
   • Column selector & batch actions operate via unified hook

This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00
t0ng7u
f43c695527 🗑️ refactor(table): remove custom formatPageText from all table components
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.
2025-07-18 10:59:24 +08:00
t0ng7u
ead43f081c 🎉 feat(i18n): integrate Semi UI LocaleProvider with dynamic i18next language support
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.
2025-07-18 10:55:05 +08:00
t0ng7u
218ad6bbe0 🎨 refactor(ui): scope table scrolling to console cards & refine overall layout
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.
2025-07-18 01:06:18 +08:00
t0ng7u
15f65bb558 🌐 feat: add configurable USD exchange-rate support across backend & frontend
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.
2025-07-17 23:04:45 +08:00
t0ng7u
f1506ed5da 💸 feat(model-pricing): add “show with recharge price” toggle and USD/CNY selector
* 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.
2025-07-17 22:07:06 +08:00
t0ng7u
afa9c650fe 💱 feat(model-pricing): add currency (USD/CNY) & token unit (M/K) toggles to Model Pricing table
* Introduced a currency switch to toggle prices between USD and CNY.
  * CNY prices are calculated by multiplying USD prices with the site-wide `price` rate from `/api/status`.
* Added a second switch to display prices per 1 M tokens or per 1 K tokens.
  * When “K” is selected, prices are divided by 1 000 and labels are updated accordingly.
* Extended component state with `currency` and `tokenUnit` variables.
* Integrated `StatusContext` to retrieve and memoize the current exchange rate.
* Updated price rendering logic and labels to reflect selected currency and token unit.
* Minor UI tweaks: kept Switch components compact and aligned with the table header.

No breaking changes.
2025-07-17 19:07:11 +08:00
t0ng7u
cf46b89814 🧹 refactor(PageLayout): remove unused state variables
Removed unused `userState` and `statusState` bindings from `PageLayout.js`
while retaining their dispatch functions for authentication and status
management. Confirmed correct use of array destructuring to skip the
unused toggle function returned by `useSidebarCollapsed`.

This change introduces no functional differences and solely improves
readability and maintainability.
2025-07-16 04:50:23 +08:00
t0ng7u
3360b34af9 🐛 fix: SSR hydration mismatch in mobile detection & clean up sidebar style
- Added a server-snapshot fallback (`() => false`) to `useIsMobile` to ensure
  consistent results between server-side rendering and the browser, preventing
  hydration mismatches.
- Removed a redundant ternary in `PageLayout` sidebar styles, replacing
  `isMobile ? 'fixed' : 'fixed'` with a single `'fixed'` value for clarity.

These changes improve SSR reliability and tidy up inline styles without
affecting runtime functionality.
2025-07-16 04:46:31 +08:00
t0ng7u
4558eb41fc 🎨 feat(sidebar): replace custom collapse button with Semi UI Button
* Replaced the handmade collapse/expand div with Semi UI `<Button>`
  * Uses `theme="outline"` and `type="tertiary"` for outlined style
  * Shows icon + text when sidebar is expanded, icon-only when collapsed
* Added `iconOnly` prop and dynamic padding to remove extra text area in collapsed state
* Ensured full-width layout with consistent padding for both states
* Updated imports to include `Button` from `@douyinfe/semi-ui`
* Maintains tooltip content for accessibility and better UX
2025-07-16 04:35:19 +08:00
t0ng7u
bbc5584f80 ♻️ refactor(auth, ui): simplify Loading component & optimize OAuth2Callback flow
* 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.
2025-07-16 04:21:13 +08:00
t0ng7u
8604c9f9d5 feat(HeaderBar): ensure skeleton shows ≥500 ms and waits for real status data
The header’s skeleton screen now remains visible for at least 500 ms and
only disappears after `/api/status` has successfully populated
`StatusContext`.

Changes include:
• Added `loadingStartRef` to record the mount time.
• Reworked loading effect to compute the remaining delay based on the
  elapsed time and the presence of real status data.
• Removed the previous fixed‐timer logic, preventing premature content
  rendering and improving perceived loading consistency across pages.
2025-07-16 04:02:05 +08:00
t0ng7u
747e02ee0d 📱 feat(ui): auto-close sidebar on mobile after menu navigation
Adds a smoother mobile experience by automatically closing the sidebar
drawer once a menu item is tapped.

### Details
* SiderBar
  * Introduce `onNavigate` prop and invoke it on every `<Link>` click.
  * Remove unused `useIsMobile` hook and related `isMobile` variable.
* PageLayout
  * Pass `onNavigate` callback to `SiderBar` that sets `drawerOpen` to
    `false` when on mobile, ensuring the sidebar collapses after
    navigation.

This eliminates the “isMobile declared but never used” warning and
aligns the behaviour of the sidebar with common mobile UX expectations.
2025-07-16 03:52:40 +08:00
t0ng7u
a44fc51007 📱 refactor(web): remove legacy isMobile util and migrate to useIsMobile hook
BREAKING CHANGE:
helpers/utils.js no longer exports `isMobile()`.
Any external code that relied on this function must switch to the `useIsMobile` React hook.

Summary
-------
1. Deleted the obsolete `isMobile()` function from helpers/utils.js.
2. Introduced `MOBILE_BREAKPOINT` constant and `matchMedia`-based detection for non-React contexts.
3. Reworked toast positioning logic in utils.js to rely on `matchMedia`.
4. Updated render.js:
   • Removed isMobile import.
   • Added MOBILE_BREAKPOINT detection in `truncateText`.
5. Migrated every page/component to the `useIsMobile` hook:
   • Layout: HeaderBar, PageLayout, SiderBar
   • Pages: Home, Detail, Playground, User (Add/Edit), Token, Channel, Redemption, Ratio Sync
   • Components: ChannelsTable, ChannelSelectorModal, ConflictConfirmModal
6. Purged all remaining `isMobile()` calls and legacy imports.
7. Added missing `const isMobile = useIsMobile()` declarations where required.

Benefits
--------
• Unifies mobile detection with a React-friendly hook.
• Eliminates duplicated logic and improves maintainability.
• Keeps non-React helpers lightweight by using `matchMedia` directly.
2025-07-16 02:54:58 +08:00
t0ng7u
b2b018ab93 🚀 feat(frontend): add robust boolean handling across settings pages
Summary
-------
1. Introduced a reusable `toBoolean` utility (`web/src/helpers/boolean.js`) that converts
   strings (`'true'/'false'`, `'1'/'0'`), numbers, and native booleans to a proper boolean.
2. Re-exported `toBoolean` via `web/src/helpers/index.js` for simple one-line imports.

Refactors
---------
• Systematically replaced all legacy `item.value === 'true'` checks with `toBoolean(item.value)` in
  the following components:
  – `SystemSetting.js`
  – `OperationSetting.js`
  – `PaymentSetting.js`
  – `RatioSetting.js`
  – `RateLimitSetting.js`
  – `ModelSetting.js`
  – `DrawingSetting.js`
  – `DashboardSetting.js`
  – `ChatsSetting.js`

• Unified import statements to
  `import { …, toBoolean } from '../../helpers';`
  removing redundant `../../helpers/boolean` paths.

Why
---
SQLite sometimes returns `1/0` or boolean literals instead of the string `'true'/'false'`, causing
checkbox states to reset on page reload. The new utility guarantees consistent boolean parsing,
fixing the issue across all environments (SQLite, MySQL, etc.) while improving code clarity.
2025-07-15 17:18:48 +08:00
t0ng7u
06ad5e3f8c 🐛 fix: multi-key channel sync and Vertex-AI key-upload edge cases
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.
2025-07-15 12:02:04 +08:00
t0ng7u
eb59f9c75d feat(ui): enhance loading states and fix layout issues
- Fix uptime service card bottom spacing by removing flex layout
- Replace IconRotate with IconSend for request count to better represent semantic meaning
- Add skeleton loading placeholders for all dashboard statistics with 500ms minimum duration
- Unify avgRPM and avgTPM calculation with consistent NaN handling
- Standardize skeleton usage across HeaderBar and Detail components with active animations
- Remove unnecessary empty wrapper elements in skeleton implementations
- Remove gradient styling from system name in header

The changes improve user experience with consistent loading states, better semantic icons,
and eliminate visual layout issues in the dashboard cards.
2025-07-14 23:31:01 +08:00
t0ng7u
a36ce199ba feat: implement backend channel duplication & streamline frontend copy flow
Add a dedicated backend endpoint to clone an existing channel (including its key) and
replace all previous front-end cloning logic with a single API call.

Backend
• controller/channel.go
  – add CopyChannel: safely clone a channel, reset balance/usage, append name suffix,
    preserve key, create abilities, return new ID.
  – supports optional query params: `suffix`, `reset_balance`.
• router/api-router.go
  – register POST /api/channel/copy/:id (secured by AdminAuth).
• model interaction uses BatchInsertChannels to ensure transactional integrity.

Frontend
• ChannelsTable.js
  – simplify copySelectedChannel: call /api/channel/copy/{id} and refresh list.
  – remove complex field-manipulation & key-fetching logic.
  – improved error handling.

Security & stability
• All cloning done server-side; sensitive key never exposed to client.
• Route inherits existing admin middleware.
• Graceful JSON responses with detailed error messages.
2025-07-14 21:54:53 +08:00
t0ng7u
5f011502d1 🍎style(button): Optimize the colors of all buttons to reduce visual fatigue 2025-07-14 19:49:40 +08:00
t0ng7u
52fe92ed7f 🐛 fix: Ensure channel tooltip displays correctly in LogsTable
* 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
2025-07-14 13:12:40 +08:00
t0ng7u
0d005df463 🎨 feat(ui): Change TolenTables Progress Style marginTop 0 to 1px 2025-07-13 19:34:20 +08:00
t0ng7u
a203e98689 💄 feat(ui): Enhance TokensTable quota presentation and clean up code
Summary
• Re-architect the status column to embed quota information directly inside the Tag suffix.
• Consolidate rendering logic for clearer structure and easier maintenance.

Details
• Moved the quota Progress bar under the remaining / total text, inside `quotaSuffix`.
• Added “Unlimited” label for tokens with `unlimited_quota`; hides Progress and Tooltip in this case.
• Tightened vertical spacing with a flex container (`gap-[2px]`, `leading-none`) and removed extra wrappers; Progress now has zero top/bottom margin and full-width style.
• Refactored variables:
  – Replaced `tagNode/bodyContent` with a single `content` node.
  – Wrapped `content` with Tooltip only when quota is limited.
• Visual tweaks:
  – Applied `size='large'` to the Tag for better alignment.
  – Ensured consistent color via shared `getProgressColor`.
• Deleted obsolete comments and redundant code.

Result
Improves readability of the component and delivers a cleaner, more compact quota display.
2025-07-13 19:14:43 +08:00
t0ng7u
27f99a0f38 🔍 feat(edit-token): add search capability to model limit selector
Changes:
• `Form.Select` for “Model Limits” now supports in-dropdown searching (`filter` + `searchPosition='dropdown'`) enabling quick model lookup.
• Removed `maxTagCount` to display all selected models without truncation.

Benefit: simplifies selecting specific models when the list is large, improving usability during token creation/editing.
2025-07-13 18:25:05 +08:00
t0ng7u
d1e48d02bd 🎨 style(tokens-table): enhance quota usage progress bar UI
Improves the “Balance” column in `TokensTable`:

• Re-styled progress bar: wider container (`w-[140px]`) and `showInfo` enabled to display percentage label.
• Added `format={() => \`\${percent}%\`}` for precise percentage feedback.
• Maintains dynamic color mapping (success / warning / danger) for clarity.

Result: clearer, more informative visual representation of remaining token quota.
2025-07-13 18:10:59 +08:00
t0ng7u
4f06a1df50 🔄 fix(tables): keep current page after edits & auto-fallback when page becomes empty
Includes ChannelsTable, RedemptionsTable and UsersTable:

• Refactor `refresh(page = activePage)` in all three tables so data reloads the requested (or current) page instead of forcing page 1.
• On single-row deletion (and bulk deletion in ChannelsTable):
  – Refresh current page immediately.
  – If the refreshed page has no data and `activePage > 1`, automatically load the previous page to avoid blank views.
• RedemptionsTable: corrected prior bug where `refresh` used `activePage - 1`.
• Misc: removed outdated inline comments and aligned search / reset flows.

Result: smoother UX—users stay on their working page, and pagination gracefully adjusts after deletions.
2025-07-13 17:45:31 +08:00
t0ng7u
2d7ae1180f feat(tokens-table): show “Other” avatar for models without vendor logo
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.
2025-07-13 17:24:55 +08:00
CaIon
dd741fc38a 🔄 update: regenerate bun.lockb file to reflect dependency changes 2025-07-13 12:08:13 +08:00
t0ng7u
9d2a56bff4 🎨 refactor: TokensTable UI for clearer quota info & compact controls
• Display remaining-quota percentage instead of used-quota in the Progress indicator
  - 100 % when quota is untouched, shown in green
  - Warn at ≤ 30 % (yellow) and at ≤ 10 % (red)
  - Hide internal label (`showInfo={false}`) and move the percentage text into the Tooltip
  - Switch Progress `size` to `small` for a lighter visual footprint

• Update Tooltip to list used, remaining, total quota and the new percentage value

• Uniformly set `size="small"` on all header Buttons and Form inputs within the table
  — enhances readability and keeps the main content centered

UI/UX improvement only; no backend logic affected.
2025-07-13 01:02:55 +08:00
t0ng7u
31d82a3169 🚑 fix: safeguard NewAPIError.Error() against nil pointer panic
Backend
• `types/error.go`
  – Return empty string when receiver itself is `nil`.
  – If `Err` is `nil`, fall back to `errorCode` string to avoid calling `nil.Error()`.

This prevents runtime panics when the error handler builds an OpenAI-style error response but the underlying `Err` field has not been set.
2025-07-13 00:16:38 +08:00
t0ng7u
93b5638a9c Merge remote-tracking branch 'origin/multi_keys_channel' into alpha
# Conflicts:
#	web/src/components/table/LogsTable.js
#	web/src/i18n/locales/en.json
#	web/src/pages/Channel/EditChannel.js
2025-07-12 23:47:24 +08:00
CaIon
20607b0b5c feat(logs): add multi-key support in LogsTable and enhance log info generation 2025-07-12 15:14:55 +08:00
t0ng7u
5b83d478d6 🎨 style(footer): remove redundant bg-semi-color-bg-2 class (#1354)
The background utility class `bg-semi-color-bg-2` was unnecessary after recent
design adjustments and unintentionally overrode intended styles.
Removing it cleans up the markup and allows the footer to inherit the correct
background from its parent containers.

File affected:
- web/src/components/layout/Footer.js

Closes #1354
2025-07-12 03:53:06 +08:00
t0ng7u
dca38d01d6 🐛 fix(tokens-table): show all extra IP addresses in tooltip
Previously, the tooltip that appears when more than one IP address is configured
skipped the second IP (`ips.slice(2)`), so users could not see it unless they
expanded the list in another way.
Changed the slice start index to `1`, ensuring that **every IP after the first
display tag** is included in the tooltip (`ips.slice(1).join(', ')`).

File affected:
- web/src/components/table/TokensTable.js
2025-07-12 03:48:55 +08:00
t0ng7u
7c4b83a430 🎨 refactor(TokensTable): refactor TokensTable UI & UX for clearer data and inline actions
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.
2025-07-12 03:35:19 +08:00
CaIon
85efea3fb8 feat(channel): implement multi-key mode handling and improve channel update logic 2025-07-11 21:12:17 +08:00
t0ng7u
c820fda26d 🌐 feat(system-settings): add ServerAddress option & full i18n support
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.
2025-07-11 02:53:53 +08:00
CaIon
cd8c23c0ab feat(channel): enhance channel status management 2025-07-10 17:49:53 +08:00
CaIon
8759ef012f feat(ability): enhance FixAbility function 2025-07-08 18:33:32 +08:00
CaIon
9546a47f2b feat(tokens): add cherryConfig support for URL generation and base64 encoding 2025-07-06 20:56:09 +08:00
Calcium-Ion
5ec421d8e6 Merge pull request #1321 from iszcz/main
支持Midjourney视频任务和图片编辑
2025-07-05 15:28:33 +08:00
t0ng7u
3049ad47e5 🔢 feat(user-edit): replace add-quota input with Semi-UI InputNumber
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.
2025-07-05 00:03:12 +08:00
t0ng7u
8945a3a2dd 🖼️ style(RatioSync): remove the useless rounded-full style 2025-07-04 23:49:34 +08:00
t0ng7u
bf577b8937 🔌 feat(api): extend endpoint type support & expose in pricing UI
* 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.
2025-07-04 03:15:34 +08:00
IcedTangerine
34aca14858 Merge pull request #1309 from feitianbubu/pr/alpha/video-action-constant2
feat: video action to constant
2025-07-02 15:50:23 +08:00
iszcz
660180ea1b 支持Midjourney视频任务和图片编辑 2025-06-30 22:31:12 +08:00
t0ng7u
e6949e611a style: change the border radius of most components from full to lg size 2025-06-29 02:32:09 +08:00
skynono
59a1f4c900 feat: video action to constant 2025-06-27 23:19:34 +08:00
skynono
05ea0dd54f feat: add video channel jimeng 2025-06-27 17:08:20 +08:00