style(components): 调整组件样式和布局细节
This commit is contained in:
parent
e0f6b66ed1
commit
fbe85702a9
@ -178,7 +178,7 @@ const emit = defineEmits(['open-config', 'open-agent-modal']);
|
|||||||
const state = reactive({
|
const state = reactive({
|
||||||
...props.state,
|
...props.state,
|
||||||
debug_mode: computed(() => props.state.debug_mode ?? false),
|
debug_mode: computed(() => props.state.debug_mode ?? false),
|
||||||
isSidebarOpen: localStorage.getItem('chat_sidebar_open') === 'true' || true,
|
isSidebarOpen: localStorage.getItem('chat_sidebar_open', 'true') === 'true',
|
||||||
waitingServerResponse: false,
|
waitingServerResponse: false,
|
||||||
isProcessingRequest: false,
|
isProcessingRequest: false,
|
||||||
creatingNewChat: false,
|
creatingNewChat: false,
|
||||||
@ -226,7 +226,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 延迟移除初始渲染标记,防止切换动画
|
// 延迟移除初始渲染标记,防止切换动画
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
state.isInitialRender = false;
|
state.isInitialRender = false;
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -527,7 +527,7 @@ const toggleToolCall = (toolCallId) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ol, ul {
|
ol, ul {
|
||||||
padding-left: 1rem;
|
padding-left: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
cite {
|
cite {
|
||||||
|
|||||||
@ -178,8 +178,8 @@
|
|||||||
<div v-if="providerConfig.allModels.length === 0" class="modal-no-models">
|
<div v-if="providerConfig.allModels.length === 0" class="modal-no-models">
|
||||||
<a-alert v-if="!modelStatus[providerConfig.provider]" type="warning" message="请在 src/.env 中配置对应的 APIKEY,并重新启动服务" />
|
<a-alert v-if="!modelStatus[providerConfig.provider]" type="warning" message="请在 src/.env 中配置对应的 APIKEY,并重新启动服务" />
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<a-alert type="warning" message="该提供商暂未适配获取模型列表的方法,如果需要添加模型,请在 src/static/models.private.yml 中添加。" />
|
<a-alert type="warning" message="该提供商暂未适配获取模型列表的方法,如果需要添加模型,请在 src/static/models.private.yml 中添加。(如没有此文件,则需要手动创建一个)" />
|
||||||
<img src="@/assets/pics/guides/how-to-add-models.png" alt="添加模型指引" style="width: 100%; height: 100%;">
|
<img src="@/assets/pics/guides/how-to-add-models.png" alt="添加模型指引" style="width: 100%; height: 100%; margin-top: 16px;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -450,14 +450,12 @@ const filteredModels = computed(() => {
|
|||||||
border: 1px solid var(--gray-200);
|
border: 1px solid var(--gray-200);
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 16px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
// box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
|
transition: all 0.3s ease;
|
||||||
transition: all 0.2s ease;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
// box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
|
|
||||||
border-color: var(--gray-300);
|
border-color: var(--gray-300);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,11 +509,11 @@ const filteredModels = computed(() => {
|
|||||||
.card-header {
|
.card-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 12px 14px;
|
padding: 16px 20px;
|
||||||
background: white;
|
background: white;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--gray-50);
|
background: var(--gray-50);
|
||||||
@ -644,8 +642,8 @@ const filteredModels = computed(() => {
|
|||||||
.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: 10px;
|
gap: 12px;
|
||||||
padding: 12px;
|
padding: 16px;
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
|
|
||||||
// 普通模型卡片样式
|
// 普通模型卡片样式
|
||||||
@ -653,17 +651,17 @@ const filteredModels = computed(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: 1px solid var(--gray-200);
|
border: 1px solid var(--gray-200);
|
||||||
padding: 10px 12px;
|
padding: 12px 16px;
|
||||||
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: white;
|
background: white;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.3s ease;
|
||||||
min-height: 42px;
|
min-height: 48px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
border-color: var(--gray-400);
|
border-color: var(--gray-400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,17 +695,17 @@ const filteredModels = computed(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
padding: 10px 12px;
|
padding: 12px 16px;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-height: 64px;
|
min-height: 72px;
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: 1px solid var(--gray-200);
|
border: 1px solid var(--gray-200);
|
||||||
transition: all 0.2s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
|
||||||
border-color: var(--gray-400);
|
border-color: var(--gray-400);
|
||||||
|
|
||||||
.card-models__header .action {
|
.card-models__header .action {
|
||||||
|
|||||||
@ -135,9 +135,9 @@ const handleSelectModel = (provider, name) => {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less" scoped>
|
||||||
// 添加全局样式以确保滚动功能在dropdown内正常工作
|
// 将全局样式移到scoped中以避免样式污染
|
||||||
.ant-dropdown-menu {
|
:deep(.ant-dropdown-menu) {
|
||||||
&.scrollable-menu {
|
&.scrollable-menu {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
@ -1,212 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-card class="config-card" style="max-width: 960px">
|
|
||||||
<a-form layout="vertical">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in configList"
|
|
||||||
:key="index"
|
|
||||||
class="config-item"
|
|
||||||
>
|
|
||||||
<a-row :gutter="[16, 8]" align="middle">
|
|
||||||
<a-col :span="8">
|
|
||||||
<a-input
|
|
||||||
v-model:value="item.key"
|
|
||||||
placeholder="模型名称"
|
|
||||||
readonly
|
|
||||||
class="key-input"
|
|
||||||
/>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="14">
|
|
||||||
<a-input
|
|
||||||
v-model:value="item.value"
|
|
||||||
@change="updateValue(index)"
|
|
||||||
placeholder="模型本地路径"
|
|
||||||
class="value-input"
|
|
||||||
/>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="2" class="delete-btn-col">
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
danger
|
|
||||||
class="delete-btn"
|
|
||||||
@click="deleteConfig(index)"
|
|
||||||
>
|
|
||||||
<DeleteOutlined />
|
|
||||||
</a-button>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a-button block @click="addConfig" class="add-btn" :disabled="isAdding">
|
|
||||||
<PlusOutlined /> 添加路径映射
|
|
||||||
</a-button>
|
|
||||||
</a-form>
|
|
||||||
|
|
||||||
<a-modal
|
|
||||||
title="添加路径映射"
|
|
||||||
v-model:open="addConfigModalVisible"
|
|
||||||
@ok="confirmAddConfig"
|
|
||||||
class="config-modal"
|
|
||||||
>
|
|
||||||
<a-form layout="vertical">
|
|
||||||
<a-form-item label="模型名称(与Huggingface名称一致,比如 BAAI/bge-large-zh-v1.5" required>
|
|
||||||
<a-input
|
|
||||||
v-model:value="newConfig.key"
|
|
||||||
placeholder="请输入模型名称"
|
|
||||||
class="modal-input"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="模型本地路径(绝对路径,比如 /hdd/models/BAAI/bge-large-zh-v1.5)" required>
|
|
||||||
<a-input
|
|
||||||
v-model:value="newConfig.value"
|
|
||||||
placeholder="请输入模型本地路径"
|
|
||||||
class="modal-input"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</a-modal>
|
|
||||||
</a-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, computed, watch } from 'vue';
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
config: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:config']);
|
|
||||||
|
|
||||||
// 配置列表
|
|
||||||
const configList = reactive([]);
|
|
||||||
|
|
||||||
// 初始化配置列表
|
|
||||||
props.config && Object.entries(props.config).forEach(([key, value]) => {
|
|
||||||
configList.push({ key, value });
|
|
||||||
});
|
|
||||||
|
|
||||||
// 控制模态框显示
|
|
||||||
const addConfigModalVisible = ref(false);
|
|
||||||
const isAdding = ref(false); // 添加新的ref变量
|
|
||||||
|
|
||||||
// 新增配置项数据
|
|
||||||
const newConfig = ref({ key: '', value: '' });
|
|
||||||
|
|
||||||
// 添加配置
|
|
||||||
const addConfig = () => {
|
|
||||||
isAdding.value = true; // 设置添加状态
|
|
||||||
addConfigModalVisible.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 确认添加配置
|
|
||||||
const confirmAddConfig = () => {
|
|
||||||
if (newConfig.value.key === '' || newConfig.value.value === '') {
|
|
||||||
message.warning('键或值不能为空');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (configList.some(item => item.key === newConfig.value.key)) {
|
|
||||||
message.warning('键已存在');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
configList.push({ key: newConfig.value.key, value: newConfig.value.value });
|
|
||||||
addConfigModalVisible.value = false;
|
|
||||||
newConfig.value = { key: '', value: '' };
|
|
||||||
isAdding.value = false; // 重置添加状态
|
|
||||||
};
|
|
||||||
|
|
||||||
// 删除配置
|
|
||||||
const deleteConfig = (index) => {
|
|
||||||
configList.splice(index, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新值
|
|
||||||
const updateValue = (index) => {
|
|
||||||
// 值的更新实时反映在 configList 中,无需额外处理
|
|
||||||
};
|
|
||||||
|
|
||||||
// 将配置列表转换为对象
|
|
||||||
const configObject = computed(() => {
|
|
||||||
return configList.reduce((acc, item) => {
|
|
||||||
acc[item.key] = item.value;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听配置变化并传递回父组件
|
|
||||||
watch(configObject, (newValue) => {
|
|
||||||
emit('update:config', newValue);
|
|
||||||
}, { deep: true });
|
|
||||||
|
|
||||||
// 监听模态框关闭
|
|
||||||
watch(addConfigModalVisible, (newValue) => {
|
|
||||||
if (!newValue) {
|
|
||||||
isAdding.value = false; // 当模态框关闭时重置添加状态
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.config-card {
|
|
||||||
background-color: var(--gray-10);
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid var(--gray-300);
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-item {
|
|
||||||
border-bottom: 1px solid #f0f0f0;
|
|
||||||
padding: 12px 0;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-item:hover {
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-item:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-input {
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
border-color: #e8e8e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-btn-col {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-btn {
|
|
||||||
opacity: 0.6;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-btn:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-btn {
|
|
||||||
margin-top: 16px;
|
|
||||||
height: 40px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-input {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ant-modal-content) {
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ant-card-body) {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
<!-- 用户表单模态框 -->
|
<!-- 用户表单模态框 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="userManagement.modalVisible"
|
v-model:open="userManagement.modalVisible"
|
||||||
:title="userManagement.modalTitle"
|
:title="userManagement.modalTitle"
|
||||||
@ok="handleUserFormSubmit"
|
@ok="handleUserFormSubmit"
|
||||||
:confirmLoading="userManagement.loading"
|
:confirmLoading="userManagement.loading"
|
||||||
|
|||||||
@ -126,7 +126,6 @@ import {
|
|||||||
GlobalOutlined
|
GlobalOutlined
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import HeaderComponent from '@/components/HeaderComponent.vue';
|
import HeaderComponent from '@/components/HeaderComponent.vue';
|
||||||
import TableConfigComponent from '@/components/TableConfigComponent.vue';
|
|
||||||
import ModelProvidersComponent from '@/components/ModelProvidersComponent.vue';
|
import ModelProvidersComponent from '@/components/ModelProvidersComponent.vue';
|
||||||
import UserManagementComponent from '@/components/UserManagementComponent.vue';
|
import UserManagementComponent from '@/components/UserManagementComponent.vue';
|
||||||
import { notification, Button } from 'ant-design-vue';
|
import { notification, Button } from 'ant-design-vue';
|
||||||
@ -302,7 +301,6 @@ const openLink = (url) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
// box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
border: 1px solid var(--gray-200);
|
border: 1px solid var(--gray-200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,9 +308,12 @@ const openLink = (url) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
// padding: 12px 0;
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--gray-800);
|
||||||
|
|
||||||
button {
|
button {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
@ -325,13 +326,9 @@ const openLink = (url) => {
|
|||||||
|
|
||||||
.services-grid {
|
.services-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-link-card {
|
.service-link-card {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user