feat: 优化设置面板和模型提供者组件的布局与样式

This commit is contained in:
Wenjie Zhang 2026-01-15 05:33:24 +08:00
parent 62685b7ffe
commit 673a7fdd75
3 changed files with 126 additions and 190 deletions

View File

@ -1,42 +1,56 @@
<template> <template>
<div class="basic-settings-section"> <div class="basic-settings-section">
<h3 class="section-title">检索配置</h3> <h3 class="section-title">检索配置</h3>
<div class="section"> <div class="settings-panel">
<div class="card card-select"> <div class="setting-row two-cols">
<span class="label">{{ items?.default_model?.des || '默认对话模型' }}</span> <div class="col-item">
<ModelSelectorComponent <div class="setting-label">{{ items?.default_model?.des || '默认对话模型' }}</div>
@select-model="handleChatModelSelect" <div class="setting-content">
:model_spec="configStore.config?.default_model" <ModelSelectorComponent
placeholder="请选择默认模型" @select-model="handleChatModelSelect"
/> :model_spec="configStore.config?.default_model"
placeholder="请选择默认模型"
/>
</div>
</div>
<div class="col-item">
<div class="setting-label">{{ items?.fast_model.des }}</div>
<div class="setting-content">
<ModelSelectorComponent
@select-model="handleFastModelSelect"
:model_spec="configStore.config?.fast_model"
placeholder="请选择模型"
/>
</div>
</div>
</div> </div>
<div class="card card-select"> <div class="setting-row two-cols">
<span class="label">{{ items?.fast_model.des }}</span> <div class="col-item">
<ModelSelectorComponent <div class="setting-label">{{ items?.embed_model.des }}</div>
@select-model="handleFastModelSelect" <div class="setting-content">
:model_spec="configStore.config?.fast_model" <EmbeddingModelSelector
placeholder="请选择模型" :value="configStore.config?.embed_model"
/> @change="handleChange('embed_model', $event)"
</div> style="width: 100%"
<div class="card card-select"> />
<span class="label">{{ items?.embed_model.des }}</span> </div>
<EmbeddingModelSelector </div>
:value="configStore.config?.embed_model" <div class="col-item">
@change="handleChange('embed_model', $event)" <div class="setting-label">{{ items?.reranker.des }}</div>
style="width: 320px" <div class="setting-content">
/> <a-select
</div> class="full-width"
<div class="card card-select"> :value="configStore.config?.reranker"
<span class="label">{{ items?.reranker.des }}</span> @change="handleChange('reranker', $event)"
<a-select style="width: 320px" placeholder="请选择重排序模型"
:value="configStore.config?.reranker" >
@change="handleChange('reranker', $event)" <a-select-option
> v-for="(name, idx) in rerankerChoices" :key="idx"
<a-select-option :value="name">{{ name }}
v-for="(name, idx) in rerankerChoices" :key="idx" </a-select-option>
:value="name">{{ name }} </a-select>
</a-select-option> </div>
</a-select> </div>
</div> </div>
</div> </div>
@ -195,7 +209,7 @@ const openLink = (url) => {
color: var(--gray-900); color: var(--gray-900);
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
margin: 24px 0 12px 0; margin: 24px 0 0 0;
padding-bottom: 8px; padding-bottom: 8px;
&:first-child { &:first-child {
@ -211,7 +225,6 @@ const openLink = (url) => {
} }
.section { .section {
margin-top: 10px;
background-color: var(--gray-0); background-color: var(--gray-0);
padding: 10px 16px; padding: 10px 16px;
border-radius: 8px; border-radius: 8px;
@ -221,6 +234,49 @@ const openLink = (url) => {
border: 1px solid var(--gray-150); border: 1px solid var(--gray-150);
} }
.settings-panel {
background-color: var(--gray-50);
border: 1px solid var(--gray-200);
border-radius: 8px;
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
}
.setting-row {
display: flex;
flex-direction: column;
gap: 8px;
&.two-cols {
flex-direction: row;
gap: 20px;
}
.col-item {
flex: 1;
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
}
}
.setting-label {
font-size: 13px;
font-weight: 500;
color: var(--gray-700);
}
.setting-content {
width: 100%;
.full-width {
width: 100%;
}
}
.card { .card {
display: flex; display: flex;
align-items: center; align-items: center;
@ -288,79 +344,4 @@ const openLink = (url) => {
} }
} }
} }
//
@media (max-width: 768px) {
.basic-settings-section {
.section {
padding: 12px;
}
.card {
flex-direction: column;
align-items: flex-start;
gap: 12px;
padding: 16px 0;
.label {
margin-right: 0;
margin-bottom: 8px;
}
&.card-select {
gap: 0px;
padding: 0;
.label {
margin-top: 0;
}
}
}
.services-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.service-link-card {
flex-direction: column;
align-items: flex-start;
gap: 12px;
min-height: auto;
padding: 12px;
.service-info {
margin-right: 0;
margin-bottom: 8px;
}
}
}
}
//
@media (max-width: 480px) {
.basic-settings-section {
.section-title {
font-size: 15px;
}
.card {
.label {
font-size: 14px;
min-width: 120px;
}
}
.service-link-card {
.service-info {
h4 {
font-size: 14px;
}
p {
font-size: 12px;
}
}
}
}
}
</style> </style>

