Commit Graph

1019 Commits

Author SHA1 Message Date
mini
73b3980711 feat(portal): i18n-ify DocsView + auth narrative panels
Extract all Chinese from DocsView.vue into docs.* namespace and add
auth.narrative.* sub-namespace for LoginView/RegisterView narrative slots.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 01:42:32 +08:00
mini
fc7e27671d feat(landing): extract i18n keys + add English translations
Replaces all rendered Chinese strings in LandingView with $t() calls and
<i18n-t> interpolation components; adds landing namespace (62 leaf keys) to
both zh.ts and en.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 01:30:23 +08:00
mini
6328881801 feat(portal): mount PuroLocaleSwitcher in Landing/Docs/AuthLayout 2026-04-20 21:36:41 +08:00
mini
e711a20373 feat(i18n): add PuroLocaleSwitcher for portal pages 2026-04-20 21:24:51 +08:00
mini
49ee2cba8a fix(docs): DocsView fidelity port (plan A)
Some checks failed
continuous-integration/drone/push Build is passing
CI / test (push) Has been cancelled
CI / golangci-lint (push) Has been cancelled
Security Scan / backend-security (push) Has been cancelled
Security Scan / frontend-security (push) Has been cancelled
Visual alignment with zip Docs.html (excluding 3-col layout):
- SVG hexagon logo (replaces ⬢ emoji)
- h2 cyan accent bar (::before 3px left strip)
- Models section: replace <ul> with structured table
  (provider badges with brand-color dots, OK/BETA status chips)
- Wrap all code blocks in .code-panel with:
  - traffic-light header + filename tab
  - 复制 button with clipboard API + 已复制 feedback

Kept intentionally different per Stage 1 decisions:
- Section 1 uses 'contact admin@puro.im' (not OAuth self-serve)
- Nav omits pricing / design-system links
- Codex CLI section preserved (Vue-only)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:19:46 +08:00
mini
4cf6840479 fix(landing): LandingView fidelity port from design zip
A-group deltas restored (excluding Stage 1 decisions — no Pricing/FAQ/
CTA banner, kept existing Hero CTA copy):

- Nav + footer brand: SVG hexagon replaces ⬢ emoji
- Hero: add NEW badge in eyebrow; inline pills around OpenAI/Anthropic
- Section kickers: monospace // providers / // capabilities / etc
- Features: restored title "付一次订阅,用起一整个模型池" + subtitle
  + 9 bullet items (3 per card, dashed-border lists)
- Model wall: SVG letter-logos + green status chips (was plain dots)
- Code demo: traffic-light + tab header in each code-block
- Dashboard mockup: added sidebar nav + donut chart (chart-grid 2fr:1fr)
- Footer: Chinese product tagline; all-systems-operational indicator

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:58:07 +08:00
mini
9f78b70a87 fix(auth): RegisterView fidelity port from design zip
Port A-group deltas from design zip (excluding bonus/pricing which
are explicitly out of scope):
- Narrative: N (not 5) 个订阅; add '// 5 分钟开始用' n-kicker;
  SVG hexagon logo (was emoji); n-bottom live status bar
- Add 3-step onboarding panel (创建账户 → 绑定订阅 → 生成 key)
  in narrative, active-step highlighted
- Add password strength meter (4 bars + text label 弱/中/强/极强)
- Add confirm-password field with live // matched/mismatch hint
- Add Terms & Privacy consent checkbox (submit gated)
- New i18n keys: confirmPasswordLabel/Placeholder, passwordsDoNotMatch

All existing Vue logic preserved (OAuth/Turnstile/verify code/
invitation+promo codes).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:53:40 +08:00
mini
046765632d fix(auth): LoginView fidelity port from design zip
- Narrative: N (not 5) 个订阅, matching design intent
- Add '// 你的订阅,已经付过钱了' n-kicker above headline
- Port route-demo panel (POST /v1/chat/completions → pool → 200 OK)
- Port n-bottom live status bar (green dot + ai.puro.im operational)
- Replace ⬢ emoji with inline SVG hexagon (crisp at all sizes)

All Vue auth logic preserved: OAuth sections, Turnstile, 2FA modal,
forgot-password, form validation, v-model bindings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:45:54 +08:00
mini
6291dc40d0 fix(auth): restore dark split-layout visuals on /login /register
Three regressions from Task 7-9 caused /login /register to render broken:
- bg-glow not rendering: puro.css scopes .bg-glow to .puro-page,
  AuthLayout isn't inside one. Fix: duplicate bg-glow rules into
  AuthLayout scoped CSS keyed on .auth-shell-split.
