Softhub软件下载站实战开发(六):软件配置面板实现
在上一篇文章中,我们实现了分类模块。本文实现配置面板功能,并聚焦ai配置信息存储,并为后续配置信息拓展留足空间。
设计思路与核心功能
AI配置面板需要满足以下需求:
- 多提供商支持:支持OpenAI、DeepSeek、Ollama及自定义API
- 动态表单:根据不同提供商显示不同配置项
- 模型管理:自动获取可用模型列表
- 参数配置:温度、最大Token数等关键参数
- 本地存储:使用IndexedDB保存配置
实现详解
1. 多提供商支持与动态表单
<el-form-item label="AI 提供商" prop="provider">
<el-select v-model="aiConfig.provider" placeholder="请选择 AI 提供商" @change="handleProviderChange">
<el-option label="OpenAI" value="openai" />
<el-option label="DeepSeek" value="deepseek" />
<el-option label="Ollama" value="ollama" />
<el-option label="自定义" value="custom" />
</el-select>
</el-form-item>
根据选择的提供商动态显示/隐藏相关字段:
<el-form-item label="API Key" prop="apiKey" v-if="aiConfig.provider !== 'ollama'">
<!-- API Key输入框 -->
</el-form-item>
<el-form-item label="API 地址" prop="apiEndpoint" v-if="aiConfig.provider !== 'custom'">
<!-- API地址输入框 -->
</el-form-item>
<el-form-item label="自定义地址" prop="customEndpoint" v-if="aiConfig.provider === 'custom'">
<!-- 自定义地址输入框 -->
</el-form-item>
2. 模型管理
为不同提供商设置默认模型列表:
const defaultModels = {
openai: ['gpt-4', 'gpt-3.5-turbo'],
deepseek: ['deepseek-chat', 'deepseek-reasoner'],
ollama: []
};
对于Ollama提供商,动态获取本地模型列表:
const fetchOllamaModels = async () => {
loadingModels.value = true;
try {
const response = await fetch('http://localhost:11434/api/tags');
const data = await response.json();
availableModels.value = data.models.map(model => model.name);
} catch (error) {
ElMessage.error('获取 Ollama 模型列表失败');
availableModels.value = [];
} finally {
loadingModels.value = false;
}
};
3. 参数配置
温度参数使用滑块控制:
<el-form-item label="温度" prop="temperature">
<el-slider
v-model="aiConfig.temperature"
:min="0"
:max="1"
:step="0.1"
show-input
/>
</el-form-item>
最大Token数使用步进器控制:
<el-form-item label="最大长度" prop="maxTokens">
<el-input-number
v-model="aiConfig.maxTokens"
:min="100"
:max="4000"
:step="100"
/>
</el-form-item>
4. 数据持久化
使用IndexedDB存储配置:
需要安装idb库
npm install idb
const initDB = async () => {
try {
const db = await openDB('softhub', 1, {
upgrade(db) {
const store = db.createObjectStore('aiConfig', { keyPath: 'id' });
store.createIndex('current', 'id', { unique: true });
}
});
return db;
} catch (error) {
console.error('初始化数据库失败:', error);
throw error;
}
};
const loadConfig = async () => {
try {
const db = await initDB();
const config = await db.get('aiConfig', 'current');
if (config) {
Object.assign(aiConfig, config);
if (aiConfig.provider === 'ollama') {
await fetchOllamaModels();
} else if (aiConfig.provider) {
availableModels.value = defaultModels[aiConfig.provider];
}
}
} catch (error) {
console.error('加载配置失败:', error);
}
};
const handleSave = async () => {
try {
await aiFormRef.value.validate();
saving.value = true;
const db = await initDB();
const configToSave = {
id: 'current',
...aiConfig,
apiEndpoint: aiConfig.provider === 'custom' ?
aiConfig.customEndpoint :
aiConfig.apiEndpoint
};
await db.put('aiConfig', configToSave);
ElMessage.success('配置保存成功');
} catch (error) {
ElMessage.error('配置保存失败');
} finally {
saving.value = false;
}
};
布局与UI设计
1. 主页面布局
<template>
<div class="config-container">
<el-tabs v-model="activeTab" tab-position="left" class="config-tabs">
<el-tab-pane name="ai">
<template #label>
<el-icon><Connection /></el-icon>
<span>AI 配置</span>
</template>
<ai-config ref="aiConfigRef" />
</el-tab-pane>
</el-tabs>
</div>
</template>
2. 表单样式优化
.config-content {
max-width: 800px;
}
.config-form {
margin-top: 20px;
}
:deep(.el-form-item__label) {
font-weight: 500;
}
:deep(.el-button) {
padding: 8px 20px;
}
:deep(.el-button .el-icon) {
margin-right: 4px;
}
3. 标签页样式
.config-container {
padding: 20px;
height: calc(100vh - 40px);
background-color: #f5f7fa;
}
.config-tabs {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}
:deep(.el-tabs__header) {
margin: 0;
border-right: 1px solid #e4e7ed;
background-color: #f5f7fa;
}
:deep(.el-tabs__nav-wrap) {
width: 180px;
}
:deep(.el-tabs__item) {
height: 50px;
line-height: 50px;
padding: 0 20px;
font-size: 14px;
color: #606266;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
:deep(.el-tabs__item.is-active) {
background-color: #fff;
color: #409eff;
font-weight: 500;
}
页面效果
技术总结
- 动态表单渲染:根据选择的AI提供商动态显示/隐藏相关配置项
- 混合模型管理:结合预设模型列表和动态API获取
- 响应式数据绑定:使用Vue的响应式系统管理复杂表单状态
- 本地存储方案:IndexedDB提供可靠的客户端数据持久化
- 优雅的错误处理:对网络请求和数据库操作进行完善的错误处理
- 用户友好的UI:Element Plus组件提供一致且美观的用户体验
softhub系列往期文章