View File

@ -103,19 +103,15 @@
</div> </div>
<div class="model-title-container"> <div class="model-title-container">
<h3>{{ modelNames[item].name }}</h3> <h3>{{ modelNames[item].name }}</h3>
<div class="provider-meta">
<span class="model-count">{{ modelNames[item].models?.length || 0 }} 个模型</span>
<span class="provider-id">{{ item }}</span>
</div>
</div> </div>
<div class="provider-actions"> <div class="provider-meta">
<a-button <a-button
type="text" type="text"
class="expand-button" class="expand-button"
@click.stop="openProviderConfig(item)" @click.stop="openProviderConfig(item)"
title="配置模型" title="配置模型"
> >
<SettingOutlined /> <SettingOutlined /> 已选 {{ modelNames[item].models?.length || 0 }} 个模型
</a-button> </a-button>
</div> </div>
</div> </div>
@ -798,7 +794,7 @@ const testCustomProvider = async (providerId, modelName) => {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 16px 20px; padding: 8px 12px;
background: var(--gray-25); background: var(--gray-25);
border-bottom: 1px solid var(--gray-200); border-bottom: 1px solid var(--gray-200);
@ -830,17 +826,16 @@ const testCustomProvider = async (providerId, modelName) => {
} }
.card-content { .card-content {
padding: 16px 20px; padding: 8px 12px;
.provider-details { .provider-details {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 12px; gap: 12px 8px;
.detail-item { .detail-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px;
.label { .label {
font-size: 12px; font-size: 12px;
@ -929,13 +924,6 @@ const testCustomProvider = async (providerId, modelName) => {
.model-icon { .model-icon {
filter: grayscale(0%); filter: grayscale(0%);
} }
.provider-meta {
.model-count {
color: var(--gray-600);
font-weight: 500;
}
}
} }
// provider // provider
@ -957,9 +945,9 @@ const testCustomProvider = async (providerId, modelName) => {
.card-header { .card-header {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 10px;
cursor: pointer; cursor: pointer;
padding: 8px 16px; padding: 6px 10px;
background: var(--gray-0); background: var(--gray-0);
.model-title-container { .model-title-container {
@ -973,28 +961,6 @@ const testCustomProvider = async (providerId, modelName) => {
font-weight: 600; font-weight: 600;
color: var(--gray-900); color: var(--gray-900);
} }
.provider-meta {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
.model-count {
color: var(--gray-600);
font-weight: 500;
}
.provider-id {
background: var(--gray-50);
color: var(--gray-900);
padding: 2px 6px;
border-radius: 4px;
font-size: 11px;
font-weight: 500;
font-family: 'Courier New', monospace;
}
}
} }
.model-url { .model-url {
@ -1009,21 +975,21 @@ const testCustomProvider = async (providerId, modelName) => {
} }
.model-icon { .model-icon {
width: 36px; width: 32px;
height: 36px; height: 32px;
border-radius: 6px; border-radius: 6px;
overflow: hidden; overflow: hidden;
filter: grayscale(100%); filter: grayscale(100%);
flex-shrink: 0; flex-shrink: 0;
background-color: white; background-color: white;
border: 1px solid var(--gray-200); // border: 1px solid var(--gray-200);
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: contain; object-fit: contain;
padding: 4px; padding: 4px;
border-radius: 6px; border-radius: 8px;
} }
&.available { &.available {
@ -1032,16 +998,16 @@ const testCustomProvider = async (providerId, modelName) => {
} }
.expand-button, .config-button { .expand-button, .config-button {
height: 32px; height: 28px;
width: 32px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 0; padding: 4px 6px;
cursor: pointer; cursor: pointer;
color: var(--gray-500); color: var(--gray-800);
border-radius: 6px; border-radius: 6px;
transition: all 0.2s ease; transition: all 0.2s ease;
font-size: 12px;
&:hover { &:hover {
background-color: var(--gray-50); background-color: var(--gray-50);
@ -1093,21 +1059,22 @@ const testCustomProvider = async (providerId, modelName) => {
.card-body { .card-body {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 12px; gap: 8px;
padding: 16px; padding: 10px;
padding-top: 4px;
// //
.card-models { .card-models {
width: 100%; width: 100%;
border-radius: 6px; border-radius: 6px;
border: 1px solid var(--gray-150); border: 1px solid var(--gray-150);
padding: 12px 16px; padding: 8px 12px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;
background: var(--gray-0); background: var(--gray-0);
min-height: 48px; // min-height: 48px;
.model_name { .model_name {
font-size: 14px; font-size: 14px;
@ -1156,7 +1123,7 @@ const testCustomProvider = async (providerId, modelName) => {
.modal-models-section { .modal-models-section {
.model-search { .model-search {
margin-bottom: 10px; margin-bottom: 10px;
padding: 0 6px; padding: 0;
.ant-input-affix-wrapper { .ant-input-affix-wrapper {
border-radius: 6px; border-radius: 6px;
@ -1177,6 +1144,7 @@ const testCustomProvider = async (providerId, modelName) => {
.modal-checkbox-item { .modal-checkbox-item {
display: inline-block; display: inline-block;
margin-bottom: 4px; margin-bottom: 4px;
margin-right: 4px;
padding: 4px 6px; padding: 4px 6px;
border-radius: 6px; border-radius: 6px;
background-color: var(--gray-0); background-color: var(--gray-0);
@ -1202,24 +1170,6 @@ const testCustomProvider = async (providerId, modelName) => {
} }
} }
//
@media (max-width: 768px) {
.model-provider-card {
margin-bottom: 10px;
.card-body {
grid-template-columns: 1fr;
gap: 8px;
padding: 10px;
}
.card-header {
padding: 10px;
gap: 8px;
}
}
}
// Simple Notice Styles // Simple Notice Styles
.simple-notice { .simple-notice {
padding: 8px 12px; padding: 8px 12px;

View File

@ -182,8 +182,9 @@ watch(() => props.visible, (newVal) => {
display: flex; display: flex;
height: 100%; height: 100%;
width: 100%; width: 100%;
gap: 6px;
@media (max-width: 768px) { @media (max-width: 900px) {
flex-direction: column; flex-direction: column;
} }
} }
@ -199,7 +200,7 @@ watch(() => props.visible, (newVal) => {
gap: 8px; gap: 8px;
flex-shrink: 0; flex-shrink: 0;
@media (max-width: 768px) { @media (max-width: 900px) {
display: none; display: none;
} }
@ -236,15 +237,19 @@ watch(() => props.visible, (newVal) => {
.settings-content-wrapper { .settings-content-wrapper {
flex: 1; flex: 1;
height: 100%; height: 100%;
/* background-color: #fff; SettingView seems to use default background */ max-width: calc(100% - 128px);
@media (max-width: 900px) {
max-width: 100%;
}
.settings-content { .settings-content {
padding: 0 20px; /* Matches SettingView .setting padding */ padding: 0; /* Matches SettingView .setting padding */
// margin-bottom: 40px; /* Matches SettingView .setting margin-bottom */ // margin-bottom: 40px; /* Matches SettingView .setting margin-bottom */
overflow-y: scroll; overflow-y: scroll;
height: 70vh; height: 70vh;
@media (max-width: 768px) { @media (max-width: 900px) {
height: 70vh; height: 70vh;
padding: 0px; padding: 0px;
} }
@ -268,7 +273,7 @@ watch(() => props.visible, (newVal) => {
padding: 0; padding: 0;
flex-shrink: 0; flex-shrink: 0;
@media (max-width: 768px) { @media (max-width: 900px) {
display: flex; display: flex;
} }