Commit Graph

76 Commits

Author SHA1 Message Date
t0ng7u
def4d16c73 🎨 refactor(ui): harden iframe messaging
- useHeaderBar.js
  - Wrap handlers with useCallback (logout, language/theme toggle, mobile menu)
  - Add null checks and try/catch around iframe postMessage (theme & language)
  - Keep minimal effect deps; remove unused StatusContext dispatch
  - Logo preload effect safe and scoped to `logo`

- index.jsx
  - No functional changes; locale memoization remains stable

Chore:
- Lint clean; no runtime warnings
- Verified no render loops or performance regressions
2025-08-23 03:17:03 +08:00
t0ng7u
61ae19ac82 🌓 feat(ui): add auto theme mode, refactor ThemeToggle, optimize header theme handling
- Feature: Introduce 'auto' theme mode
  - Detect system preference via matchMedia('(prefers-color-scheme: dark)')
  - Add useActualTheme context to expose the effective theme ('light'|'dark')
  - Persist selected mode in localStorage ('theme-mode') with 'auto' as default
  - Apply/remove `dark` class on <html> and sync `theme-mode` on <body>
  - Broadcast effective theme to iframes

- UI: Redesign ThemeToggle with Dropdown items and custom highlight
  - Replace non-existent IconMonitor with IconRefresh
  - Use Dropdown.Menu + Dropdown.Item with built-in icon prop
  - Selected state uses custom background highlight; hover state preserved
  - Remove checkmark; selection relies on background styling
  - Current button icon reflects selected mode

- Performance: reduce re-renders and unnecessary effects
  - Memoize theme options and current button icon (useMemo)
  - Simplify handleThemeToggle to accept only explicit modes ('light'|'dark'|'auto')
  - Minimize useEffect dependencies; remove unrelated deps

- Header: streamline useHeaderBar
  - Use useActualTheme for iframe theme messaging
  - Remove unused statusDispatch
  - Remove isNewYear from theme effect dependencies

- Home: send effective theme (useActualTheme) to external content iframes

- i18n: add/enhance theme-related copy in locales (en/zh)

- Chore: minor code cleanup and consistency
  - Improve readability and maintainability
  - Lint clean; no functional regressions
2025-08-23 03:02:35 +08:00
t0ng7u
6c94573323 ♻️ refactor(InvitationCard): restructure cards with title prop and clean up styling
- 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
2025-08-19 00:22:28 +08:00
t0ng7u
adc7fbd424 ♻️ refactor(web): migrate React modules from .js to .jsx and align entrypoint
- Rename React components/pages/utilities that contain JSX to `.jsx` across `web/src`
- Update import paths and re-exports to match new `.jsx` extensions
- Fix Vite entry by switching `web/index.html` from `/src/index.js` to `/src/index.jsx`
- Verified remaining `.js` files are plain JS (hooks/helpers/constants) and do not require JSX
- No runtime behavior changes; extension and reference alignment only

Context: Resolves the Vite pre-transform error caused by the stale `/src/index.js` entry after migrating to `.jsx`.
2025-08-18 04:14:35 +08:00
t0ng7u
1074f8acb1 🎛️ refactor: HeaderBar into modular components, add shared skeletons, and primary-colored nav hover
Summary
- Split HeaderBar into maintainable components and hooks
- Centralized skeleton loading UI via a reusable SkeletonWrapper
- Improved navigation UX with primary-colored hover indication
- Preserved API surface and passed linters

Why
- Improve readability, reusability, and testability of the header
- Remove duplicated skeleton logic across files
- Provide clearer hover feedback consistent with the theme

What’s changed
- Components (web/src/components/layout/HeaderBar/)
  - New container: index.js
  - New UI components: HeaderLogo.js, Navigation.js, ActionButtons.js, UserArea.js, MobileMenuButton.js, NewYearButton.js, NotificationButton.js, ThemeToggle.js, LanguageSelector.js
  - New shared skeleton: SkeletonWrapper.js
  - Updated entry: HeaderBar.js now re-exports ./HeaderBar/index.js
- Hooks (web/src/hooks/common/)
  - New: useHeaderBar.js (state and actions for header)
  - New: useNotifications.js (announcements state, unread calc, open/close)
  - New: useNavigation.js (main nav link config)
- Skeleton refactor
  - Navigation.js: replaced inline skeletons with <SkeletonWrapper type="navigation" .../>
  - UserArea.js: replaced inline skeletons with <SkeletonWrapper type="userArea" .../>
  - HeaderLogo.js: replaced image/title skeletons with <SkeletonWrapper type="image"/>, <SkeletonWrapper type="title"/>
