Files
sub2api/frontend/src/api/channels.ts
T
erio ff4ef1b574 feat(channels): themed model popover + group-badge with rate, subscription & exclusivity
Pricing popover:
- Teleport to body + fixed-position re-measuring on hover/scroll/resize so it
  escapes the card's overflow-hidden clip that was chopping off the lower
  half of the panel.
- Header + border adopt the platform theme via platformBorderClass /
  platformBadgeLightClass so each model card reads at a glance.

Accessible groups:
- Backend AvailableGroupRef / user DTO now expose subscription_type,
  rate_multiplier and is_exclusive. User-specific rates continue to come
  from /groups/rates (same pattern as the API keys page).
- Table renders groups through the shared GroupBadge, which already deepens
  subscription-type colors and shows default vs custom rate as
  <s>default</s> <b>custom</b>.
- Exclusive groups are labelled with a purple shield row, public groups
  with a grey globe row so admins and users can tell at a glance which
  groups they got via explicit grant vs. public access.

i18n keys for exclusive / public / their tooltips added to zh + en.
2026-04-21 21:44:34 +08:00

77 lines
2.3 KiB
TypeScript

/**
* User Channels API endpoints (non-admin)
* 用户侧「可用渠道」聚合查询:渠道 + 用户可访问的分组 + 支持模型(含定价)。
*/
import { apiClient } from './client'
import type { BillingMode } from '@/constants/channel'
export interface UserAvailableGroup {
id: number
name: string
platform: string
/** 'standard' | 'subscription' — 订阅分组视觉加深,和 API 密钥页保持一致。 */
subscription_type: string
/** 分组默认倍率。用户专属倍率(若有)通过 /groups/rates 获取后在前端 join。 */
rate_multiplier: number
/** true = 专属分组(小范围授权);false = 公开分组。 */
is_exclusive: boolean
}
export interface UserPricingInterval {
min_tokens: number
max_tokens: number | null
tier_label?: string
input_price: number | null
output_price: number | null
cache_write_price: number | null
cache_read_price: number | null
per_request_price: number | null
}
export interface UserSupportedModelPricing {
billing_mode: BillingMode
input_price: number | null
output_price: number | null
cache_write_price: number | null
cache_read_price: number | null
image_output_price: number | null
per_request_price: number | null
intervals: UserPricingInterval[]
}
export interface UserSupportedModel {
name: string
platform: string
pricing: UserSupportedModelPricing | null
}
/**
* 渠道下单个平台的子视图:用户可访问的分组 + 该平台支持的模型。
* 后端把一个渠道按平台聚合成 sections,前端可以把渠道名作为 row-group
* 一次渲染,后面按 sections 顺序用 rowspan 铺开。
*/
export interface UserChannelPlatformSection {
platform: string
groups: UserAvailableGroup[]
supported_models: UserSupportedModel[]
}
export interface UserAvailableChannel {
name: string
description: string
platforms: UserChannelPlatformSection[]
}
/** 列出当前用户可见的「可用渠道」(与 /groups/available 保持一致,返回平数组)。 */
export async function getAvailable(options?: { signal?: AbortSignal }): Promise<UserAvailableChannel[]> {
const { data } = await apiClient.get<UserAvailableChannel[]>('/channels/available', {
signal: options?.signal
})
return data
}
export const userChannelsAPI = { getAvailable }
export default userChannelsAPI