- .auth-main had no background: right side showed naked body bg.
  Fix: .auth-shell-split now sets var(--bg-0) for whole shell.
- Heading/label colors used text-gray-900 light-mode classes,
  invisible on dark bg. Fix: switch to explicit text-slate-50/400,
  and :deep() override for form inputs via AuthLayout split scope.

Legacy (non-split) mode unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:22:25 +08:00
mini
0fceb100e0 chore(i18n): consolidate PURO auth heading keys into zh.ts
Login and Register heading strings moved from hardcoded Chinese to
auth.puroLoginTitle / puroLoginSub / puroRegisterTitle / puroRegisterSub.

Landing (LandingView) and Docs (DocsView) intentionally keep hardcoded
Chinese this cycle (see spec §6 note 5 — English version deferred).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:54:49 +08:00
mini
7dc8062988 feat(docs): public DocsView with Codex/Claude Code/curl quickstart
Route /docs (no auth). Six sections: get key, codex CLI, claude code,
curl, supported models, feedback. Uses puro.css design system.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:42:08 +08:00
mini
f17a88c171 feat(auth): RegisterView with PURO narrative split layout
Same split layout as LoginView: left narrative, right form.
Heading: '创建账户' + '5 分钟开始用 PURO AI'.
All form logic preserved (OAuth, Turnstile, email verify code, password fields).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:29:08 +08:00
mini
91b9ae7e21 feat(auth): LoginView with PURO narrative split layout
- Left: ⬢ PURO AI brand + '5→1' headline + three-line value props
- Right: existing form (OAuth, Turnstile, 2FA all preserved unchanged)
- Heading changed from t('auth.welcomeBack') to '登录' — i18n key consolidation in Task 11

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:27:23 +08:00
mini
9ee99d17fd refactor(auth): AuthLayout supports optional narrative slot
New slot 'narrative' enables split-screen layout (50/50 desktop, collapses
to single column on mobile <900px).

Backward compatibility:
- Pages that don't pass a narrative slot still render the original
  centered-card layout with siteName + logo + copyright
- ForgotPassword, ResetPassword, EmailVerify unaffected

To be used in Tasks 8 and 9 (LoginView, RegisterView).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:25:01 +08:00
mini
284b5129ac feat(router): mount Landing at / with auth-aware redirect
- / (anonymous) → LandingView
- / (authenticated) → redirects to /dashboard via new meta.redirectIfAuth
- Remove temporary /landing-preview route (Task 2 helper)
- RouteMeta TS augmentation for redirectIfAuth
- LandingView brand link uses router-link (was <a href>, causing SPA reload)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:14:12 +08:00
mini
4832534232 fix(landing): Polish items from code review
- Add noreferrer to all external rel attributes (4 anchors)
- Change 更新日志 link from /releases (may 404) to /commits/branch/main
- Remove dead CSS overridden by puro.css: .nav z-index:10, .nav-links gap:20px
- Document puro.css global dependency at top of scoped style block

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:11:13 +08:00
mini
4e675d70c1 feat(landing): Footer + sticky Nav styles
- 4-column footer (brand/产品/资源/联系), responsive 2-col on mobile
- Nav sticky with blur background, border-bottom
- nav-links hidden on mobile (<640px)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:01:10 +08:00
mini
c099cd5d97 feat(landing): add Code Demo + Dashboard mockup sections
Dashboard mockup is pure static (SVG chart + stats grid + log table).
No backend dependency. Reuses puro.css .log-table / .provider / .status-*
(scoped to .puro-page). Only adds component-local styles for .code-demo,
.dash-mock, .stat-row, .chart-card and friends.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:29:14 +08:00
mini
158f2a8d53 fix(landing): resolve Task 3 CSS specificity issues
Code review flagged:
- .feature.card caused padding/background specificity race;
  .feature already defines all card properties, so drop .card
- model-card flex row misaligned name/meta (should stack in column);
  wrap in div to get dot | [name/meta] layout