- Navigation hover UX
  - Added primary-colored hover to nav items for clearer pointer feedback
  - Final hover style: hover:text-semi-color-primary (kept rounded + transition classes)

Non-functional
- No breaking API changes; HeaderBar usage stays the same
- All modified files pass lint checks

Notes for future work
- SkeletonWrapper is extensible: add new cases (e.g., card) in one place
- Components are small and test-friendly; unit tests can be added per component

Affected files (key)
- web/src/components/layout/HeaderBar.js
- web/src/components/layout/HeaderBar/index.js
- web/src/components/layout/HeaderBar/Navigation.js
- web/src/components/layout/HeaderBar/UserArea.js
- web/src/components/layout/HeaderBar/HeaderLogo.js
- web/src/components/layout/HeaderBar/ActionButtons.js
- web/src/components/layout/HeaderBar/MobileMenuButton.js
- web/src/components/layout/HeaderBar/NewYearButton.js
- web/src/components/layout/HeaderBar/NotificationButton.js
- web/src/components/layout/HeaderBar/ThemeToggle.js
- web/src/components/layout/HeaderBar/LanguageSelector.js
- web/src/components/layout/HeaderBar/SkeletonWrapper.js
- web/src/hooks/common/useHeaderBar.js
- web/src/hooks/common/useNotifications.js
- web/src/hooks/common/useNavigation.js
2025-08-18 03:20:56 +08:00
t0ng7u
a6ad49dba0 Revert "️ perf: Defer Visactor chart libs to dashboard; minimize home bundle"
This reverts commit b67a42e0a8.
2025-08-17 10:49:09 +08:00
t0ng7u
b67a42e0a8 ️ perf: Defer Visactor chart libs to dashboard; minimize home bundle
Home started loading `/assets/visactor-*.js` due to static imports of `@visactor/react-vchart` and the Semi theme in dashboard components/hooks. This change moves chart dependencies to lazy/dynamic imports so they load only on dashboard routes.

Changes
- StatsCards.jsx: replace static `VChart` import with `React.lazy` + `Suspense` (fallback: null)
- ChartsPanel.jsx: replace static `VChart` import with `React.lazy` + `Suspense` (fallback: null)
- useDashboardCharts.js: remove static `initVChartSemiTheme` import; dynamically import and initialize the theme inside `useEffect` with a cancel guard

Behavior
- Home page no longer downloads `visactor` chunks on first load
- Chart libraries are fetched only when visiting `/console` (dashboard)
- No functional changes to chart rendering

Files
- web/src/components/dashboard/StatsCards.jsx
- web/src/components/dashboard/ChartsPanel.jsx
- web/src/hooks/dashboard/useDashboardCharts.js

Verification
- Build the app (`npm run build`) and open `/`: no `/assets/visactor-*.js` requests
- Navigate to `/console`: `visactor` chunks load and charts render as expected

Breaking Changes
- None

Follow-ups
- If needed, further trim homepage bundle by reducing heavy icon sets on the hero section
2025-08-17 01:22:44 +08:00
t0ng7u
196e2a0abb 🐛 fix: Always update searchValue during IME composition to enable Chinese input in model search
Summary:
• Removed early return in `handleChange` that blocked controlled value updates while an Input Method Editor (IME) was composing text.
• Ensures that Chinese (and other IME-based) characters appear immediately in the “Fuzzy Search Model Name” field.
• No change to downstream filtering logic—`searchValue` continues to drive model list filtering as before.

Files affected:
web/src/hooks/model-pricing/useModelPricingData.js
2025-08-12 23:37:30 +08:00
t0ng7u
63b9457b6c 🔍 fix(pricing): synchronize search term with sidebar filters & reset behavior
* Add `searchValue` to every dependency array in `usePricingFilterCounts`
  to ensure group/vendor/tag counts and disabled states update dynamically
  while performing fuzzy search.

* Refactor `PricingTopSection` search box into a controlled component:
  - Accept `searchValue` prop and bind it to `Input.value`
  - Extend memo dependencies to include `searchValue`
  This keeps the UI in sync with state changes triggered by `handleChange`.

* Guarantee that `resetPricingFilters` clears the search field by
  leveraging the new controlled input.

