feat(ui): 渠道表单模型标签和映射输入框显示平台对应颜色
- PricingEntryCard 折叠态模型 tag 按平台着色 - ModelTagInput 模型标签按平台着色 - 模型映射输入框边框按平台着色
This commit is contained in:
@@ -5,7 +5,8 @@
|
|||||||
<span
|
<span
|
||||||
v-for="(model, idx) in models"
|
v-for="(model, idx) in models"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
class="inline-flex items-center gap-1 rounded-md bg-primary-50 px-2 py-0.5 text-sm text-primary-700 dark:bg-primary-900/30 dark:text-primary-300"
|
class="inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-sm"
|
||||||
|
:class="getPlatformTagClass(props.platform || '')"
|
||||||
>
|
>
|
||||||
{{ model }}
|
{{ model }}
|
||||||
<button
|
<button
|
||||||
@@ -38,12 +39,14 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import Icon from '@/components/icons/Icon.vue'
|
import Icon from '@/components/icons/Icon.vue'
|
||||||
|
import { getPlatformTagClass } from './types'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
models: string[]
|
models: string[]
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
|
platform?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
<span
|
<span
|
||||||
v-for="(m, i) in entry.models.slice(0, 3)"
|
v-for="(m, i) in entry.models.slice(0, 3)"
|
||||||
:key="i"
|
:key="i"
|
||||||
class="inline-flex shrink-0 rounded bg-gray-200 px-1.5 py-0.5 text-xs text-gray-700 dark:bg-dark-600 dark:text-gray-300"
|
class="inline-flex shrink-0 rounded px-1.5 py-0.5 text-xs"
|
||||||
|
:class="getPlatformTagClass(props.platform || '')"
|
||||||
>
|
>
|
||||||
{{ m }}
|
{{ m }}
|
||||||
</span>
|
</span>
|
||||||
@@ -74,6 +75,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<ModelTagInput
|
<ModelTagInput
|
||||||
:models="entry.models"
|
:models="entry.models"
|
||||||
|
:platform="props.platform"
|
||||||
@update:models="onModelsUpdate($event)"
|
@update:models="onModelsUpdate($event)"
|
||||||
:placeholder="t('admin.channels.form.modelsPlaceholder', '输入模型名后按回车添加,支持通配符 *')"
|
:placeholder="t('admin.channels.form.modelsPlaceholder', '输入模型名后按回车添加,支持通配符 *')"
|
||||||
class="mt-1"
|
class="mt-1"
|
||||||
@@ -232,7 +234,7 @@ import Icon from '@/components/icons/Icon.vue'
|
|||||||
import IntervalRow from './IntervalRow.vue'
|
import IntervalRow from './IntervalRow.vue'
|
||||||
import ModelTagInput from './ModelTagInput.vue'
|
import ModelTagInput from './ModelTagInput.vue'
|
||||||
import type { PricingFormEntry, IntervalFormEntry } from './types'
|
import type { PricingFormEntry, IntervalFormEntry } from './types'
|
||||||
import { perTokenToMTok } from './types'
|
import { perTokenToMTok, getPlatformTagClass } from './types'
|
||||||
import type { BillingMode } from '@/api/admin/channels'
|
import type { BillingMode } from '@/api/admin/channels'
|
||||||
import channelsAPI from '@/api/admin/channels'
|
import channelsAPI from '@/api/admin/channels'
|
||||||
|
|
||||||
@@ -240,6 +242,7 @@ const { t } = useI18n()
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
entry: PricingFormEntry
|
entry: PricingFormEntry
|
||||||
|
platform?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -72,3 +72,27 @@ export function formIntervalsToAPI(intervals: IntervalFormEntry[]): PricingInter
|
|||||||
sort_order: iv.sort_order
|
sort_order: iv.sort_order
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 平台对应的模型 tag 样式(背景+文字) */
|
||||||
|
export function getPlatformTagClass(platform: string): string {
|
||||||
|
switch (platform) {
|
||||||
|
case 'anthropic': return 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'
|
||||||
|
case 'openai': return 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400'
|
||||||
|
case 'gemini': return 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400'
|
||||||
|
case 'antigravity': return 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400'
|
||||||
|
case 'sora': return 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400'
|
||||||
|
default: return 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 平台对应的输入框边框色 */
|
||||||
|
export function getPlatformBorderClass(platform: string): string {
|
||||||
|
switch (platform) {
|
||||||
|
case 'anthropic': return 'border-orange-300 dark:border-orange-700'
|
||||||
|
case 'openai': return 'border-emerald-300 dark:border-emerald-700'
|
||||||
|
case 'gemini': return 'border-blue-300 dark:border-blue-700'
|
||||||
|
case 'antigravity': return 'border-purple-300 dark:border-purple-700'
|
||||||
|
case 'sora': return 'border-rose-300 dark:border-rose-700'
|
||||||
|
default: return 'border-gray-300 dark:border-dark-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -322,6 +322,7 @@
|
|||||||
:value="srcModel"
|
:value="srcModel"
|
||||||
type="text"
|
type="text"
|
||||||
class="input flex-1 text-xs"
|
class="input flex-1 text-xs"
|
||||||
|
:class="getPlatformInputBorder(section.platform)"
|
||||||
:placeholder="t('admin.channels.form.mappingSource', 'Source model')"
|
:placeholder="t('admin.channels.form.mappingSource', 'Source model')"
|
||||||
@change="renameMappingKey(sIdx, srcModel, ($event.target as HTMLInputElement).value)"
|
@change="renameMappingKey(sIdx, srcModel, ($event.target as HTMLInputElement).value)"
|
||||||
/>
|
/>
|
||||||
@@ -330,6 +331,7 @@
|
|||||||
:value="section.model_mapping[srcModel]"
|
:value="section.model_mapping[srcModel]"
|
||||||
type="text"
|
type="text"
|
||||||
class="input flex-1 text-xs"
|
class="input flex-1 text-xs"
|
||||||
|
:class="getPlatformInputBorder(section.platform)"
|
||||||
:placeholder="t('admin.channels.form.mappingTarget', 'Target model')"
|
:placeholder="t('admin.channels.form.mappingTarget', 'Target model')"
|
||||||
@input="section.model_mapping[srcModel] = ($event.target as HTMLInputElement).value"
|
@input="section.model_mapping[srcModel] = ($event.target as HTMLInputElement).value"
|
||||||
/>
|
/>
|
||||||
@@ -363,6 +365,7 @@
|
|||||||
v-for="(entry, idx) in section.model_pricing"
|
v-for="(entry, idx) in section.model_pricing"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
:entry="entry"
|
:entry="entry"
|
||||||
|
:platform="section.platform"
|
||||||
@update="updatePricingEntry(sIdx, idx, $event)"
|
@update="updatePricingEntry(sIdx, idx, $event)"
|
||||||
@remove="removePricingEntry(sIdx, idx)"
|
@remove="removePricingEntry(sIdx, idx)"
|
||||||
/>
|
/>
|
||||||
@@ -532,6 +535,17 @@ function getRateBadgeClass(platform: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPlatformInputBorder(platform: string): string {
|
||||||
|
switch (platform) {
|
||||||
|
case 'anthropic': return 'border-orange-300 focus:border-orange-500 dark:border-orange-700'
|
||||||
|
case 'openai': return 'border-emerald-300 focus:border-emerald-500 dark:border-emerald-700'
|
||||||
|
case 'gemini': return 'border-blue-300 focus:border-blue-500 dark:border-blue-700'
|
||||||
|
case 'antigravity': return 'border-purple-300 focus:border-purple-500 dark:border-purple-700'
|
||||||
|
case 'sora': return 'border-rose-300 focus:border-rose-500 dark:border-rose-700'
|
||||||
|
default: return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Helpers ──
|
// ── Helpers ──
|
||||||
function formatDate(value: string): string {
|
function formatDate(value: string): string {
|
||||||
if (!value) return '-'
|
if (!value) return '-'
|
||||||
|
|||||||
Reference in New Issue
Block a user