- .container and .section-* scoped rules silently shadow puro.css defaults;
  add comment explaining intentional override

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:26:50 +08:00
mini
cfcdd988db feat(landing): add Models wall + Features sections
- Added Models section (② 模型墙) with 5 platform cards (Claude, GPT, Codex, Gemini, More)
- Added Features section (③ 三特性) with 3 feature cards (unified key, account pool failover, analytics dashboard)
- Implemented responsive grid layouts with scoped CSS rules
- Used existing design tokens and brand colors from puro.css

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:18:56 +08:00
mini
9dae8724e3 feat(landing): LandingView scaffold with Nav + Hero
Temporary route /landing-preview added for dev iteration. Will flip /
to this view once all 6 sections are in place (Task 6).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:11:06 +08:00
mini
064a4b7614 fix(design): scope .bg-glow::before selector to .puro-page
One missed prefix from the automated transform. Aligns with the
scoping contract established in 41664efe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:06:21 +08:00
mini
41664efede fix(design): scope puro.css to .puro-page container
Code review flagged two critical issues with the initial scaffold:
- html/body bg + universal reset applied globally, overriding admin Tailwind styles
- Shared class names (.btn, .card, .input, .badge, .divider) collided with style.css,
  breaking 25+ admin views

Fix: all non-:root rules now scoped under .puro-page descendant selector.
@keyframes and global box-sizing preserved. html/body props merged into .puro-page root.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:03:22 +08:00
mini
1d7e75b82e feat(design): scaffold PURO AI design system
- Add puro.css (tokens + primitives) as global stylesheet
- Load Inter + JetBrains Mono via Google Fonts
- Extend tailwind.config with puro.* color namespace (no conflict with legacy primary/accent palettes)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 19:11:24 +08:00
shaw
a789c8c4c7 feat: 支持opus-4.7 2026-04-17 09:37:25 +08:00
Wesley Liddick
e6e73b4f52 Merge pull request #1690 from KnowSky404/fix/ws-codex-scheduler-cache-1662
fix: preserve openai ws flags in scheduler cache
2026-04-16 17:21:32 +08:00
KnowSky404
836092a666 fix: restore ctx pool ws mode option in account ui 2026-04-16 02:13:04 +00:00
Wesley Liddick
1db32d692b Merge pull request #1666 from touwaeriol/feat/account-cost-display
feat(usage): add account cost display to admin dashboard and usage pages
2026-04-15 16:43:07 +08:00
Wesley Liddick
8fd29082c0 Merge pull request #1663 from touwaeriol/fix/test-dialog-close-during-stream
fix(ui): allow closing test dialog during active SSE stream
2026-04-15 16:40:40 +08:00
erio
e180dd0710 fix(usage): remove label text from inline account cost, keep orange color 2026-04-15 16:09:58 +08:00
erio
a7dd535d47 fix(usage): show account cost inline under cost column, remove separate column
- Cost cell: change gray "A $xxx" to orange "成本 $xxx" with i18n
- Remove standalone account_cost column from column settings (redundant)
2026-04-15 15:59:51 +08:00
erio
db27e8f000 feat(usage): add account cost to breakdown sub-table and admin usage log
- UserBreakdownItem: add AccountCost field + SQL aggregation
- UserBreakdownSubTable: add orange account cost column
- Admin usage table: add account_cost column (after cost, default visible)
- Column settings: add account_cost toggle option
2026-04-15 15:40:40 +08:00
erio
e0b12b7512 fix(usage): put cost label before value in usage stats card 2026-04-15 15:02:21 +08:00
erio
6ade6d30a8 feat(usage): add account cost display to admin dashboard and usage pages
- Add account_cost column to dashboard aggregation tables (migration 107)
- DashboardStats: add TotalAccountCost/TodayAccountCost fields
- ModelStat/GroupStat: add AccountCost field with SQL aggregation
- GetStatsWithFilters: always return TotalAccountCost (remove accountID filter)
- Dashboard Token cards: show user(green)/cost(orange)/standard(gray)
- Usage stats card: show account cost and standard below main value
- Model/Group distribution tables: add orange cost column
2026-04-15 15:02:21 +08:00
erio
38c00872e1 fix(ui): allow closing test dialog during active SSE stream
Replace dead EventSource variable with AbortController to enable
cancelling fetch streams. Remove close-button disable during connecting
status so users can dismiss the dialog at any time.
2026-04-15 11:34:31 +08:00
erio
3053c56cac fix(payment): show full amount breakdown on payment result page
- Show base amount (充值金额) as first line
- Show fee amount with percentage when fee_rate > 0
- Show pay_amount (实付金额) in bold primary color
- Show credited amount (到账金额) when different from pay_amount
- Compute baseAmount and feeAmount from backend order data
2026-04-15 01:27:25 +08:00
erio
d149dbc91f fix(payment): enhance fee rate input validation and UI
Backend:
- Validate recharge_fee_rate: 0 ≤ rate ≤ 100, max 2 decimal places

