feat(admin):渠道模型能力页面添加字段使用说明

This commit is contained in:
qian committed 2026-08-02 14:20:35 +08:00
1 parent 49b05b66ad
commit f13b583c35
6 files changed
+18 -87

No files matched your search

-1
View File
@@ -57,7 +57,6 @@ type IAdminV1 interface {
ChannelKeyCreate(ctx context.Context, req *v1.ChannelKeyCreateReq) (res *v1.ChannelKeyCreateRes, err error)
ChannelKeyDelete(ctx context.Context, req *v1.ChannelKeyDeleteReq) (res *v1.ChannelKeyDeleteRes, err error)
ChannelAbilityBatch(ctx context.Context, req *v1.ChannelAbilityBatchReq) (res *v1.ChannelAbilityBatchRes, err error)
ChannelCostRatioImport(ctx context.Context, req *v1.ChannelCostRatioImportReq) (res *v1.ChannelCostRatioImportRes, err error)
ProviderDefaultURL(ctx context.Context, req *v1.ProviderDefaultURLReq) (res *v1.ProviderDefaultURLRes, err error)
ChannelKeyList(ctx context.Context, req *v1.ChannelKeyListReq) (res *v1.ChannelKeyListRes, err error)
ChannelAbilitiesGet(ctx context.Context, req *v1.ChannelAbilitiesGetReq) (res *v1.ChannelAbilitiesGetRes, err error)
-19
View File
@@ -169,25 +169,6 @@ type AbilityItem struct {
CostRatio float64 `json:"cost_ratio" d:"1" v:"between:0,100" dc:"成本比例:上游实际价/平台基准价,1.0=等价(参与调度 costFactor)"`
}
// ChannelCostRatioImportReq 批量导入渠道模型成本比例(CSV 由前端解析为条目)
type ChannelCostRatioImportReq struct {
g.Meta `path:"/channels/cost-ratio-import" method:"post" mime:"json" tags:"管理后台-渠道" summary:"批量导入成本比例"`
Items []CostRatioImportItem `json:"items" v:"required#请提供导入条目" dc:"导入条目列表"`
}
// CostRatioImportItem 成本比例导入条目
type CostRatioImportItem struct {
ChannelID int64 `json:"channel_id" v:"required|min:1" dc:"渠道ID"`
ModelName string `json:"model_name" v:"required" dc:"平台标准模型名"`
CostRatio float64 `json:"cost_ratio" v:"required|between:0.0001,100" dc:"成本比例"`
}
// ChannelCostRatioImportRes 批量导入成本比例响应
type ChannelCostRatioImportRes struct {
Updated int `json:"updated" dc:"成功更新条数"`
Skipped []string `json:"skipped" dc:"未匹配到能力记录的条目(渠道ID:模型名)"`
}
// ProviderDefaultURLReq 获取供应商默认 URL
type ProviderDefaultURLReq struct {
g.Meta `path:"/channels/provider-default-urls" method:"get" mime:"json" tags:"管理后台-渠道" summary:"供应商默认地址"`
@@ -49,6 +49,3 @@ func (c *ControllerV1) ChannelExport(ctx context.Context, req *v1.ChannelExportR
func (c *ControllerV1) ChannelClone(ctx context.Context, req *v1.ChannelCloneReq) (res *v1.ChannelCloneRes, err error) {
return service.Admin().CloneChannel(ctx, req)
}
func (c *ControllerV1) ChannelCostRatioImport(ctx context.Context, req *v1.ChannelCostRatioImportReq) (res *v1.ChannelCostRatioImportRes, err error) {
return service.Admin().ImportChannelCostRatios(ctx, req)
}
-24
View File
@@ -636,30 +636,6 @@ func (s *sAdmin) GetChannelAbilities(ctx context.Context, req *v1.ChannelAbiliti
return &v1.ChannelAbilitiesGetRes{List: list}, nil
}
// ImportChannelCostRatios 批量导入渠道模型成本比例(CSV 由前端解析为条目提交)。
// 只更新已存在的能力记录,未匹配的条目返回在 skipped 中;成功后触发目录失效。
func (s *sAdmin) ImportChannelCostRatios(ctx context.Context, req *v1.ChannelCostRatioImportReq) (*v1.ChannelCostRatioImportRes, error) {
res := &v1.ChannelCostRatioImportRes{Skipped: make([]string, 0)}
for _, item := range req.Items {
affected, err := dao.ChnAbilities.Ctx(ctx).
Where("channel_id", item.ChannelID).
Where("model_name", item.ModelName).
Data(do.ChnAbilities{CostRatio: item.CostRatio}).
UpdateAndGetAffected()
if err != nil {
return nil, err
}
if affected == 0 {
res.Skipped = append(res.Skipped, fmt.Sprintf("%d:%s", item.ChannelID, item.ModelName))
continue
}
res.Updated++
}
// 成本比例参与调度 costFactor,变更后跨实例目录失效
dispatchadapter.PublishInvalidate(ctx)
return res, nil
}
// GetProviderDefaultURLs 获取供应商默认 API 地址
func (s *sAdmin) GetProviderDefaultURLs(ctx context.Context, _ *v1.ProviderDefaultURLReq) (*v1.ProviderDefaultURLRes, error) {
return &v1.ProviderDefaultURLRes{URLs: defaultProviderURLs}, nil
-3
View File
@@ -115,9 +115,6 @@ type (
GetChannelKeys(ctx context.Context, req *v1.ChannelKeyListReq) (*v1.ChannelKeyListRes, error)
// GetChannelAbilities 获取渠道模型能力列表
GetChannelAbilities(ctx context.Context, req *v1.ChannelAbilitiesGetReq) (*v1.ChannelAbilitiesGetRes, error)
// ImportChannelCostRatios 批量导入渠道模型成本比例(CSV 由前端解析为条目提交)。
// 只更新已存在的能力记录,未匹配的条目返回在 skipped 中;成功后触发目录失效。
ImportChannelCostRatios(ctx context.Context, req *v1.ChannelCostRatioImportReq) (*v1.ChannelCostRatioImportRes, error)
// GetProviderDefaultURLs 获取供应商默认 API 地址
GetProviderDefaultURLs(ctx context.Context, _ *v1.ProviderDefaultURLReq) (*v1.ProviderDefaultURLRes, error)
// GetChannelHealthTrend 获取渠道健康趋势数据
+18 -37
View File
@@ -228,36 +228,6 @@ function handleUpstreamModelChange(record: any, value: string) {
scheduleAbilitySave('上游模型名已更新')
}
// CSV 批量导入成本比例:每行 "model_name,cost_ratio"(首行可为表头)
const csvInputRef = ref<HTMLInputElement>()
const csvImporting = ref(false)
function triggerCsvImport() { csvInputRef.value?.click() }
async function handleCsvFile(e: Event) {
const input = e.target as HTMLInputElement
const file = input.files?.[0]
input.value = ''
if (!file) return
const text = await file.text()
const items: { channel_id: number; model_name: string; cost_ratio: number }[] = []
for (const rawLine of text.split(/\r?\n/)) {
const line = rawLine.trim()
if (!line) continue
const [model, ratioStr] = line.split(',').map(s => s?.trim())
const ratio = Number(ratioStr)
if (!model || !Number.isFinite(ratio) || ratio <= 0) continue // 跳过表头与非法行
items.push({ channel_id: Number(channelId), model_name: model, cost_ratio: ratio })
}
if (!items.length) { Message.warning('未解析到有效条目,格式:model_name,cost_ratio'); return }
csvImporting.value = true
try {
const res: any = await request.post('/admin/channels/cost-ratio-import', { items })
const data = res.data?.data || res.data
const skipped = data?.skipped?.length ? `,未匹配 ${data.skipped.length} 条` : ''
Message.success(`已更新 ${data?.updated ?? 0} 条${skipped}`)
fetchAbilities()
} catch { /* error handled by interceptor */ } finally { csvImporting.value = false }
}
async function handleDeleteAbility(id: number) {
const newList = abilitiesData.value.filter(a => a.id !== id)
try {
@@ -593,15 +563,14 @@ function formatHeaders(headers: Record<string, string>): string {
<!-- Tab 2: Model Abilities -->
<ATabPane key="abilities" title="模型能力">
<ACard :bordered="false">
<template #title>
<div class="flex items-center justify-between">
<span>模型能力配置</span>
<AButton type="primary" @click="openAddAbilityModal">添加能力</AButton>
</div>
</template>
<div class="flex items-center justify-between mb-4">
<span style="color: var(--color-text-3)">已配置 {{ abilitiesData.length }} 个模型能力</span>
<ASpace>
<ATooltip content="CSV 每行:model_name,cost_ratio(如 gpt-4o,0.8)">
<AButton type="outline" :loading="csvImporting" @click="triggerCsvImport">导入成本比例</AButton>
</ATooltip>
<AButton type="primary" @click="openAddAbilityModal">添加能力</AButton>
</ASpace>
<input ref="csvInputRef" type="file" accept=".csv,text/csv" style="display:none" @change="handleCsvFile" />
</div>
<ATable
:columns="abilityColumns"
@@ -612,6 +581,18 @@ function formatHeaders(headers: Record<string, string>): string {
:pagination="false"
row-key="id"
/>
<!-- 字段功能说明(面向运营者) -->
<div class="mt-3 text-xs" style="color: var(--color-text-3); line-height: 1.7;">
<div class="mb-1"><strong>字段说明</strong></div>
<div class="flex flex-wrap gap-x-6 gap-y-1">
<div>
<span style="font-weight: 500;">上游模型名:</span>该渠道转发请求时实际调用的上游模型名称。仅当上游名称与平台标准模型名不同时填写(如平台名 gpt-4、上游名 gpt-4-0314);留空表示与平台模型名相同。
</div>
<div>
<span style="font-weight: 500;">成本比例:</span>该渠道相对基准价的成本系数,1.0 为标准。小于 1(如 0.8)表示更便宜,多渠道择优时更优先调度;大于 1(如 1.5)表示更贵,优先级降低。仅用于渠道调度,不影响对用户的计费。
</div>
</div>
</div>
</ACard>
</ATabPane>