const express = require('express') const router = express.Router() const { AIModel } = require('../models') const { authMiddleware, requirePermission } = require('../middleware/auth') const ApiResponse = require('../utils/response') const logger = require('../utils/logger') // 所有路由都需要认证 router.use(authMiddleware) /** * 获取当前使用的模型(公开接口,用于AI问答) * GET /api/ai-model/current */ router.get('/current', async (req, res) => { try { const model = await AIModel.getCurrentModel() if (!model) { // 如果没有配置模型,返回环境变量中的默认配置 return ApiResponse.success(res, { name: '默认模型', modelId: process.env.OPENAI_MODEL || 'gpt-3.5-turbo', apiUrl: process.env.OPENAI_API_URL || 'https://api.openai.com/v1/chat/completions', apiKey: process.env.OPENAI_API_KEY || '', config: { temperature: 0.7, maxTokens: 800, topP: 1 } }) } // 返回模型信息(不返回API Key) return ApiResponse.success(res, { name: model.name, modelId: model.modelId, config: model.config }) } catch (error) { logger.error('获取当前模型失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 获取模型列表(管理后台) * GET /api/ai-model/list */ router.get('/list', requirePermission('dashboard:read'), async (req, res) => { try { const { page = 1, pageSize = 10, keyword = '' } = req.query const query = keyword ? { $or: [ { name: { $regex: keyword, $options: 'i' } }, { modelId: { $regex: keyword, $options: 'i' } } ]} : {} const [list, total] = await Promise.all([ AIModel.find(query) .sort({ isDefault: -1, priority: 1, createdAt: -1 }) .skip((page - 1) * pageSize) .limit(parseInt(pageSize)), AIModel.countDocuments(query) ]) return ApiResponse.success(res, { list, total, page: parseInt(page), pageSize: parseInt(pageSize) }) } catch (error) { logger.error('获取模型列表失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 获取所有启用的模型(下拉选择用) * GET /api/ai-model/active */ router.get('/active', requirePermission('dashboard:read'), async (req, res) => { try { const models = await AIModel.getActiveModels() return ApiResponse.success(res, { list: models.map(m => ({ _id: m._id, name: m.name, modelId: m.modelId, isDefault: m.isDefault })) }) } catch (error) { logger.error('获取启用模型失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 获取模型详情 * GET /api/ai-model/:id */ router.get('/:id', requirePermission('dashboard:read'), async (req, res) => { try { const { id } = req.params const model = await AIModel.findById(id) if (!model) { return ApiResponse.notFound(res, '模型不存在') } return ApiResponse.success(res, { model }) } catch (error) { logger.error('获取模型详情失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 创建模型 * POST /api/ai-model */ router.post('/', requirePermission('settings:write'), async (req, res) => { try { const { name, modelId, apiUrl, apiKey, description, config, priority } = req.body // 验证必填字段 if (!name || !modelId || !apiUrl || !apiKey) { return ApiResponse.error(res, '请填写所有必填字段', 400) } // 检查modelId是否已存在 const existingModel = await AIModel.findOne({ modelId }) if (existingModel) { return ApiResponse.error(res, '该模型ID已存在', 400) } const model = new AIModel({ name, modelId, apiUrl, apiKey, description, config, priority }) await model.save() logger.info('创建AI模型:', { name, modelId, admin: req.admin.username }) return ApiResponse.success(res, { message: '创建成功', model: { _id: model._id, name: model.name, modelId: model.modelId, isDefault: model.isDefault, isActive: model.isActive } }) } catch (error) { logger.error('创建模型失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 更新模型 * PUT /api/ai-model/:id */ router.put('/:id', requirePermission('settings:write'), async (req, res) => { try { const { id } = req.params const { name, modelId, apiUrl, apiKey, description, isActive, isDefault, config, priority } = req.body const model = await AIModel.findById(id) if (!model) { return ApiResponse.notFound(res, '模型不存在') } // 如果修改了modelId,检查是否与其他模型冲突 if (modelId && modelId !== model.modelId) { const existingModel = await AIModel.findOne({ modelId, _id: { $ne: id } }) if (existingModel) { return ApiResponse.error(res, '该模型ID已存在', 400) } } // 更新字段 if (name) model.name = name if (modelId) model.modelId = modelId if (apiUrl) model.apiUrl = apiUrl if (apiKey) model.apiKey = apiKey if (description !== undefined) model.description = description if (isActive !== undefined) model.isActive = isActive if (isDefault !== undefined) model.isDefault = isDefault if (config) model.config = { ...model.config, ...config } if (priority !== undefined) model.priority = priority await model.save() logger.info('更新AI模型:', { id, name: model.name, admin: req.admin.username }) return ApiResponse.success(res, { message: '更新成功', model: { _id: model._id, name: model.name, modelId: model.modelId, isDefault: model.isDefault, isActive: model.isActive } }) } catch (error) { logger.error('更新模型失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 删除模型 * DELETE /api/ai-model/:id */ router.delete('/:id', requirePermission('settings:write'), async (req, res) => { try { const { id } = req.params const model = await AIModel.findById(id) if (!model) { return ApiResponse.notFound(res, '模型不存在') } // 检查是否是唯一的默认模型 if (model.isDefault) { const defaultCount = await AIModel.countDocuments({ isDefault: true }) if (defaultCount <= 1) { return ApiResponse.error(res, '不能删除唯一的默认模型,请先设置其他默认模型', 400) } } await AIModel.findByIdAndDelete(id) logger.info('删除AI模型:', { id, name: model.name, admin: req.admin.username }) return ApiResponse.success(res, { message: '删除成功' }) } catch (error) { logger.error('删除模型失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 设置默认模型 * POST /api/ai-model/:id/set-default */ router.post('/:id/set-default', requirePermission('settings:write'), async (req, res) => { try { const { id } = req.params const model = await AIModel.findById(id) if (!model) { return ApiResponse.notFound(res, '模型不存在') } if (!model.isActive) { return ApiResponse.error(res, '不能将禁用模型设为默认', 400) } model.isDefault = true await model.save() logger.info('设置默认AI模型:', { id, name: model.name, admin: req.admin.username }) return ApiResponse.success(res, { message: '设置默认模型成功', model: { _id: model._id, name: model.name, modelId: model.modelId, isDefault: true } }) } catch (error) { logger.error('设置默认模型失败:', error) return ApiResponse.serverError(res, error.message) } }) /** * 初始化默认模型(从环境变量) * POST /api/ai-model/init-default */ router.post('/init-default', requirePermission('settings:write'), async (req, res) => { try { // 检查是否已有模型 const existingCount = await AIModel.countDocuments() if (existingCount > 0) { return ApiResponse.error(res, '已有模型配置,如需重新初始化请先删除现有模型', 400) } // 从环境变量创建默认模型 const defaultModel = new AIModel({ name: '默认模型', modelId: process.env.OPENAI_MODEL || 'gpt-3.5-turbo', apiUrl: process.env.OPENAI_API_URL || 'https://api.openai.com/v1/chat/completions', apiKey: process.env.OPENAI_API_KEY || '', description: '从环境变量初始化的默认模型', isDefault: true, isActive: true, priority: 0 }) await defaultModel.save() logger.info('初始化默认AI模型:', { admin: req.admin.username }) return ApiResponse.success(res, { message: '初始化默认模型成功', model: { _id: defaultModel._id, name: defaultModel.name, modelId: defaultModel.modelId, isDefault: true } }) } catch (error) { logger.error('初始化默认模型失败:', error) return ApiResponse.serverError(res, error.message) } }) module.exports = router