As a result, sidebar counters/disabled states now react to search input,
and the “Reset” button fully restores default filters without leaving the
search term visible.
2025-08-12 23:32:25 +08:00
t0ng7u
d1d945eaa0 🔠 refactor: refine group label formatting in price info
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.
2025-08-10 17:17:49 +08:00
t0ng7u
870132a5cb feat: Add tag-based filtering & refactor filter counts logic
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.
2025-08-10 14:05:25 +08:00
t0ng7u
cdf27d60be fix: prevent model name flicker when closing SideSheet
- Delay clearing selectedModel until SideSheet close animation completes
- Prevents brief display of 'AI/Unknown Model' text during closing transition
- Improves user experience by eliminating visual flicker
- Uses 300ms timeout matching Semi UI default animation duration
2025-08-10 13:41:19 +08:00
CaIon
4cec55c9a4 feat: enhance TokensPage and useTokensData to support Fluent integration and notifications 2025-08-09 17:02:06 +08:00
Calcium-Ion
ec28671aed Merge pull request #1429 from feitianbubu/pr/video-preview-modal
feat: add video preview modal
2025-08-09 11:37:19 +08:00
t0ng7u
1690b05629 🚀 feat(pricing): clarify “auto” group routing chain and exclude it from price table
Detailed changes
Backend
• `controller/pricing.go` now includes `auto_groups` in `/api/pricing` response, sourced from `setting.AutoGroups`.

Frontend
• `useModelPricingData.js`
  – Parses `auto_groups` and exposes `autoGroups` state.
• `PricingPage.jsx` → `ModelDetailSideSheet.jsx` → `ModelPricingTable.jsx`
  – Thread `autoGroups` through component tree.
• `ModelPricingTable.jsx`
  – Removes deprecated `getGroupDescription` / `Tooltip`.
  – Filters out `auto` when building price table rows.
  – Renders a descriptive banner: “auto 分组调用链路 → auto → group1 → …”, clarifying fallback order without showing prices.
• Minor i18n tweak: adds `auto分组调用链路` key for the banner text.

Why
Users were confused by the “auto” tag appearing alongside regular groups with no price.
This change:
1. Makes the routing chain explicit.
2. Keeps the pricing table focused on billable groups.

No breaking API changes; existing clients can ignore the new `auto_groups` field.
2025-08-08 14:49:55 +08:00
t0ng7u
8fba0017c7 feat(pricing+endpoints+ui): wire custom endpoint mapping end‑to‑end and overhaul visual JSON editor
Backend (Go)
- Include custom endpoints in each model’s SupportedEndpointTypes by parsing Model.Endpoints (JSON) and appending keys alongside native endpoint types.
- Build a global supportedEndpointMap map[string]EndpointInfo{path, method} by:
  - Seeding with native defaults.
  - Overriding/adding from models.endpoints (accepts string path → default POST, or {path, method}).
- Expose supported_endpoint at the top level of /api/pricing (vendors-like), removing per-model duplication.
- Fix default path for EndpointTypeOpenAIResponse to /v1/responses.
- Keep concurrency/caching for pricing retrieval intact.

Frontend (React)
- Fetch supported_endpoint in useModelPricingData and propagate to PricingPage → ModelDetailSideSheet → ModelEndpoints.
- ModelEndpoints
  - Resolve path+method via endpointMap; replace {model} with actual model name.
  - Fix mobile visibility; always show path and HTTP method.
- JSONEditor
  - Wrap with Form.Slot to inherit form layout; simplify visual styles.
  - Use Tabs for “Visual” / “Manual” modes.
  - Unify editors: key-value editor now supports nested JSON:
    - “+” to convert a primitive into an object and add nested fields.
    - Add “Convert to value” for two‑way toggle back from object.
    - Stable key rename without reordering rows; new rows append at bottom.
    - Use Row/Col grid for clean alignment; region editor uses Form.Slot + grid.
- Editing flows
  - EditModelModal / EditPrefillGroupModal use JSONEditor (editorType='object') for endpoint mappings.
  - PrefillGroupManagement renders endpoint group items by JSON keys.

Data expectations / compatibility
- models.endpoints should be a JSON object mapping endpoint type → string path or {path, method}. Strings default to POST.
- No schema changes; existing TEXT field continues to store JSON.

QA
- /api/pricing now returns custom endpoint types and global supported_endpoint.
- UI shows both native and custom endpoints; paths/methods render on mobile; nested editing works and preserves order.
2025-08-08 02:34:15 +08:00
t0ng7u
7cfeb6e87c Merge remote-tracking branch 'origin/alpha' into refactor/model-pricing 2025-08-07 11:09:28 +08:00
t0ng7u
0a231a8acc 🎨 feat(models): add row styling for disabled models in ModelsTable
Add visual distinction for enabled/disabled models by applying different
background colors to table rows based on model status. This implementation
follows the same pattern used in ChannelsTable for consistent user experience.

Changes:
- Modified handleRow function in useModelsData.js to include row styling
- Disabled models (status !== 1) now display with gray background using
  --semi-color-disabled-border CSS variable
- Enabled models (status === 1) maintain normal background color
- Preserved existing row click selection functionality

