feat: add routing reliability management

This commit is contained in:
CaIon
2026-06-20 13:55:50 +08:00
parent dfcb74b52d
commit 91ab664c53
36 changed files with 1171 additions and 782 deletions
+9
View File
@@ -24,6 +24,7 @@ import type {
BatchSetTagParams,
Channel,
ChannelBalanceResponse,
ChannelOpsResponse,
ChannelTestResponse,
CopyChannelParams,
CopyChannelResponse,
@@ -103,6 +104,14 @@ export async function getChannel(id: number): Promise<GetChannelResponse> {
return res.data
}
/**
* Get channel operations summary for administrators
*/
export async function getChannelOps(): Promise<ChannelOpsResponse> {
const res = await api.get('/api/channel/ops', channelActionConfig())
return res.data
}
/**
* Create new channel(s)
* Supports single, batch, and multi-key modes
+65 -1
View File
@@ -17,7 +17,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import { useTranslation } from 'react-i18next'
import { Link } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { Settings2 } from 'lucide-react'
import { SectionPageLayout } from '@/components/layout'
import { Badge } from '@/components/ui/badge'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip'
import { ROLE } from '@/lib/roles'
import { useAuthStore } from '@/stores/auth-store'
import { getChannelOps } from './api'
import { ChannelsDialogs } from './components/channels-dialogs'
import { ChannelsPrimaryButtons } from './components/channels-primary-buttons'
import { ChannelsProvider } from './components/channels-provider'
@@ -25,10 +37,62 @@ import { ChannelsTable } from './components/channels-table'
export function Channels() {
const { t } = useTranslation()
const isRoot = useAuthStore(
(state) => state.auth.user?.role === ROLE.SUPER_ADMIN
)
const channelOpsQuery = useQuery({
queryKey: ['channel-ops'],
queryFn: getChannelOps,
retry: false,
staleTime: 5 * 60 * 1000,
})
const retryTimes = channelOpsQuery.data?.data?.retry_times
const retryLabel =
typeof retryTimes === 'number'
? `${t('Max Retries')}: ${retryTimes}`
: null
let retryBadge = null
if (retryLabel) {
retryBadge = isRoot ? (
<Tooltip>
<TooltipTrigger
render={
<Badge
variant='outline'
className='shrink-0 cursor-pointer'
aria-label={t('Retry Settings')}
render={
<Link
to='/system-settings/models/$section'
params={{ section: 'routing-reliability' }}
/>
}
/>
}
>
<span>{retryLabel}</span>
<Settings2 data-icon='inline-end' />
</TooltipTrigger>
<TooltipContent>
<p>{t('Retry Settings')}</p>
</TooltipContent>
</Tooltip>
) : (
<Badge variant='outline' className='shrink-0'>
{retryLabel}
</Badge>
)
}
return (
<ChannelsProvider>
<SectionPageLayout fixedContent>
<SectionPageLayout.Title>{t('Channels')}</SectionPageLayout.Title>
<SectionPageLayout.Title>
<span className='flex min-w-0 items-center gap-2'>
<span className='truncate'>{t('Channels')}</span>
{retryBadge}
</span>
</SectionPageLayout.Title>
<SectionPageLayout.Actions>
<ChannelsPrimaryButtons />
</SectionPageLayout.Actions>
+8
View File
@@ -167,6 +167,14 @@ export interface GetChannelResponse {
data?: Channel
}
export interface ChannelOpsResponse {
success: boolean
message?: string
data?: {
retry_times: number
}
}
export interface ChannelTestResponse {
success: boolean
message?: string