Frontend settings:
- Add % suffix icon to fee rate input
- Enforce max=100, min=0, step=0.01 with 2 decimal precision
2026-04-15 01:27:24 +08:00
erio
e761d38fd1 fix(payment): integrate recharge fee rate in order flow and fix UI display
Backend:
- Use cfg.RechargeFeeRate in order creation instead of hardcoded 0
- Remove dead getFeeRate stub method
- All amounts computed server-side: order_amount, pay_amount, fee_rate

Frontend - PaymentView:
- Read recharge_fee_rate from checkout-info API (not per-method)
- Show fee breakdown only when fee_rate > 0
- Show credited amount only when multiplier ≠ 1

Frontend - Order display (user + admin):
- Fix fee_rate * 100 bug (fee_rate is already a percentage)
- OrderTable: show pay_amount as primary, fee/credited as sub-lines
- AdminOrderDetail: full breakdown (base/fee/paid/credited)
- AdminRefundDialog: label "到账金额" for clarity
- PaymentResultView: show pay_amount with fee info

Types + i18n:
- Add recharge_fee_rate to CheckoutInfoResponse
- Add fee_rate to CreateOrderResult
- Add translations: creditedAmount, fee, baseAmount, includedInPayAmount
2026-04-15 01:27:24 +08:00
erio
98140f6cac feat(payment): add recharge fee rate setting and fix provider card UI
- Add recharge_fee_rate system setting (percentage fee on top of recharge amount)
- Full backend chain: config constant, PaymentConfig struct, update validation,
  read/write persistence, DTO, handler GET/PUT responses
- Frontend: settings input with preview, i18n (zh/en), API types
- Fix provider card toggle layout: labels above switches to save width
- Fix Chinese translation: "EasyPay" → "易支付" in provider description
2026-04-15 01:27:24 +08:00
erio
60a4b9316b feat(payment): balance recharge multiplier and refund amount separation
- Add balance_recharge_multiplier system setting (e.g. 1.2 = charge 100 get 120)
- Separate order_amount (credited balance) from pay_amount (actual payment)
- Refund calculates gateway amount proportionally from pay_amount
- Frontend shows both amounts in order details, payment status, refund dialog
- Admin settings UI for configuring recharge multiplier
2026-04-15 01:27:24 +08:00
Wesley Liddick
7c671b5373 Merge pull request #1635 from KnowSky404/fix-issue-1613-version-dropdown
fix(sidebar): prevent version dropdown clipping in expanded brand
2026-04-14 20:41:53 +08:00
erio
3fa5b8bca5 fix: flaky WebSocket test, usage request queue, and test improvements
- Fix flaky WebSocket passthrough test: allow StatusNormalClosure after
  client close instead of requiring NoError (race condition fix)
- Fix ratelimit 401 test: use PlatformOpenAI instead of PlatformGemini
  for OAuth token cache invalidation scenario (more accurate)
- Add usageLoadQueue: Anthropic OAuth/setup-token accounts sharing the
  same proxy exit are serialized with 1-2s jitter to prevent upstream 429
- AccountUsageCell: add module-level usage cache (5min TTL), unmounted
  safety guard, and integrate enqueueUsageRequest for throttled fetching
2026-04-14 20:13:59 +08:00
erio
5240b44452 refactor(payment): inline payment flow, mobile support, renewal modal
Replace dialog-based payment with inline state flow (select → paying/stripe).
- PaymentStatusPanel replaces QR dialog for scan-to-pay
- StripePaymentInline replaces Stripe popup
- Subscription confirm as inline card instead of modal
- Payment button color follows payment method
- Renewal modal with URL parameter navigation (?tab=subscription&group=123)
- Mobile auto-redirect for H5 payment
- AmountInput uses global min/max instead of per-method
- Tab auto-hides during payment
- Restore CNY (¥) currency for upstream compatibility
2026-04-14 19:45:53 +08:00
erio
a56151fec9 refactor: extract CapacityBadge component from AccountCapacityCell
Extract repeated badge template (SVG icon + current/max display) into
a reusable CapacityBadge component. Reduces AccountCapacityCell from
~300 lines to ~180 lines with identical behavior.
2026-04-14 19:39:22 +08:00
erio
63f539b382 fix: merge general improvements from release branch
Backend:
- gateway_handler: pass subject.UserID instead of int64(0) for user-level routing
- setting_handler: add missing BalanceLowNotifyRechargeURL to UpdateSettings response
- openai_gateway_service: use applyAccountStatsCost for account stats pricing integration
- embed_on: add local file override (data/public/) for embedded frontend assets

