Merge pull request #4385 from yardbirds0/feat/upstream-billing-probe

feat: 增加上游 Sub2API 计费倍率探测与账号展示
This commit is contained in:
Wesley Liddick
2026-07-16 10:27:45 +08:00
committed by GitHub
49 changed files with 5747 additions and 74 deletions
@@ -0,0 +1,53 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
const { get, post, put } = vi.hoisted(() => ({
get: vi.fn(),
post: vi.fn(),
put: vi.fn()
}))
vi.mock('@/api/client', () => ({
apiClient: { get, post, put }
}))
import {
getUpstreamBillingProbeSettings,
probeUpstreamBilling,
probeUpstreamBillingBatch,
setUpstreamBillingProbeEnabled,
updateUpstreamBillingProbeSettings
} from '@/api/admin/accounts'
describe('admin account upstream billing probe API', () => {
beforeEach(() => {
get.mockReset()
post.mockReset()
put.mockReset()
})
it('reads and updates global settings', async () => {
const settings = { enabled: true, interval_minutes: 30 }
get.mockResolvedValueOnce({ data: settings })
put.mockResolvedValueOnce({ data: settings })
await expect(getUpstreamBillingProbeSettings()).resolves.toEqual(settings)
await expect(updateUpstreamBillingProbeSettings(settings)).resolves.toEqual(settings)
expect(get).toHaveBeenCalledWith('/admin/accounts/upstream-billing-probe/settings')
expect(put).toHaveBeenCalledWith('/admin/accounts/upstream-billing-probe/settings', settings)
})
it('uses dedicated account and batch endpoints', async () => {
const result = { account_id: 7, snapshot: { status: 'unsupported' } }
put.mockResolvedValueOnce({ data: {} })
post.mockResolvedValueOnce({ data: result })
post.mockResolvedValueOnce({ data: { results: [result] } })
await setUpstreamBillingProbeEnabled(7, true)
await expect(probeUpstreamBilling(7)).resolves.toEqual(result)
await expect(probeUpstreamBillingBatch([7])).resolves.toEqual([result])
expect(put).toHaveBeenCalledWith('/admin/accounts/7/upstream-billing-probe', { enabled: true })
expect(post).toHaveBeenNthCalledWith(1, '/admin/accounts/7/upstream-billing-probe')
expect(post).toHaveBeenNthCalledWith(2, '/admin/accounts/upstream-billing-probe/batch', { account_ids: [7] })
})
})
+41 -2
View File
@@ -20,7 +20,9 @@ import type {
CodexSessionImportResult,
OpenAICodexPATCreateRequest,
CheckMixedChannelRequest,
CheckMixedChannelResponse
CheckMixedChannelResponse,
UpstreamBillingProbeResult,
UpstreamBillingProbeSettings
} from '@/types'
/**
@@ -848,6 +850,38 @@ export async function createSparkShadow(parentId: number, payload: SparkShadowCr
return data
}
export async function getUpstreamBillingProbeSettings(): Promise<UpstreamBillingProbeSettings> {
const { data } = await apiClient.get<UpstreamBillingProbeSettings>('/admin/accounts/upstream-billing-probe/settings')
return data
}
export async function updateUpstreamBillingProbeSettings(
settings: UpstreamBillingProbeSettings
): Promise<UpstreamBillingProbeSettings> {
const { data } = await apiClient.put<UpstreamBillingProbeSettings>(
'/admin/accounts/upstream-billing-probe/settings',
settings
)
return data
}
export async function setUpstreamBillingProbeEnabled(id: number, enabled: boolean): Promise<void> {
await apiClient.put(`/admin/accounts/${id}/upstream-billing-probe`, { enabled })
}
export async function probeUpstreamBilling(id: number): Promise<UpstreamBillingProbeResult> {
const { data } = await apiClient.post<UpstreamBillingProbeResult>(`/admin/accounts/${id}/upstream-billing-probe`)
return data
}
export async function probeUpstreamBillingBatch(accountIds: number[]): Promise<UpstreamBillingProbeResult[]> {
const { data } = await apiClient.post<{ results: UpstreamBillingProbeResult[] }>(
'/admin/accounts/upstream-billing-probe/batch',
{ account_ids: accountIds }
)
return data.results
}
export const accountsAPI = {
list,
listWithEtag,
@@ -894,7 +928,12 @@ export const accountsAPI = {
revertProxyFallback,
queryOpenAIQuota,
resetOpenAIQuota,
createSparkShadow
createSparkShadow,
getUpstreamBillingProbeSettings,
updateUpstreamBillingProbeSettings,
setUpstreamBillingProbeEnabled,
probeUpstreamBilling,
probeUpstreamBillingBatch
}
export default accountsAPI