refactor(channels): tighten types and error paths per second review
- service: drop groupRepo nil guard (DI must inject), switch SupportedModels to SliceStable to match doc - frontend: reuse user-side DTO types in SupportedModelChip/AvailableChannelsTable instead of duplicating shapes; narrow admin statusLabel param to ChannelStatus - tests: replace nil-groupRepo case with ListAll/ListActive error propagation and BillingModelSource default-backfill coverage
This commit is contained in:
@@ -61,6 +61,7 @@ import { computed, useSlots } from 'vue'
|
||||
import DataTable from '@/components/common/DataTable.vue'
|
||||
import Icon from '@/components/icons/Icon.vue'
|
||||
import SupportedModelChip from './SupportedModelChip.vue'
|
||||
import type { UserSupportedModelPricing } from '@/api/channels'
|
||||
|
||||
interface GroupRef {
|
||||
id: number
|
||||
@@ -75,7 +76,7 @@ interface Row {
|
||||
supported_models: Array<{
|
||||
name: string
|
||||
platform: string
|
||||
pricing: unknown | null
|
||||
pricing: UserSupportedModelPricing | null
|
||||
}>
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
@@ -127,34 +127,15 @@ import {
|
||||
BILLING_MODE_IMAGE,
|
||||
type BillingMode
|
||||
} from '@/constants/channel'
|
||||
import type { UserPricingInterval, UserSupportedModel } from '@/api/channels'
|
||||
|
||||
interface PricingInterval {
|
||||
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
|
||||
}
|
||||
|
||||
interface SupportedModelPricing {
|
||||
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: PricingInterval[]
|
||||
}
|
||||
|
||||
interface SupportedModelLike {
|
||||
name: string
|
||||
platform: string
|
||||
pricing: SupportedModelPricing | null
|
||||
}
|
||||
/**
|
||||
* 复用 api/channels.ts 的用户侧最小形态 DTO。
|
||||
* admin 侧 ChannelModelPricing 字段更多,但结构上是用户 DTO 的超集,
|
||||
* 因此 admin 视图传入时 TypeScript 结构化子类型会直接通过。
|
||||
*/
|
||||
type PricingInterval = UserPricingInterval
|
||||
type SupportedModelLike = UserSupportedModel
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
||||
@@ -78,7 +78,7 @@ import AvailableChannelsTable from '@/components/channels/AvailableChannelsTable
|
||||
import channelsAPI, { type AvailableChannel } from '@/api/admin/channels'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { extractApiErrorMessage } from '@/utils/apiError'
|
||||
import { CHANNEL_STATUS_ACTIVE } from '@/constants/channel'
|
||||
import { CHANNEL_STATUS_ACTIVE, type ChannelStatus } from '@/constants/channel'
|
||||
|
||||
const { t } = useI18n()
|
||||
const appStore = useAppStore()
|
||||
@@ -95,7 +95,7 @@ const columns = computed(() => [
|
||||
{ key: 'supported_models', label: t('admin.availableChannels.columns.supportedModels') }
|
||||
])
|
||||
|
||||
function statusLabel(status: string): string {
|
||||
function statusLabel(status: ChannelStatus): string {
|
||||
return status === CHANNEL_STATUS_ACTIVE
|
||||
? t('admin.availableChannels.statusActive')
|
||||
: t('admin.availableChannels.statusDisabled')
|
||||
|
||||
Reference in New Issue
Block a user