This enhancement improves the visual feedback for users to quickly identify
which models are active vs inactive in the models management interface.
2025-08-07 10:54:05 +08:00
t0ng7u
94506bee99 feat(models): Revamp EditModelModal UI and UX
This commit significantly refactors the `EditModelModal` component to streamline the user interface and enhance usability, aligning it with the interaction patterns found elsewhere in the application.

- **Consolidated Layout:** Merged the "Vendor Information" and "Feature Configuration" sections into a single "Basic Information" card. This simplifies the form, reduces clutter, and makes all settings accessible in one view.

- **Improved Prefill Groups:** Replaced the separate `Select` dropdowns for tag and endpoint groups with a more intuitive button-based system within the `extraText` of the `TagInput` components.

- **Additive Button Logic:** The prefill group buttons now operate in an additive mode. Users can click multiple group buttons to incrementally add tags or endpoints, with duplicates being automatically handled.

- **Clear Functionality:** Added "Clear" buttons for both tags and endpoints, allowing users to easily reset the fields.

- **Code Cleanup:** Removed the unused `endpointOptions` constant and unnecessary icon imports (`Building`, `Settings`) to keep the codebase clean.
2025-08-06 03:29:45 +08:00
t0ng7u
7c814a5fd9 🚀 refactor: migrate vendor-count aggregation to model layer & align frontend logic
Summary
• Backend
  – Moved duplicate-name validation and total vendor-count aggregation from controllers (`controller/model_meta.go`, `controller/vendor_meta.go`, `controller/prefill_group.go`) to model layer (`model/model_meta.go`, `model/vendor_meta.go`, `model/prefill_group.go`).
  – Added `GetVendorModelCounts()` and `Is*NameDuplicated()` helpers; controllers now call these instead of duplicating queries.
  – API response for `/api/models` now returns `vendor_counts` with per-vendor totals across all pages, plus `all` summary.
  – Removed redundant checks and unused imports, eliminating `go vet` warnings.

• Frontend
  – `useModelsData.js` updated to consume backend-supplied `vendor_counts`, calculate the `all` total once, and drop legacy client-side counting logic.
  – Simplified initial data flow: first render now triggers only one models request.
  – Deleted obsolete `updateVendorCounts` helper and related comments.
  – Ensured search flow also sets `vendorCounts`, keeping tab badges accurate.

Why
This refactor enforces single-responsibility (aggregation in model layer), delivers consistent totals irrespective of pagination, and removes redundant client queries, leading to cleaner code and better performance.
2025-08-06 01:40:08 +08:00
creamlike1024
edbe18b157 fix: responses cache token 未计费 2025-08-05 22:56:27 +08:00
t0ng7u
f3a1f98add 🐛 fix(models): eliminate vendor column flicker by loading vendors before models
Why:
• The vendor list API is separate from the models API, causing the “Vendor” column in `ModelsTable` to flash (rendering `'-'` first, then updating) after the table finishes loading.
• This visual jump degrades the user experience.

What:
• Updated `web/src/hooks/models/useModelsData.js`
  – In the initial `useEffect`, vendors are fetched first with `loadVendors()` and awaited.
  – Only after vendors are ready do we call `loadModels()`, ensuring `vendorMap` is populated before the table renders.

Outcome:
• The table now renders with complete vendor data on first paint, removing the flicker and providing a smoother UI.
2025-08-04 22:11:13 +08:00
t0ng7u
512850e83d Merge remote-tracking branch 'origin/alpha' into refactor/model-pricing 2025-08-04 21:37:38 +08:00
t0ng7u
0e9c3cde7c 🏗️ refactor: Replace model categories with vendor-based filtering and optimize data structure
- **Backend Changes:**
  - Refactor pricing API to return separate vendors array with ID-based model references
  - Remove redundant vendor_name/vendor_icon fields from pricing records, use vendor_id only
  - Add vendor_description to pricing response for frontend display
  - Maintain 1-minute cache protection for pricing endpoint security

- **Frontend Data Flow:**
  - Update useModelPricingData hook to build vendorsMap from API response
  - Enhance model records with vendor info during data processing
  - Pass vendorsMap through component hierarchy for consistent vendor data access

- **UI Component Replacements:**
  - Replace PricingCategories with PricingVendors component for vendor-based filtering
  - Replace PricingCategoryIntro with PricingVendorIntro in header section
  - Remove all model category related components and logic

- **Header Improvements:**
  - Implement vendor intro with real backend data (name, icon, description)
  - Add text collapsible feature (2-line limit with expand/collapse functionality)
  - Support carousel animation for "All Vendors" view with vendor icon rotation

