|
|
@@ -4,7 +4,6 @@
|
|
|
<a-tabs v-model:active-key="activeTab" class="ai-model__tabs" size="small" destroy-inactive-tab-pane>
|
|
|
<template #rightExtra>
|
|
|
<div class="ai-topbar__actions">
|
|
|
- <span class="ai-topbar__meta ai-model__summary">{{ summary }}</span>
|
|
|
<a-button :loading="loading" @click="load">
|
|
|
<template #icon><Icon icon="mdi:refresh" :size="14" /></template>
|
|
|
刷新
|
|
|
@@ -22,8 +21,6 @@
|
|
|
<span class="ai-model__tab-count">{{ listOf(tab.key).length }}</span>
|
|
|
</template>
|
|
|
|
|
|
- <div class="ai-model__hint">{{ tab.hint }}</div>
|
|
|
-
|
|
|
<a-spin :spinning="loading">
|
|
|
<div v-if="listOf(tab.key).length" class="ai-model__grid">
|
|
|
<article v-for="record in listOf(tab.key)" :key="record.id" class="ai-model__card">
|
|
|
@@ -47,7 +44,6 @@
|
|
|
</div>
|
|
|
|
|
|
<div class="ai-model__card-meta">
|
|
|
- <span class="ai-model__mono">{{ maskKey(record.apiKey) }}</span>
|
|
|
<span class="ai-model__mono ai-model__ellipsis" :title="record.baseUrl">
|
|
|
{{ record.baseUrl || '—' }}
|
|
|
</span>
|
|
|
@@ -118,20 +114,11 @@
|
|
|
interface ModelTab {
|
|
|
key: ModelTypeKey;
|
|
|
label: string;
|
|
|
- hint: string;
|
|
|
}
|
|
|
|
|
|
const TABS: ModelTab[] = [
|
|
|
- {
|
|
|
- key: 'llm',
|
|
|
- label: '对话模型',
|
|
|
- hint: '对话模型用于驱动 AI 对话与分析推理。默认对话模型会在新建会话时自动绑定,会话中也可随时切换。API Key 仅用于服务端调用模型,前端不会用于任何直连请求。',
|
|
|
- },
|
|
|
- {
|
|
|
- key: 'embedding',
|
|
|
- label: '向量模型',
|
|
|
- hint: '向量模型用于把表结构转成向量以支持语义检索,不参与对话。默认向量模型在构建表结构索引时使用,切换默认后新构建的索引将使用新模型。',
|
|
|
- },
|
|
|
+ { key: 'llm', label: '对话模型' },
|
|
|
+ { key: 'embedding', label: '向量模型' },
|
|
|
];
|
|
|
|
|
|
const models = ref<AiModel[]>([]);
|
|
|
@@ -151,20 +138,6 @@
|
|
|
return key === 'embedding' ? embeddingModels.value : llmModels.value;
|
|
|
}
|
|
|
|
|
|
- function defaultOf(key: ModelTypeKey) {
|
|
|
- return listOf(key).find((m) => m.defaultModel);
|
|
|
- }
|
|
|
-
|
|
|
- const summary = computed(() => {
|
|
|
- if (!models.value.length) return '尚未配置模型';
|
|
|
- const parts = [`${models.value.length} 个模型`];
|
|
|
- parts.push(`默认对话:${defaultOf('llm')?.name || defaultOf('llm')?.modelId || '未设置'}`);
|
|
|
- if (embeddingModels.value.length) {
|
|
|
- parts.push(`默认向量:${defaultOf('embedding')?.name || defaultOf('embedding')?.modelId || '未设置'}`);
|
|
|
- }
|
|
|
- return parts.join(' · ');
|
|
|
- });
|
|
|
-
|
|
|
/**
|
|
|
* 状态展示:后端 StatusEnum 为 ACTIVE / SUSPENDED / ARCHIVED / DISABLED / DELETED
|
|
|
* (DELETED 已被列表接口过滤,不会出现)
|
|
|
@@ -271,13 +244,6 @@
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
-
|
|
|
- /** API Key 脱敏展示 */
|
|
|
- function maskKey(key?: string) {
|
|
|
- if (!key) return '—';
|
|
|
- if (key.length <= 8) return '••••••';
|
|
|
- return `${key.slice(0, 4)}••••${key.slice(-4)}`;
|
|
|
- }
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
@@ -320,14 +286,6 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* 摘要与页签同在一行,过长时限宽省略,避免把页签挤进溢出下拉 */
|
|
|
- &__summary {
|
|
|
- max-width: 360px;
|
|
|
- overflow: hidden;
|
|
|
- white-space: nowrap;
|
|
|
- text-overflow: ellipsis;
|
|
|
- }
|
|
|
-
|
|
|
&__tab-count {
|
|
|
display: inline-block;
|
|
|
min-width: 18px;
|
|
|
@@ -342,21 +300,6 @@
|
|
|
border-radius: 999px;
|
|
|
}
|
|
|
|
|
|
- &__hint {
|
|
|
- margin-bottom: var(--ai-sp-2);
|
|
|
- padding: var(--ai-sp-3);
|
|
|
- font-size: 12.5px;
|
|
|
- line-height: 1.75;
|
|
|
- color: var(--ai-text-2);
|
|
|
- background: var(--ai-primary-softer);
|
|
|
- border-left: 3px solid fade(@primary-color, 45%);
|
|
|
- border-radius: 0 var(--ai-radius-sm) var(--ai-radius-sm) 0;
|
|
|
-
|
|
|
- b {
|
|
|
- color: var(--ai-text);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/* 卡片网格:间距取分析页那一档(8px);圆角比页面外壳(12px)低一档,用 --ai-radius(8px) */
|
|
|
&__grid {
|
|
|
display: grid;
|