Frontend:
- useTableSelection: add batchUpdate method for batch operations
- AccountsView: virtual scrolling params, Set-based isSelected, swipe virtualization
- ProxiesView: add batchUpdate to selection and swipe-select
- BulkEditAccountModal: fix submit handler to prevent event object as argument
- SettingsView: move payload construction outside try block
- i18n: add general translation keys (saved, deleted, view, validation, allowUserRefund)
- api/client: reorder error fields for consistency
- stores/payment: clarify pollOrderStatus JSDoc
2026-04-14 19:29:37 +08:00
erio
6ac8ccde46 fix: merge 30 general improvements from release branch
Bug fixes:
- Detached context for GetAccountConcurrencyBatch (prevent all-zero on request cancel)
- Filter soft-deleted users in GetByGroupID
- Stripe CSP policy (allow Stripe.js in script-src and frame-src)
- WebSearch API key validation on save
- RECHARGING status in payment result success check
- Windows test fixes (logger Sync deadlock, config path escaping)

Feature enhancements:
- Webhook multi-instance dispatch (extractOutTradeNo + GetWebhookProvider)
- EasyPay mobile H5 payment (device param + PayURL2)
- SSE error propagation in WebSearch emulation
- AccountStatsCost DTO field for admin usage logs
- Plans sort by sort_order instead of created_at
- UsageMapHook for streaming response usage data
- apicompat Instructions field passthrough
- EffectiveLoadFactor for ops concurrency/metrics
- Usage billing RETURNING balance for notify system
- BulkUpdate mixed channel warning with details
- println to slog migration in auth cache
- Wire ProviderSet cleanup
- CI cache-dependency-path optimization

Frontend:
- Refund eligibility check per provider (canRequestRefund)
- Plan sort_order editing
- Dead code cleanup (simulate_claude_max, client_affinity)
- GroupsView platform switch guard
- channels features_config API type
- UsageView account_stats_cost export
2026-04-14 17:35:27 +08:00
erio
f1297a3694 feat: add per-provider allow_user_refund control and align wildcard matching
allow_user_refund:
- Add allow_user_refund field to PaymentProviderInstance ent schema
- Migration 103: ALTER TABLE payment_provider_instances ADD COLUMN
- Cascade logic: disabling refund_enabled auto-disables allow_user_refund
- User refund validation: check provider instance allows user refund
- Admin refund validation: check provider instance allows admin refund
- Subscription refund: deduct days on refund, rollback on failure
- New endpoint: GET /payment/orders/refund-eligible-providers
- Frontend: ToggleSwitch in ProviderCard/Dialog, cascade in SettingsView

Wildcard matching:
- Change findPricingForModel from "longest prefix wins" to "config order
  priority (first match wins)", aligning with channel service behavior
2026-04-14 16:26:46 +08:00
erio
7c7292935e feat: websearch quota enhancements and balance notify hint
- QuotaLimit changed to *int64 (null=unlimited, >0=limited)
- Add reset-usage endpoint (POST /admin/settings/web-search-emulation/reset-usage)
- Show quota usage in header always (collapsed and expanded)
- Add reset quota button in expanded provider view
- Quota input: empty=unlimited with ∞ placeholder, must be >0 if set
- Add email verification hint on balance notify card
2026-04-14 09:36:40 +08:00
erio
9e0d12d3b0 fix: show websearch API key visibility/copy buttons for saved providers
The buttons were hidden because v-if only checked provider.api_key,
which is always empty for saved providers (backend sanitizes it).
Now also checks api_key_configured. Copy button is disabled when
no actual key is available (only configured placeholder shown).
2026-04-14 09:35:46 +08:00
erio
0a4ece5f5b fix: audit round-3 — proxy safety, intervals persistence, SMTP timeout, sort fix
- Skip websearch provider when ProxyID is set but proxy not found (prevent
  silent direct connection bypass)
- Fix sortByStableRandomWeight: pair factors with items so sort.Slice swap
  keeps weights aligned
- Allow empty platform in account_stats_pricing_rules (wildcard matching),
  only force anthropic default for main model_pricing
- Add channel_account_stats_pricing_intervals table and repo layer support
  for interval-based pricing in account stats rules
- calculateTokenStatsCost now uses interval pricing when available
- Replace smtp.SendMail/tls.Dial with net.Dialer timeout (10s dial, 20s IO)
  to prevent goroutine leak on SMTP hang
- Fix gofmt formatting issues
- Web Search label: black text with red warning hint
2026-04-14 09:35:20 +08:00