- **Model Detail Modal Enhancements:**
  - Update ModelHeader to use real vendor icons via getLobeHubIcon()
  - Move tags from header to ModelBasicInfo content area to avoid SideSheet title width constraints
  - Display only custom tags from backend with stringToColor() for consistent styling
  - Use Space component with wrap property for proper tag layout

- **Table View Optimizations:**
  - Integrate RenderUtils for description and tags columns
  - Implement renderLimitedItems for tags (max 3 visible, +x popover for overflow)
  - Use renderDescription for text truncation with tooltip support

- **Filter Logic Updates:**
  - Vendor filter shows disabled options instead of hiding when no models match
  - Include "Unknown Vendor" category for models without vendor information
  - Remove all hardcoded vendor descriptions, use real backend data

- **Code Quality:**
  - Fix import paths after component relocation
  - Remove unused model category utilities and hardcoded mappings
  - Ensure consistent vendor data usage across all pricing views
  - Maintain backward compatibility with existing pricing calculation logic

This refactor provides a more scalable vendor-based architecture while eliminating
data redundancy and improving user experience with real-time backend data integration.
2025-08-04 21:36:31 +08:00
CaIon
ecdd9d1ccb feat: add multi-key management 2025-08-04 16:52:31 +08:00
t0ng7u
5e81ef4a44 ♻️ refactor(hooks/models): deduplicate useModelsData and optimize vendor-tab counts
Highlights
──────────
1. Removed code duplication
   • Introduced `extractItems` helper to safely unwrap API payloads.
   • Simplified `getFormValues` to a single-line fallback expression.
   • Replaced repeated list-extraction code in `loadModels`, `searchModels`,
     and `refreshVendorCounts` with the new helper.

