perf: 模型管理界面重做

This commit is contained in:
2026-03-11 20:33:04 +08:00
parent 219fa566ef
commit 373d7f8201
37 changed files with 4120 additions and 2108 deletions

View File

@@ -0,0 +1,155 @@
<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>