diff --git a/web/src/components/ChatComponent.vue b/web/src/components/ChatComponent.vue
index 6bba07d9..298411e9 100644
--- a/web/src/components/ChatComponent.vue
+++ b/web/src/components/ChatComponent.vue
@@ -17,29 +17,7 @@
-
-
-
-
- {{ configStore.config?.model_name }}
-
- {{ configStore.config?.model_provider }}
-
-
-
-
-
+
@@ -362,120 +112,26 @@ import {
ReloadOutlined,
SettingOutlined,
CodeOutlined,
- ExceptionOutlined,
FolderOutlined,
- DeleteOutlined,
- EditOutlined,
- InfoCircleOutlined,
- DownOutlined,
- UpOutlined,
- LoadingOutlined,
- UpCircleOutlined,
- DownCircleOutlined,
- UserOutlined,
- PlusOutlined
+ UserOutlined
} 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';
-import { modelIcons } from '@/utils/modelIcon'
import { systemConfigApi } from '@/apis/admin_api'
-import { chatApi } from '@/apis/auth_api'
-
const configStore = useConfigStore()
const userStore = useUserStore()
const items = computed(() => configStore.config._config_items)
-const modelNames = computed(() => configStore.config?.model_names)
-const modelStatus = computed(() => configStore.config?.model_provider_status)
-const modelProvider = computed(() => configStore.config?.model_provider)
const isNeedRestart = ref(false)
-const customModel = reactive({
- modelTitle: '添加自定义模型',
- visible: false,
- custom_id: '',
- name: '',
- api_key: '',
- api_base: '',
- edit_type: 'add',
-})
-const providerConfig = reactive({
- visible: false,
- provider: '',
- providerName: '',
- models: [],
- allModels: [], // 所有可用的模型
- selectedModels: [], // 用户选择的模型
- loading: false,
-})
const state = reactive({
loading: false,
section: 'base',
windowWidth: window?.innerWidth || 0
})
-// 用户管理相关状态
-const userManagement = reactive({
- loading: false,
- users: [],
- error: null,
- modalVisible: false,
- modalTitle: '添加用户',
- editMode: false,
- editUserId: null,
- form: {
- username: '',
- password: '',
- confirmPassword: '',
- role: 'user' // 默认角色
- },
- displayPasswordFields: true, // 编辑时是否显示密码字段
-})
-
-// 筛选 modelStatus 中为真的key
-const modelKeys = computed(() => {
- return Object.keys(modelStatus.value || {}).filter(key => modelStatus.value?.[key])
-})
-
-// 监听密码字段显示状态变化
-watch(() => userManagement.displayPasswordFields, (newVal) => {
- // 当取消显示密码字段时,清空密码输入
- if (!newVal) {
- userManagement.form.password = ''
- userManagement.form.confirmPassword = ''
- }
-})
-
-const notModelKeys = computed(() => {
- return Object.keys(modelStatus.value || {}).filter(key => !modelStatus.value?.[key])
-})
-
-// 模型展开状态管理
-const expandedModels = reactive({})
-
-// 监听 modelKeys 变化,确保新添加的模型也是默认展开状态
-watch(modelKeys, (newKeys) => {
- newKeys.forEach(key => {
- if (expandedModels[key] === undefined) {
- expandedModels[key] = true
- }
- })
-}, { immediate: true })
-
-// 切换展开状态的方法
-const toggleExpand = (item) => {
- expandedModels[item] = !expandedModels[item]
-}
-
-const generateRandomHash = (length) => {
- let chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
- let hash = '';
- for (let i = 0; i < length; i++) {
- hash += chars.charAt(Math.floor(Math.random() * chars.length));
- }
- return hash;
-}
-
const handleModelLocalPathsUpdate = (config) => {
handleChange('model_local_paths', config)
}
@@ -525,71 +181,6 @@ const handleChanges = (items) => {
configStore.setConfigValues(items)
}
-const handleAddOrEditCustomModel = async () => {
- if (!customModel.name || !customModel.api_base) {
- message.error('请填写完整的模型名称和API Base信息。')
- return
- }
-
- let custom_models = configStore.config.custom_models || [];
-
- const model_info = {
- custom_id: customModel.custom_id || `${customModel.name}-${generateRandomHash(4)}`,
- name: customModel.name,
- api_key: customModel.api_key,
- api_base: customModel.api_base,
- }
-
- if (customModel.edit_type === 'add') {
- if (custom_models.find(item => item.custom_id === customModel.custom_id)) {
- message.error('模型ID已存在')
- return
- }
- custom_models.push(model_info)
- } else {
- // 如果 custom_id 相同,则更新
- custom_models = custom_models.map(item => item.custom_id === customModel.custom_id ? model_info : item);
- }
-
- customModel.visible = false;
- await configStore.setConfigValue('custom_models', custom_models);
- message.success(customModel.edit_type === 'add' ? '模型添加成功' : '模型修改成功');
-}
-
-const handleDeleteCustomModel = (custom_id) => {
- const updatedModels = configStore.config.custom_models.filter(item => item.custom_id !== custom_id);
- configStore.setConfigValue('custom_models', updatedModels);
-}
-
-const prepareToEditCustomModel = (item) => {
- customModel.modelTitle = '编辑自定义模型'
- customModel.custom_id = item.custom_id
- customModel.visible = true
- customModel.edit_type = 'edit'
- customModel.name = item.name
- customModel.api_key = item.api_key
- customModel.api_base = item.api_base
-}
-
-const prepareToAddCustomModel = () => {
- customModel.modelTitle = '添加自定义模型'
- customModel.edit_type = 'add'
- customModel.visible = true
- clearCustomModel()
-}
-
-const clearCustomModel = () => {
- customModel.custom_id = ''
- customModel.name = ''
- customModel.api_key = ''
- customModel.api_base = ''
-}
-
-const handleCancelCustomModel = () => {
- clearCustomModel()
- customModel.visible = false
-}
-
const updateWindowWidth = () => {
state.windowWidth = window?.innerWidth || 0
}
@@ -620,310 +211,6 @@ const sendRestart = () => {
message.error({ content: `重启失败: ${error.message}`, key: "restart", duration: 2 });
});
}
-
-// 获取模型提供商的模型列表
-const fetchProviderModels = (provider) => {
- providerConfig.loading = true;
- chatApi.getProviderModels(provider)
- .then(data => {
- console.log(`${provider} 模型列表:`, data);
-
- // 处理各种可能的API返回格式
- let modelsList = [];
-
- // 情况1: { data: [...] }
- if (data.data && Array.isArray(data.data)) {
- modelsList = data.data;
- }
- // 情况2: { models: [...] } (字符串数组)
- else if (data.models && Array.isArray(data.models)) {
- modelsList = data.models.map(model => typeof model === 'string' ? { id: model } : model);
- }
- // 情况3: { models: { data: [...] } }
- else if (data.models && data.models.data && Array.isArray(data.models.data)) {
- modelsList = data.models.data;
- }
-
- console.log("处理后的模型列表:", modelsList);
- providerConfig.allModels = modelsList;
- providerConfig.loading = false;
- })
- .catch(error => {
- console.error(`获取${provider}模型列表失败:`, error);
- message.error({ content: `获取${modelNames.value[provider].name}模型列表失败`, duration: 2 });
- providerConfig.loading = false;
- });
-}
-
-const openProviderConfig = (provider) => {
- providerConfig.provider = provider;
- providerConfig.providerName = modelNames.value[provider].name;
- providerConfig.allModels = [];
- providerConfig.visible = true;
- providerConfig.loading = true;
-
- // 获取当前选择的模型作为初始选中值
- const currentModels = modelNames.value[provider]?.models || [];
- providerConfig.selectedModels = [...currentModels];
-
- // 获取所有可用模型
- fetchProviderModels(provider);
-}
-
-const saveProviderConfig = async () => {
- if (!modelStatus.value[providerConfig.provider]) {
- message.error('请在 src/.env 中配置对应的 APIKEY,并重新启动服务')
- return
- }
-
- message.loading({ content: '保存配置中...', key: 'save-config', duration: 0 });
-
- try {
- // 发送选择的模型列表到后端
- const data = await chatApi.updateProviderModels(providerConfig.provider, providerConfig.selectedModels);
- console.log('更新后的模型列表:', data.models);
-
- message.success({ content: '模型配置已保存!', key: 'save-config', duration: 2 });
-
- // 关闭弹窗
- providerConfig.visible = false;
-
- // 刷新配置
- configStore.refreshConfig();
-
- } catch (error) {
- console.error('保存配置失败:', error);
- message.error({ content: '保存配置失败: ' + error.message, key: 'save-config', duration: 2 });
- }
-}
-
-const cancelProviderConfig = () => {
- providerConfig.visible = false;
-}
-
-// 获取用户列表
-const fetchUsers = async () => {
- try {
- userManagement.loading = true
- const users = await userStore.getUsers()
- userManagement.users = users
- userManagement.error = null
- } catch (error) {
- console.error('获取用户列表失败:', error)
- userManagement.error = '获取用户列表失败'
- } finally {
- userManagement.loading = false
- }
-}
-
-// 打开添加用户模态框
-const showAddUserModal = () => {
- userManagement.modalTitle = '添加用户'
- userManagement.editMode = false
- userManagement.editUserId = null
- userManagement.form = {
- username: '',
- password: '',
- confirmPassword: '',
- role: 'user' // 默认角色为普通用户
- }
- userManagement.displayPasswordFields = true
- userManagement.modalVisible = true
-}
-
-// 打开编辑用户模态框
-const showEditUserModal = (user) => {
- userManagement.modalTitle = '编辑用户'
- userManagement.editMode = true
- userManagement.editUserId = user.id
- userManagement.form = {
- username: user.username,
- password: '',
- confirmPassword: '',
- role: user.role
- }
- userManagement.displayPasswordFields = true // 默认显示密码字段
- userManagement.modalVisible = true
-}
-
-// 处理用户表单提交
-const handleUserFormSubmit = async () => {
- try {
- // 简单验证
- if (!userManagement.form.username) {
- notification.error({ message: '用户名不能为空' })
- return
- }
-
- if (userManagement.displayPasswordFields) {
- if (!userManagement.form.password) {
- notification.error({ message: '密码不能为空' })
- return
- }
-
- if (userManagement.form.password !== userManagement.form.confirmPassword) {
- notification.error({ message: '两次输入的密码不一致' })
- return
- }
- }
-
- userManagement.loading = true
-
- // 根据模式决定创建还是更新用户
- if (userManagement.editMode) {
- // 创建更新数据对象
- const updateData = {
- username: userManagement.form.username,
- role: userManagement.form.role
- }
-
- // 如果显示了密码字段并且填写了密码,才更新密码
- if (userManagement.displayPasswordFields && userManagement.form.password) {
- updateData.password = userManagement.form.password
- }
-
- await userStore.updateUser(userManagement.editUserId, updateData)
- notification.success({ message: '用户更新成功' })
- } else {
- await userStore.createUser({
- username: userManagement.form.username,
- password: userManagement.form.password,
- role: userManagement.form.role
- })
- notification.success({ message: '用户创建成功' })
- }
-
- // 重新获取用户列表
- await fetchUsers()
- userManagement.modalVisible = false
- } catch (error) {
- console.error('用户操作失败:', error)
- notification.error({
- message: '操作失败',
- description: error.message || '请稍后重试'
- })
- } finally {
- userManagement.loading = false
- }
-}
-
-// 切换是否显示密码字段(编辑用户时使用)
-const togglePasswordFields = () => {
- userManagement.displayPasswordFields = !userManagement.displayPasswordFields
- if (!userManagement.displayPasswordFields) {
- userManagement.form.password = ''
- userManagement.form.confirmPassword = ''
- }
-}
-
-// 删除用户
-const confirmDeleteUser = (user) => {
- // 自己不能删除自己
- if (user.id === userStore.userId) {
- notification.error({ message: '不能删除自己的账户' })
- return
- }
-
- // 确认对话框
- const { modal } = notification
-
- modal.confirm({
- title: '确认删除用户',
- content: `确定要删除用户 "${user.username}" 吗?此操作不可撤销。`,
- okText: '删除',
- okType: 'danger',
- cancelText: '取消',
- async onOk() {
- try {
- userManagement.loading = true
- await userStore.deleteUser(user.id)
- notification.success({ message: '用户删除成功' })
- // 重新获取用户列表
- await fetchUsers()
- } catch (error) {
- console.error('删除用户失败:', error)
- notification.error({
- message: '删除失败',
- description: error.message || '请稍后重试'
- })
- } finally {
- userManagement.loading = false
- }
- }
- })
-}
-
-// 在组件挂载时,如果选择了用户管理部分,则获取用户列表
-const loadUserManagement = async () => {
- if (state.section === 'user') {
- await fetchUsers()
- }
-}
-
-// 监听部分切换
-watch(() => state.section, async (newSection) => {
- if (newSection === 'user') {
- await fetchUsers()
- }
-})
-
-// 用户表格列定义
-const userColumns = [
- {
- title: 'ID',
- dataIndex: 'id',
- key: 'id',
- width: 80
- },
- {
- title: '用户名',
- dataIndex: 'username',
- key: 'username'
- },
- {
- title: '角色',
- dataIndex: 'role',
- key: 'role',
- width: 120
- },
- {
- title: '创建时间',
- dataIndex: 'created_at',
- key: 'created_at',
- width: 180
- },
- {
- title: '最后登录',
- dataIndex: 'last_login',
- key: 'last_login',
- width: 180
- },
- {
- title: '操作',
- key: 'action',
- width: 120
- }
-]
-
-// 角色显示辅助函数
-const getRoleLabel = (role) => {
- switch (role) {
- case 'superadmin': return '超级管理员'
- case 'admin': return '管理员'
- case 'user': return '普通用户'
- default: return role
- }
-}
-
-// 角色标签颜色
-const getRoleColor = (role) => {
- switch (role) {
- case 'superadmin': return 'red'
- case 'admin': return 'blue'
- case 'user': return 'green'
- default: return 'default'
- }
-}