2. Vendor tab accuracy & performance
   • Added `refreshVendorCounts` to recalc counts via a single lightweight
     request; invoked only when必要 (current tab ≠ "all“) to avoid redundancy.
   • `loadModels` still updates counts instantly when viewing "all", ensuring
     accurate numbers on initial load and page changes.

3. Misc clean-ups
   • Streamlined conditional URL building and state updates.
   • Confirmed all async branches include error handling with i18n messages.
   • Ran linter → zero issues.

Result: leaner, easier-to-maintain hook with correct, real-time vendor counts
and no repeated logic.
2025-08-01 02:39:12 +08:00
t0ng7u
232612898b 🔄 fix: improve vendor-tab filtering & counts, resolve SQL ambiguity, and reload data correctly
Backend
• model/model_meta.go
  – Import strconv
  – SearchModels: support numeric vendor ID filter vs. fuzzy name search
  – Explicitly order by `models.id` to avoid “ambiguous column name: id” error

Frontend
• hooks/useModelsData.js
  – Change vendor-filter API to pass vendor ID
  – Automatically reload models when `activeVendorKey` changes
  – Update vendor counts only when viewing “All” to preserve other tab totals
• Add missing effect in EditModelModal to refresh vendor list only when modal visible
• Other minor updates to keep lints clean

Result
Tabs now:
1. Trigger API requests on click
2. Show accurate per-vendor totals
3. Filter models without resetting other counts
Backend search handles both vendor IDs and names without SQL errors.
2025-07-31 23:30:45 +08:00
t0ng7u
af59b61f8a 🚀 feat: Introduce full Model & Vendor Management suite (backend + frontend) and UI refinements
Backend
• Add `model/model_meta.go` and `model/vendor_meta.go` defining Model & Vendor entities with CRUD helpers, soft-delete and time stamps
• Create corresponding controllers `controller/model_meta.go`, `controller/vendor_meta.go` and register routes in `router/api-router.go`
• Auto-migrate new tables in DB startup logic

Frontend
• Build complete “Model Management” module under `/console/models`
  - New pages, tables, filters, actions, hooks (`useModelsData`) and dynamic vendor tabs
  - Modals `EditModelModal.jsx` & unified `EditVendorModal.jsx`; latter now uses default confirm/cancel footer and mobile-friendly modal sizing (`full-width` / `small`) via `useIsMobile`
• Update sidebar (`SiderBar.js`) and routing (`App.js`) to surface the feature
• Add helper updates (`render.js`) incl. `stringToColor`, dynamic LobeHub icon retrieval, and tag color palettes

Table UX improvements
• Replace separate status column with inline Enable / Disable buttons in operation column (matching channel table style)
• Limit visible tags to max 3; overflow represented as “+x” tag with padded `Popover` showing remaining tags
• Color all tags deterministically using `stringToColor` for consistent theming
• Change vendor column tag color to white for better contrast

Misc
• Minor layout tweaks, compact-mode toggle relocation, lint fixes and TypeScript/ESLint clean-up

These changes collectively deliver end-to-end model & vendor administration while unifying visual language across management tables.
2025-07-31 22:28:09 +08:00
t0ng7u
4cc76f2deb Merge branch 'alpha' into refactor/model-pricing 2025-07-27 09:51:35 +08:00
t0ng7u
0cb2bb2ea7 🗂️ refactor(table): isolate column preferences per role
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.
2025-07-27 09:49:57 +08:00
t0ng7u
75548c449b refactor: pricing filters for dynamic counting & cleaner logic
This commit introduces a unified, maintainable solution for all model-pricing filter buttons and removes redundant code.

Key points
• Added `usePricingFilterCounts` hook
  - Centralises filtering logic and returns:
    - `quotaTypeModels`, `endpointTypeModels`, `dynamicCategoryCounts`, `groupCountModels`
  - Keeps internal helpers private (removed public `modelsAfterCategory`).

• Updated components to consume the new hook
  - `PricingSidebar.jsx`
  - `FilterModalContent.jsx`

• Improved button UI/UX
  - `SelectableButtonGroup.jsx` now respects `item.disabled` and auto-disables when `tagCount === 0`.
  - `PricingGroups.jsx` counts models per group (after all other filters) and disables groups with zero matches.
  - `PricingEndpointTypes.jsx` enumerates all endpoint types, computes filtered counts, and disables entries with zero matches.

• Removed obsolete / duplicate calculations and comments to keep components lean.

The result is consistent, real-time tag counts across all filter groups, automatic disabling of unavailable options, and a single source of truth for filter computations, making future extensions straightforward.
2025-07-26 18:38:18 +08:00
t0ng7u
0b1a1ca064 refactor: Restructure model pricing components and improve UX consistency
- **Fix SideSheet double-click issue**: Remove early return for null modelData to prevent rendering blockage during async state updates
- **Component modularization**:
  - Split ModelDetailSideSheet into focused sub-components (ModelHeader, ModelBasicInfo, ModelEndpoints, ModelPricingTable)
  - Refactor PricingFilterModal with FilterModalContent and FilterModalFooter components
  - Remove unnecessary FilterSection wrapper for cleaner interface
- **Improve visual consistency**:
  - Unify avatar/icon logic between ModelHeader and PricingCardView components
  - Standardize tag colors across all pricing components (violet/teal for billing types)
  - Apply consistent dashed border styling using Semi UI theme colors
- **Enhance data accuracy**:
  - Display raw endpoint type names (e.g., "openai", "anthropic") instead of translated descriptions
  - Remove text alignment classes for better responsive layout
  - Add proper null checks to prevent runtime errors
- **Code quality improvements**:
  - Reduce component complexity by 52-74% through modularization
  - Improve maintainability with single responsibility principle
  - Add comprehensive error handling for edge cases

This refactoring improves component reusability, reduces bundle size, and provides a more consistent user experience across the model pricing interface.
2025-07-26 04:24:22 +08:00
t0ng7u
52a9cee0e1 Merge branch 'alpha' into refactor/model-pricing 2025-07-25 20:33:14 +08:00
t0ng7u
fe16d05fbb 🔒 fix: Enforce admin-only column visibility in logs tables
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.
2025-07-25 20:31:20 +08:00
feitianbubu
9b73696a98 feat: add video preview modal 2025-07-24 19:34:21 +08:00
t0ng7u
1880164e29 ♻️ Refactor: Move token unit toggle from table header to filter settings
- 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)
2025-07-24 17:10:08 +08:00
t0ng7u
59a76b3970 feat: Add endpoint type filter to model pricing system
- Create PricingEndpointTypes.jsx component for endpoint type filtering
- Add filterEndpointType state management in useModelPricingData hook
- Integrate endpoint type filtering logic in filteredModels computation
- Update PricingSidebar.jsx to include endpoint type filter component
- Update PricingFilterModal.jsx to support endpoint type filtering on mobile
- Extend resetPricingFilters utility function to include endpoint type reset
- Support filtering models by endpoint types (OpenAI, Anthropic, Gemini, etc.)
- Display model count for each endpoint type with localized labels
- Ensure filter state resets to first page when endpoint type changes

