style(components): 调整组件样式和布局细节

This commit is contained in:
Wenjie Zhang 2025-08-24 18:54:54 +08:00
parent e0f6b66ed1
commit fbe85702a9
7 changed files with 28 additions and 245 deletions

View File

@ -178,7 +178,7 @@ const emit = defineEmits(['open-config', 'open-agent-modal']);
const state = reactive({
...props.state,
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,
isProcessingRequest: false,
creatingNewChat: false,
@ -226,7 +226,7 @@ onMounted(() => {
//
setTimeout(() => {
state.isInitialRender = false;
state.isInitialRender = false;
}, 300);
});

View File

@ -527,7 +527,7 @@ const toggleToolCall = (toolCallId) => {
}
ol, ul {
padding-left: 1rem;
padding-left: 1.2rem;
}
cite {

View File

@ -178,8 +178,8 @@
<div v-if="providerConfig.allModels.length === 0" class="modal-no-models">
<a-alert v-if="!modelStatus[providerConfig.provider]" type="warning" message="请在 src/.env 中配置对应的 APIKEY并重新启动服务" />
<div v-else>
<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%;">
<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%; margin-top: 16px;">
</div>
</div>
</div>
@ -450,14 +450,12 @@ const filteredModels = computed(() => {
border: 1px solid var(--gray-200);
background-color: white;
border-radius: 8px;
margin-bottom: 12px;
margin-bottom: 16px;
padding: 0;
// box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
transition: all 0.2s ease;
transition: all 0.3s ease;
overflow: hidden;
&:hover {
// box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
border-color: var(--gray-300);
}
@ -511,11 +509,11 @@ const filteredModels = computed(() => {
.card-header {
display: flex;
align-items: center;
gap: 10px;
gap: 12px;
cursor: pointer;
padding: 12px 14px;
padding: 16px 20px;
background: white;
transition: all 0.2s ease;
transition: all 0.3s ease;
&:hover {
background: var(--gray-50);
@ -644,8 +642,8 @@ const filteredModels = computed(() => {
.card-body {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 10px;
padding: 12px;
gap: 12px;
padding: 16px;
background: #fafafa;
//
@ -653,17 +651,17 @@ const filteredModels = computed(() => {
width: 100%;
border-radius: 6px;
border: 1px solid var(--gray-200);
padding: 10px 12px;
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
background: white;
transition: all 0.2s ease;
min-height: 42px;
transition: all 0.3s ease;
min-height: 48px;
&: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);
}
@ -697,17 +695,17 @@ const filteredModels = computed(() => {
display: flex;
flex-direction: column;
align-items: stretch;
padding: 10px 12px;
padding: 12px 16px;
gap: 8px;
cursor: pointer;
min-height: 64px;
min-height: 72px;
background: white;
border-radius: 6px;
border: 1px solid var(--gray-200);
transition: all 0.2s ease;
transition: all 0.3s ease;
&: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);
.card-models__header .action {

View File

@ -135,9 +135,9 @@ const handleSelectModel = (provider, name) => {
}
</style>
<style lang="less">
// dropdown
.ant-dropdown-menu {
<style lang="less" scoped>
// scoped
:deep(.ant-dropdown-menu) {
&.scrollable-menu {
max-height: 300px;
overflow-y: auto;

View File

@ -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>

View File

@ -76,7 +76,7 @@
<!-- 用户表单模态框 -->
<a-modal
v-model:visible="userManagement.modalVisible"
v-model:open="userManagement.modalVisible"
:title="userManagement.modalTitle"
@ok="handleUserFormSubmit"
:confirmLoading="userManagement.loading"

View File

@ -126,7 +126,6 @@ import {
GlobalOutlined
} from '@ant-design/icons-vue';
import HeaderComponent from '@/components/HeaderComponent.vue';
import TableConfigComponent from '@/components/TableConfigComponent.vue';
import ModelProvidersComponent from '@/components/ModelProvidersComponent.vue';
import UserManagementComponent from '@/components/UserManagementComponent.vue';
import { notification, Button } from 'ant-design-vue';
@ -302,7 +301,6 @@ const openLink = (url) => {
display: flex;
flex-direction: column;
gap: 16px;
// box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border: 1px solid var(--gray-200);
}
@ -310,9 +308,12 @@ const openLink = (url) => {
display: flex;
align-items: center;
justify-content: space-between;
// padding: 12px 0;
.label {
margin-right: 20px;
font-weight: 500;
color: var(--gray-800);
button {
margin-left: 10px;
@ -325,13 +326,9 @@ const openLink = (url) => {
.services-grid {
display: grid;
grid-template-columns: 1fr;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 16px;
margin-top: 20px;
@media (min-width: 768px) {
grid-template-columns: repeat(2, 1fr);
}
}
.service-link-card {