156 lines
3.1 KiB
Vue
156 lines
3.1 KiB
Vue
<script setup lang="ts">
|
|
import {computed} from 'vue';
|
|
|
|
import {ElImage} from 'element-plus';
|
|
|
|
import {
|
|
getIconByValue,
|
|
getProviderBadgeText,
|
|
isSvgString,
|
|
} from '#/views/ai/model/modelUtils/defaultIcon';
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
icon?: string;
|
|
providerName?: string;
|
|
providerType?: string;
|
|
size?: number;
|
|
}>(),
|
|
{
|
|
icon: '',
|
|
providerName: '',
|
|
providerType: '',
|
|
size: 40,
|
|
},
|
|
);
|
|
|
|
const presetIcon = computed(() => getIconByValue(props.providerType));
|
|
|
|
const resolvedSvg = computed(() => {
|
|
if (presetIcon.value && isSvgString(presetIcon.value)) {
|
|
return presetIcon.value;
|
|
}
|
|
|
|
return isSvgString(props.icon) ? props.icon : '';
|
|
});
|
|
|
|
const resolvedImage = computed(() => {
|
|
if (props.icon && !isSvgString(props.icon)) {
|
|
return props.icon;
|
|
}
|
|
|
|
return presetIcon.value && !isSvgString(presetIcon.value)
|
|
? presetIcon.value
|
|
: '';
|
|
});
|
|
|
|
const badgeText = computed(() =>
|
|
getProviderBadgeText(props.providerName, props.providerType),
|
|
);
|
|
|
|
const badgeStyle = computed(() => ({
|
|
width: `${props.size}px`,
|
|
height: `${props.size}px`,
|
|
}));
|
|
</script>
|
|
|
|
<template>
|
|
<div class="provider-badge" :style="badgeStyle" :aria-hidden="true">
|
|
<ElImage
|
|
v-if="resolvedImage"
|
|
:src="resolvedImage"
|
|
fit="contain"
|
|
class="provider-badge__image"
|
|
/>
|
|
<!-- eslint-disable vue/no-v-html -->
|
|
<div
|
|
v-else-if="resolvedSvg"
|
|
class="provider-badge__svg"
|
|
v-html="resolvedSvg"
|
|
></div>
|
|
<!-- eslint-enable vue/no-v-html -->
|
|
<div v-else class="provider-badge__fallback" :title="badgeText">
|
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
<circle cx="7" cy="7" r="2.5" />
|
|
<circle cx="17" cy="7" r="2.5" />
|
|
<circle cx="12" cy="17" r="2.5" />
|
|
<path d="M8.9 8.4L10.6 12" />
|
|
<path d="M15.1 8.4L13.4 12" />
|
|
<path d="M9.2 16h5.6" />
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.provider-badge {
|
|
display: inline-flex;
|
|
flex-shrink: 0;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
background: linear-gradient(
|
|
145deg,
|
|
hsl(var(--surface-contrast-soft) / 96%) 0%,
|
|
hsl(var(--surface-panel) / 98%) 100%
|
|
);
|
|
border: 1px solid hsl(var(--glass-border) / 58%);
|
|
border-radius: 14px;
|
|
box-shadow: 0 12px 26px -22px hsl(var(--foreground) / 30%);
|
|
}
|
|
|
|
.provider-badge__image,
|
|
.provider-badge__svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.provider-badge__image {
|
|
padding: 10%;
|
|
}
|
|
|
|
.provider-badge__image :deep(img) {
|
|
object-fit: contain;
|
|
}
|
|
|
|
.provider-badge__svg {
|
|
padding: 16%;
|
|
}
|
|
|
|
.provider-badge__svg :deep(svg) {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.provider-badge__fallback {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
color: hsl(var(--text-strong));
|
|
}
|
|
|
|
.provider-badge__fallback svg {
|
|
width: 58%;
|
|
height: 58%;
|
|
}
|
|
|
|
.provider-badge__fallback circle,
|
|
.provider-badge__fallback path {
|
|
stroke: currentcolor;
|
|
stroke-width: 1.8;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
}
|
|
|
|
.provider-badge__fallback circle {
|
|
fill: hsl(var(--surface-panel));
|
|
}
|
|
|
|
.provider-badge__fallback path {
|
|
fill: none;
|
|
}
|
|
</style>
|