This enhancement allows users to filter models by their supported endpoint types,
providing more granular control over model selection in the pricing interface.
2025-07-24 03:25:57 +08:00
t0ng7u
53be79a00e 💄 style(pricing): enhance card view UI and skeleton loading experience (#1365)
- Increase skeleton card count from 6 to 10 for better visual coverage
- Extend minimum skeleton display duration from 500ms to 1000ms for smoother UX
- Add circle shape to all pricing tags for consistent rounded design
- Apply circle styling to billing type, popularity, endpoint, and context tags

This commit improves the visual consistency and user experience of the pricing
card view by standardizing tag appearance and optimizing skeleton loading timing.
2025-07-24 03:19:32 +08:00
t0ng7u
a044070e1d 🎨 feat(model-pricing): refactor layout and component structure (#1365)
* Re-architected model-pricing page into modular components:
  * PricingPage / PricingSidebar / PricingContent
  * Removed obsolete `ModelPricing*` components and column defs
* Introduced reusable `SelectableButtonGroup` in `common/ui`
  * Supports Row/Col grid (3 per row)
  * Optional collapsible mode with gradient mask & toggle
* Rebuilt filter panels with the new button-group:
  * Model categories, token groups, and quota types
  * Added dynamic `tagCount` badges to display item totals
* Extended `useModelPricingData` hook
  * Added `filterGroup` and `filterQuotaType` state and logic
* Updated PricingTable columns & sidebar reset logic to respect new states
* Ensured backward compatibility via re-export in `index.jsx`
* Polished styling, icons and i18n keys
2025-07-23 01:58:51 +08:00
t0ng7u
0c5c5823bf ♻️ refactor: restructure ModelPricing component into modular architecture
- 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
2025-07-22 12:08:35 +08:00
t0ng7u
0eaeef5723 📚 refactor(dashboard): modularize dashboard page into reusable hooks and components
## 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.
2025-07-20 15:47:02 +08:00
t0ng7u
4d7562fd79 🐛 fix(ui): prevent pagination flicker when tables have no data
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
2025-07-20 12:36:38 +08:00
t0ng7u
252fddf3de 🚀 feat: Enhance table UX & fix reset actions across Users / Tokens / Redemptions
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.
2025-07-20 01:21:06 +08:00
t0ng7u
39079e7aff 💄 refactor: Users table UI & state handling
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.
2025-07-20 01:00:53 +08:00
t0ng7u
38e72e1af7 🎨 chore: integrate ESLint header automation with AGPL-3.0 notice
• Added `.eslintrc.cjs`
  - Enables `header` + `react-hooks` plugins
  - Inserts standardized AGPL-3.0 license banner for © 2025 QuantumNous
  - JS/JSX parsing & JSX support configured

• Installed dev-deps: `eslint`, `eslint-plugin-header`, `eslint-plugin-react-hooks`

• Updated `web/package.json` scripts
  - `eslint` → lint with cache
  - `eslint:fix` → auto-insert/repair license headers

• Executed `eslint --fix` to prepend license banner to all JS/JSX files

• Ignored runtime cache
  - Added `.eslintcache` to `.gitignore` & `.dockerignore`

Result: consistent AGPL-3.0 license headers, reproducible linting across local dev & CI.
2025-07-19 03:30:44 +08:00
t0ng7u
d762da9141 ♻️ refactor(users): modularize UsersTable component into microcomponent architecture
BREAKING CHANGE: Removed standalone user edit routes (/console/user/edit, /console/user/edit/:id)

- Decompose 673-line monolithic UsersTable.js into 8 specialized components
- Extract column definitions to UsersColumnDefs.js with render functions
- Create dedicated UsersActions.jsx for action buttons
- Create UsersFilters.jsx for search and filtering logic
- Create UsersDescription.jsx for description area
- Extract all data management logic to useUsersData.js hook
- Move AddUser.js and EditUser.js to users/modals/ folder as modal components
- Create 4 new confirmation modal components (Promote, Demote, EnableDisable, Delete)
- Implement pure UsersTable.jsx component for table rendering only
- Create main container component users/index.jsx to compose all subcomponents
- Update import paths in pages/User/index.js to use new modular structure
- Remove obsolete EditUser imports and routes from App.js
- Delete original monolithic files: UsersTable.js, AddUser.js, EditUser.js

The new architecture follows the same modular pattern as tokens and redemptions modules:
- Consistent file organization across all table modules
- Better separation of concerns and maintainability
- Enhanced reusability and testability
- Unified modal management approach

All existing functionality preserved with improved code organization.
2025-07-19 00:32:56 +08:00
t0ng7u
c05d6f7cdf ♻️ refactor(components): restructure RedemptionsTable to modular architecture
Refactor the monolithic RedemptionsTable component (614 lines) into a clean,
modular structure following the established tokens component pattern.

### Changes Made:

**New Components:**
- `RedemptionsColumnDefs.js` - Extract table column definitions and render logic
- `RedemptionsActions.jsx` - Extract action buttons (add, batch copy, clear invalid)
- `RedemptionsFilters.jsx` - Extract search and filter form components
- `RedemptionsDescription.jsx` - Extract description area component
- `redemptions/index.jsx` - Main container component managing state and composition

**New Hook:**
- `useRedemptionsData.js` - Extract all data management, CRUD operations, and business logic

**New Constants:**
- `redemption.constants.js` - Extract redemption status, actions, and form constants

**Architecture Changes:**
- Transform RedemptionsTable.jsx into pure table rendering component
- Move state management and component composition to index.jsx
- Implement consistent prop drilling pattern matching tokens module
- Add memoization for performance optimization
- Centralize translation function distribution

### Benefits:
- **Maintainability**: Each component has single responsibility
- **Reusability**: Components and hooks can be used elsewhere
- **Testability**: Individual modules can be unit tested
- **Team Collaboration**: Multiple developers can work on different modules
- **Consistency**: Follows established architectural patterns

### File Structure:
```
redemptions/
├── index.jsx                    # Main container (state + composition)
├── RedemptionsTable.jsx        # Pure table component
├── RedemptionsActions.jsx      # Action buttons
├── RedemptionsFilters.jsx      # Search/filter form
├── RedemptionsDescription.jsx  # Description area
└── RedemptionsColumnDefs.js    # Column definitions
2025-07-19 00:12:04 +08:00
t0ng7u
42a26f076a ♻️ refactor: modularize TokensTable component into maintainable architecture
- Split monolithic 922-line TokensTable.js into modular components:
  * useTokensData.js: Custom hook for centralized state and logic management
  * TokensColumnDefs.js: Column definitions and rendering functions
  * TokensTable.jsx: Pure table component for rendering
  * TokensActions.jsx: Actions area (add, copy, delete tokens)
  * TokensFilters.jsx: Search form component with keyword and token filters
  * TokensDescription.jsx: Description area with compact mode toggle
  * index.jsx: Main orchestrator component

- Features preserved:
  * Token status management with switch controls
  * Quota progress bars and visual indicators
  * Model limitations display with vendor avatars
  * IP restrictions handling and display
  * Chat integrations with dropdown menu
  * Batch operations (copy, delete) with confirmations
  * Key visibility toggle and copy functionality
  * Compact mode for responsive layouts
  * Search and filtering capabilities
  * Pagination and loading states

- Improvements:
  * Better separation of concerns
  * Enhanced reusability and testability
  * Simplified maintenance and debugging
  * Consistent modular architecture pattern
  * Performance optimizations with useMemo
  * Backward compatibility maintained

This refactoring follows the same successful pattern used for LogsTable, MjLogsTable, and TaskLogsTable, significantly improving code maintainability while preserving all existing functionality.
2025-07-18 22:56:34 +08:00
t0ng7u
3b67759730 ♻️ refactor: restructure TaskLogsTable into modular component architecture
Refactor the monolithic TaskLogsTable component (802 lines) into a modular,
maintainable architecture following the established pattern from LogsTable
and MjLogsTable refactors.

## What Changed

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

### 📁 New Structure
```
web/src/components/table/task-logs/
├── index.jsx                       # Main page component orchestrator
├── TaskLogsTable.jsx              # Pure table rendering component
├── TaskLogsActions.jsx            # Actions area (task records + compact mode)
├── TaskLogsFilters.jsx            # Search form component
├── TaskLogsColumnDefs.js          # Column definitions and renderers
└── modals/
    ├── ColumnSelectorModal.jsx    # Column visibility settings
    └── ContentModal.jsx           # Content viewer for JSON data

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

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

### 🎨 Task-Specific Features Preserved
- All task type rendering with icons (MUSIC, LYRICS, video generation)
- Platform-specific rendering (Suno, Kling, Jimeng) with distinct colors
- Progress indicators for task completion status
- Video preview links for successful video generation tasks
- Admin-only columns for channel information
- Status rendering with appropriate colors and icons

### 🔧 Technical Details
- Centralized all business logic in `useTaskLogsData` custom hook
- Extracted comprehensive column definitions with Lucide React icons
- Split complex UI into focused components (table, actions, filters, modals)
- Maintained responsive design patterns for mobile compatibility
- Preserved admin permission handling for restricted features
- Optimized spacing and layout (reduced gap from 4 to 2 for better density)

### 🎮 Platform Support
- **Suno**: Music and lyrics generation with music icons
- **Kling**: Video generation with video icons
- **Jimeng**: Video generation with distinct purple styling

### 🐛 Fixes
- Improved component prop passing patterns
- Enhanced type safety through better state management
- Optimized rendering performance with proper memoization
- Streamlined export pattern using `export { default }`

## Breaking Changes
None - all existing imports and functionality preserved.
2025-07-18 22:33:05 +08:00
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