feat: add icon for ai provider (#12722)

This commit is contained in:
CityFun
2026-05-13 18:37:30 +08:00
committed by zhengkunwang223
parent aa10760658
commit d522d837ff
29 changed files with 296 additions and 11 deletions

View File

@@ -200,8 +200,13 @@ export const updateAgentAccount = (req: AI.AgentAccountUpdateReq) => {
return http.post(`/ai/agents/accounts/update`, req);
};
export const pageAgentAccounts = (req: AI.AgentAccountSearch) => {
return http.post<ResPage<AI.AgentAccountItem>>(`/ai/agents/accounts/search`, req);
export const pageAgentAccounts = (req: AI.AgentAccountSearch, currentNode?: string) => {
return http.post<ResPage<AI.AgentAccountItem>>(
`/ai/agents/accounts/search`,
req,
undefined,
currentNode ? { CurrentNode: currentNode } : undefined,
);
};
export const getAgentAccountModels = (req: AI.AgentAccountModelReq) => {

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,4 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.7202 0.939941C22.9502 0.939941 23.9502 1.93994 23.9502 3.16994C23.9502 4.39994 22.9502 5.39994 21.7202 5.39994H19.7502C19.6002 5.39994 19.4902 5.27994 19.4902 5.13994V3.16994C19.4902 1.93994 20.4902 0.939941 21.7202 0.939941Z" fill="#1783FF"/>
<path d="M9.39 13.9501L17.82 5.59012C17.98 5.43012 17.89 5.12012 17.68 5.12012H13.14C13.14 5.12012 13.04 5.14012 13 5.18012L3.92 14.1901C3.78 14.3301 3.57 14.2101 3.57 13.9801V5.39012C3.57 5.24012 3.47 5.12012 3.35 5.12012H0.219999C0.0999993 5.12012 0 5.24012 0 5.39012V23.9201C0 24.0701 0.0999993 24.1901 0.219999 24.1901H3.35C3.47 24.1901 3.57 24.0701 3.57 23.9201V20.1401C3.57 20.0601 3.6 19.9801 3.65 19.9301L6.47 17.1401C6.54 17.0701 6.63 17.0601 6.71 17.1101L14.24 22.6501C15.47 23.4801 16.85 23.9901 18.25 24.1401C18.37 24.1501 18.48 24.0301 18.48 23.8701V20.3101C18.48 20.1701 18.4 20.0601 18.29 20.0501C17.47 19.9201 16.66 19.6001 15.94 19.1101L9.42 14.3901C9.28 14.3001 9.27 14.0701 9.39 13.9501Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M11.248 18.25q-.825 0-1.568-.314a4.3 4.3 0 0 1-1.32-.874 4 4 0 0 1-1.304.214 4 4 0 0 1-2.046-.544 4.27 4.27 0 0 1-1.518-1.485 4 4 0 0 1-.56-2.095q0-.48.131-1.04A4.4 4.4 0 0 1 2.04 10.71a4.07 4.07 0 0 1 .017-3.4 4.2 4.2 0 0 1 1.056-1.418 3.8 3.8 0 0 1 1.6-.842 3.9 3.9 0 0 1 .76-1.683q.593-.759 1.451-1.188a4.04 4.04 0 0 1 1.832-.429q.825 0 1.567.313.742.314 1.32.875a4 4 0 0 1 1.304-.215q1.106 0 2.046.545a4.14 4.14 0 0 1 1.501 1.485q.578.941.578 2.095 0 .48-.132 1.04.66.61 1.023 1.419.363.792.363 1.666 0 .892-.38 1.717a4.3 4.3 0 0 1-1.072 1.435 3.8 3.8 0 0 1-1.584.825 3.8 3.8 0 0 1-.775 1.683 4.06 4.06 0 0 1-1.436 1.188 4.04 4.04 0 0 1-1.832.429m-4.076-2.062q.825 0 1.435-.347l3.103-1.782a.36.36 0 0 0 .164-.313v-1.42L7.881 14.62a.67.67 0 0 1-.726 0l-3.118-1.798a.5.5 0 0 1-.017.115v.198q0 .841.396 1.551.413.693 1.139 1.089a3.2 3.2 0 0 0 1.617.412m.165-2.69a.4.4 0 0 0 .181.05q.083 0 .165-.05l1.238-.71-3.977-2.31a.7.7 0 0 1-.363-.643v-3.58q-.825.362-1.32 1.122a2.9 2.9 0 0 0-.495 1.65q0 .809.413 1.55.412.743 1.072 1.123zm3.91 3.663q.875 0 1.585-.396a2.96 2.96 0 0 0 1.534-2.64v-3.564a.32.32 0 0 0-.165-.297l-1.254-.726v4.604a.7.7 0 0 1-.363.643l-3.119 1.799a3 3 0 0 0 1.783.577m.627-6.039V8.878L10.01 7.822 8.129 8.878v2.244l1.881 1.056zM7.057 5.859a.7.7 0 0 1 .363-.644l3.119-1.798a3 3 0 0 0-1.782-.578q-.874 0-1.584.396A2.96 2.96 0 0 0 6.05 4.324a3.07 3.07 0 0 0-.396 1.551v3.547q0 .199.165.314l1.237.726zm8.383 7.887q.825-.364 1.303-1.123.495-.758.495-1.65a3.15 3.15 0 0 0-.412-1.55q-.413-.743-1.073-1.123l-3.086-1.782q-.099-.065-.181-.049a.3.3 0 0 0-.165.05l-1.238.692 3.993 2.327a.6.6 0 0 1 .264.264.64.64 0 0 1 .1.363zm-3.317-8.382a.63.63 0 0 1 .726 0l3.135 1.831v-.297q0-.792-.396-1.501a2.86 2.86 0 0 0-1.105-1.155q-.71-.43-1.65-.43-.825 0-1.436.347L8.294 5.941a.36.36 0 0 0-.165.314v1.418z"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1 @@
<svg version="1.1" viewBox="0.0 0.0 96.0 96.0" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="g31e21232314_0_33.0"><path d="m0 0l96.0 0l0 96.0l-96.0 0l0 -96.0z" clip-rule="nonzero"/></clipPath><g clip-path="url(#g31e21232314_0_33.0)"><path fill="#d9d9d9" d="m41.04961 80.271324l1.8897629 0l0 2.3307114l-1.8897629 0z" fill-rule="evenodd"/><path fill="#d9d9d9" d="m42.221855 81.45145l1.8897629 0l0 2.3307037l-1.8897629 0z" fill-rule="evenodd"/><g filter="url(#shadowFilter-g31e21232314_0_33.1)"><use xlink:href="#g31e21232314_0_33.1" transform="matrix(1.0 0.0 0.0 1.0 0.0 2.0)"/></g><defs><filter id="shadowFilter-g31e21232314_0_33.1" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" stdDeviation="2.0" result="blur"/><feComponentTransfer in="blur" color-interpolation-filters="sRGB"><feFuncR type="linear" slope="0" intercept="0.0"/><feFuncG type="linear" slope="0" intercept="0.0"/><feFuncB type="linear" slope="0" intercept="0.0"/><feFuncA type="linear" slope="0.0" intercept="0"/></feComponentTransfer></filter></defs><g id="g31e21232314_0_33.1"><path fill="#d9d9d9" d="m42.22417 28.470434l0 55.307083l-27.653543 -55.307083z" fill-rule="evenodd"/></g><g filter="url(#shadowFilter-g31e21232314_0_33.2)"><use xlink:href="#g31e21232314_0_33.2" transform="matrix(1.0 0.0 0.0 1.0 0.0 2.0)"/></g><defs><filter id="shadowFilter-g31e21232314_0_33.2" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" stdDeviation="2.0" result="blur"/><feComponentTransfer in="blur" color-interpolation-filters="sRGB"><feFuncR type="linear" slope="0" intercept="0.0"/><feFuncG type="linear" slope="0" intercept="0.0"/><feFuncB type="linear" slope="0" intercept="0.0"/><feFuncA type="linear" slope="0.0" intercept="0"/></feComponentTransfer></filter></defs><g id="g31e21232314_0_33.2"><path fill="#d9d9d9" d="m42.223038 83.77752l21.729656 0l18.653545 -70.385826l-25.574802 13.461943z" fill-rule="evenodd"/></g><g filter="url(#shadowFilter-g31e21232314_0_33.3)"><use xlink:href="#g31e21232314_0_33.3" transform="matrix(1.0 0.0 0.0 1.0 0.0 2.0)"/></g><defs><filter id="shadowFilter-g31e21232314_0_33.3" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" stdDeviation="2.0" result="blur"/><feComponentTransfer in="blur" color-interpolation-filters="sRGB"><feFuncR type="linear" slope="0" intercept="0.0"/><feFuncG type="linear" slope="0" intercept="0.0"/><feFuncB type="linear" slope="0" intercept="0.0"/><feFuncA type="linear" slope="0.0" intercept="0"/></feComponentTransfer></filter></defs><g id="g31e21232314_0_33.3"><path fill="#fdb515" d="m41.0477 27.293962l0 55.30709l-27.653542 -55.30709z" fill-rule="evenodd"/></g><g filter="url(#shadowFilter-g31e21232314_0_33.4)"><use xlink:href="#g31e21232314_0_33.4" transform="matrix(1.0 0.0 0.0 1.0 0.0 2.0)"/></g><defs><filter id="shadowFilter-g31e21232314_0_33.4" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" stdDeviation="2.0" result="blur"/><feComponentTransfer in="blur" color-interpolation-filters="sRGB"><feFuncR type="linear" slope="0" intercept="0.0"/><feFuncG type="linear" slope="0" intercept="0.0"/><feFuncB type="linear" slope="0" intercept="0.0"/><feFuncA type="linear" slope="0.0" intercept="0"/></feComponentTransfer></filter></defs><g id="g31e21232314_0_33.4"><path fill="#30a2ff" d="m41.046566 82.60105l21.72966 0l18.653545 -70.385826l-25.574806 13.461943z" fill-rule="evenodd"/></g></g></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

View File

@@ -0,0 +1,56 @@
<template>
<span class="agent-provider-logo" :style="logoStyle" :aria-label="`${displayName || provider} logo`" role="img">
<img v-if="logo.src" class="agent-provider-logo__image" :src="logo.src" :alt="displayName || provider" />
<span v-else>{{ logo.mark }}</span>
</span>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getAgentProviderLogo } from '@/utils/agent-provider-logo';
const props = withDefaults(
defineProps<{
provider: string;
displayName?: string;
size?: number;
}>(),
{
displayName: '',
size: 16,
},
);
const logo = computed(() => getAgentProviderLogo(props.provider, props.displayName));
const logoStyle = computed(() => ({
width: `${props.size}px`,
height: `${props.size}px`,
minWidth: `${props.size}px`,
background: logo.value.background,
color: logo.value.color,
fontSize: `${Math.max(10, Math.floor(props.size * 0.48))}px`,
}));
</script>
<style scoped lang="scss">
.agent-provider-logo {
display: inline-flex;
align-items: center;
justify-content: center;
font-weight: 700;
line-height: 1;
letter-spacing: 0;
user-select: none;
overflow: hidden;
box-sizing: border-box;
vertical-align: middle;
flex: 0 0 auto;
}
.agent-provider-logo__image {
display: block;
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
</style>

View File

@@ -1,14 +1,9 @@
<template>
<MdEditor
previewOnly
:model-value="props.content"
:sanitize="sanitizeHtml"
:theme="isDarkTheme ? 'dark' : 'light'"
/>
<MdPreview :model-value="props.content" :sanitize="sanitizeHtml" :theme="isDarkTheme ? 'dark' : 'light'" />
</template>
<script lang="ts" setup>
import { MdEditor } from 'md-editor-v3';
import { MdPreview } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import DOMPurify from 'dompurify';

View File

@@ -974,6 +974,7 @@ const message = {
failedRequests: 'Failed Requests',
averageTokenPerRequest: 'Avg Tokens/Request',
callLogs: 'Call Logs',
usageKeywordPlaceholder: 'Search Request ID / model / upstream model / error message',
attemptChain: 'Attempt Chain',
attemptIndex: 'Call Order',
noAttemptDetails: 'This request hit once; no fallback details',

View File

@@ -988,6 +988,7 @@ const message = {
failedRequests: 'Solicitudes fallidas',
averageTokenPerRequest: 'Tokens promedio/solicitud',
callLogs: 'Registros de llamadas',
usageKeywordPlaceholder: 'Buscar Request ID / modelo / modelo upstream / mensaje de error',
attemptChain: 'Cadena de intentos',
attemptIndex: 'Orden de llamada',
noAttemptDetails: 'Esta solicitud acertó en el primer intento; no hay detalles de fallback',

View File

@@ -978,6 +978,7 @@ const message = {
failedRequests: '失敗リクエスト',
averageTokenPerRequest: '平均 Token/リクエスト',
callLogs: '呼び出しログ',
usageKeywordPlaceholder: 'Request ID / モデル / 上流モデル / エラーメッセージを検索',
attemptChain: '試行チェーン',
attemptIndex: '呼び出し順',
noAttemptDetails: 'このリクエストは 1 回で命中しましたfallback 明細はありません',

View File

@@ -962,6 +962,7 @@ const message = {
failedRequests: '실패한 요청',
averageTokenPerRequest: '평균 Token/요청',
callLogs: '호출 로그',
usageKeywordPlaceholder: 'Request ID / 모델 / 업스트림 모델 / 오류 메시지 검색',
attemptChain: '시도 체인',
attemptIndex: '호출 순서',
noAttemptDetails: ' 요청은 번에 적중했으며 fallback 상세가 없습니다',

View File

@@ -987,6 +987,7 @@ const message = {
failedRequests: 'Permintaan gagal',
averageTokenPerRequest: 'Purata Token/permintaan',
callLogs: 'Log panggilan',
usageKeywordPlaceholder: 'Cari Request ID / model / model upstream / mesej ralat',
attemptChain: 'Rantaian percubaan',
attemptIndex: 'Urutan panggilan',
noAttemptDetails: 'Permintaan ini berjaya sekali percubaan; tiada butiran fallback',

View File

@@ -983,6 +983,7 @@ const message = {
failedRequests: 'Requisições com falha',
averageTokenPerRequest: 'Média de Token/requisição',
callLogs: 'Logs de chamadas',
usageKeywordPlaceholder: 'Pesquisar Request ID / modelo / modelo upstream / mensagem de erro',
attemptChain: 'Cadeia de tentativas',
attemptIndex: 'Ordem de chamada',
noAttemptDetails: 'Esta requisição acertou na primeira tentativa; sem detalhes de fallback',

View File

@@ -977,6 +977,7 @@ const message = {
failedRequests: 'Неуспешные запросы',
averageTokenPerRequest: 'Среднее Token/запрос',
callLogs: 'Журнал вызовов',
usageKeywordPlaceholder: 'Поиск по Request ID / модели / upstream-модели / сообщению об ошибке',
attemptChain: 'Цепочка попыток',
attemptIndex: 'Порядок вызова',
noAttemptDetails: 'Запрос выполнен с первой попытки, деталей fallback нет',

View File

@@ -985,6 +985,7 @@ const message = {
failedRequests: 'Başarısız istekler',
averageTokenPerRequest: 'Ortalama Token/istek',
callLogs: 'Çağrı günlükleri',
usageKeywordPlaceholder: 'Request ID / model / upstream model / hata mesajı ara',
attemptChain: 'Deneme zinciri',
attemptIndex: 'Çağrı sırası',
noAttemptDetails: 'Bu istek tek denemede isabet etti; fallback ayrıntısı yok',

View File

@@ -922,6 +922,7 @@ const message = {
failedRequests: '失敗請求',
averageTokenPerRequest: '平均 Token/請求',
callLogs: '呼叫日誌',
usageKeywordPlaceholder: '搜尋 Request ID / 模型 / 上游模型 / 錯誤資訊',
attemptChain: '呼叫鏈路',
attemptIndex: '調用順序',
noAttemptDetails: '本次請求一次命中,無 fallback 明細',

View File

@@ -916,6 +916,7 @@ const message = {
failedRequests: '失败请求',
averageTokenPerRequest: '平均 Token/请求',
callLogs: '调用日志',
usageKeywordPlaceholder: '搜索 Request ID / 模型 / 上游模型 / 错误信息',
attemptChain: '调用链路',
attemptIndex: '调用顺序',
noAttemptDetails: '本次请求一次命中,无 fallback 明细',

View File

@@ -0,0 +1,168 @@
export interface AgentProviderLogo {
src?: string;
mark: string;
background: string;
color: string;
borderColor?: string;
source?: string;
}
const asset = (name: string) => new URL(`../assets/images/ai-providers/${name}`, import.meta.url).href;
const providerLogos: Record<string, AgentProviderLogo> = {
ollama: {
src: asset('ollama.webp'),
mark: 'OL',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://github.com/ollama/ollama/blob/main/docs/ollama-logo.svg',
},
vllm: {
src: asset('vllm.svg'),
mark: 'v',
background: '#ffffff',
color: '#4338ca',
borderColor: '#dcdfe6',
source: 'https://vllm.ai/vLLM-Logo.svg',
},
deepseek: {
src: asset('deepseek.png'),
mark: 'DS',
background: '#ffffff',
color: '#4d6bfe',
borderColor: '#dcdfe6',
source: 'https://cdn.deepseek.com/logo.png',
},
'bailian-coding-plan': {
src: asset('aliyun.webp'),
mark: 'QW',
background: '#ffffff',
color: '#ff6a00',
borderColor: '#dcdfe6',
source: 'https://www.alibabacloud.com/',
},
'ark-coding-plan': {
src: asset('volcengine.png'),
mark: 'AR',
background: '#ffffff',
color: '#1664ff',
borderColor: '#dcdfe6',
source: 'https://www.volcengine.com/',
},
zai: {
src: asset('zai.webp'),
mark: 'Z',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://z.ai/',
},
minimax: {
src: asset('minimax.ico'),
mark: 'MM',
background: '#ffffff',
color: '#2563eb',
borderColor: '#dcdfe6',
source: 'https://www.minimax.io/',
},
xiaomi: {
src: asset('xiaomi.ico'),
mark: 'MI',
background: '#ffffff',
color: '#ff6900',
borderColor: '#dcdfe6',
source: 'https://www.mi.com/favicon.ico',
},
kimi: {
src: asset('kimi.svg'),
mark: 'KM',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://moonshotai.github.io/Branding-Guide/',
},
'kimi-coding': {
src: asset('kimi.svg'),
mark: 'KC',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://moonshotai.github.io/Branding-Guide/',
},
openai: {
src: asset('openai.svg'),
mark: 'AI',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://openai.com/brand/',
},
openrouter: {
src: asset('openrouter.png'),
mark: 'OR',
background: '#ffffff',
color: '#101828',
borderColor: '#dcdfe6',
source: 'https://openrouter.ai/',
},
anthropic: {
src: asset('anthropic.png'),
mark: 'A',
background: '#ffffff',
color: '#141413',
borderColor: '#dcdfe6',
source: 'https://www.anthropic.com/',
},
gemini: {
src: asset('gemini.webp'),
mark: 'G',
background: '#ffffff',
color: '#1a73e8',
borderColor: '#dcdfe6',
source: 'https://gemini.google.com/',
},
moonshot: {
src: asset('kimi.svg'),
mark: 'MS',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://moonshotai.github.io/Branding-Guide/',
},
};
const fallbackLogo: AgentProviderLogo = {
mark: 'AI',
background: '#f5f7fa',
color: '#606266',
borderColor: '#dcdfe6',
};
const normalizeProvider = (provider?: string) =>
String(provider || '')
.trim()
.toLowerCase();
const buildFallbackMark = (provider?: string, displayName?: string) => {
const source = String(displayName || provider || '').trim();
const asciiWords = source.match(/[a-zA-Z0-9]+/g) || [];
if (asciiWords.length >= 2) {
return `${asciiWords[0][0]}${asciiWords[1][0]}`.toUpperCase();
}
if (asciiWords.length === 1) {
return asciiWords[0].slice(0, 2).toUpperCase();
}
return fallbackLogo.mark;
};
export const getAgentProviderLogo = (provider?: string, displayName?: string): AgentProviderLogo => {
const logo = providerLogos[normalizeProvider(provider)];
if (logo) {
return logo;
}
return {
...fallbackLogo,
mark: buildFallbackMark(provider, displayName),
};
};

View File

@@ -11,7 +11,12 @@
:key="item.value"
:label="item.label"
:value="item.value"
/>
>
<div class="provider-option">
<ProviderLogo :provider="item.value" :display-name="item.label" />
<span>{{ item.label }}</span>
</div>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="API Key" prop="apiKey">
@@ -88,6 +93,7 @@ import i18n from '@/lang';
import { getAgentProviderDisplayName } from '@/utils/agent';
import { MsgError } from '@/utils/message';
import { useGlobalStore } from '@/composables/useGlobalStore';
import ProviderLogo from '@/components/agent-provider-logo/index.vue';
const emit = defineEmits(['search']);
@@ -355,3 +361,19 @@ defineExpose({
open: openDrawer,
});
</script>
<style scoped lang="scss">
.provider-option {
display: inline-flex;
align-items: center;
gap: 6px;
min-width: 0;
white-space: nowrap;
span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>

View File

@@ -15,7 +15,13 @@
<el-table-column :label="$t('commons.table.name')" prop="name" min-width="200" />
<el-table-column :label="$t('aiTools.agents.provider')" prop="provider" width="200">
<template #default="{ row }">
{{ getAgentProviderDisplayName(row.provider, row.providerName) }}
<div class="provider-cell">
<ProviderLogo
:provider="row.provider"
:display-name="getAgentProviderDisplayName(row.provider, row.providerName)"
/>
<span>{{ getAgentProviderDisplayName(row.provider, row.providerName) }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="Base URL" prop="baseUrl" min-width="200" />
@@ -57,6 +63,7 @@ import { deleteAgentAccount, pageAgentAccounts } from '@/api/modules/ai';
import { AI } from '@/api/interface/ai';
import AddDialog from '@/views/ai/agents/model/add/index.vue';
import ModelPoolDialog from '@/views/ai/agents/model/pool/index.vue';
import ProviderLogo from '@/components/agent-provider-logo/index.vue';
import { ElMessageBox } from 'element-plus';
import i18n from '@/lang';
import { dateFormat } from '@/utils/date';
@@ -177,3 +184,19 @@ onMounted(async () => {
await search();
});
</script>
<style scoped lang="scss">
.provider-cell {
display: inline-flex;
align-items: center;
gap: 6px;
min-width: 0;
white-space: nowrap;
span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>